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,fname,&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, fname);
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 Get a level dependent lanman2 dir entry.
1200 ****************************************************************************/
1202 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1203 connection_struct *conn,
1205 const char *path_mask,
1208 int requires_resume_key,
1213 int space_remaining,
1215 bool *got_exact_match,
1216 int *last_entry_off,
1217 struct ea_list *name_list)
1221 SMB_STRUCT_STAT sbuf;
1222 const char *mask = NULL;
1223 char *pathreal = NULL;
1224 const char *fname = NULL;
1225 char *p, *q, *pdata = *ppdata;
1229 SMB_OFF_T file_size = 0;
1230 SMB_BIG_UINT allocation_size = 0;
1232 struct timespec mdate_ts, adate_ts, create_date_ts;
1233 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1235 char *last_entry_ptr;
1237 uint32 nt_extmode; /* Used for NT connections instead of mode */
1238 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1239 bool check_mangled_names = lp_manglednames(conn->params);
1240 char mangled_name[13]; /* mangled 8.3 name. */
1242 *out_of_space = False;
1243 *got_exact_match = False;
1245 ZERO_STRUCT(mdate_ts);
1246 ZERO_STRUCT(adate_ts);
1247 ZERO_STRUCT(create_date_ts);
1249 if (!conn->dirptr) {
1253 p = strrchr_m(path_mask,'/');
1256 mask = talloc_strdup(ctx,"*.*");
1266 bool ms_dfs_link = False;
1268 /* Needed if we run out of space */
1269 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1270 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1273 * Due to bugs in NT client redirectors we are not using
1274 * resume keys any more - set them to zero.
1275 * Check out the related comments in findfirst/findnext.
1281 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1282 (long)conn->dirptr,curr_dirpos));
1289 * fname may get mangled, dname is never mangled.
1290 * Whenever we're accessing the filesystem we use
1291 * pathreal which is composed from dname.
1297 /* Mangle fname if it's an illegal name. */
1298 if (mangle_must_mangle(dname,conn->params)) {
1299 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1300 continue; /* Error - couldn't mangle. */
1302 fname = mangled_name;
1305 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1306 got_match = mask_match(fname, mask, conn->case_sensitive);
1309 if(!got_match && check_mangled_names &&
1310 !mangle_is_8_3(fname, False, conn->params)) {
1312 * It turns out that NT matches wildcards against
1313 * both long *and* short names. This may explain some
1314 * of the wildcard wierdness from old DOS clients
1315 * that some people have been seeing.... JRA.
1317 /* Force the mangling into 8.3. */
1318 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1319 continue; /* Error - couldn't mangle. */
1322 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1323 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1328 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1330 if (dont_descend && !isdots) {
1336 pathreal = talloc_asprintf(ctx,
1341 pathreal = talloc_asprintf(ctx,
1351 if (INFO_LEVEL_IS_UNIX(info_level)) {
1352 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1353 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1354 pathreal,strerror(errno)));
1355 TALLOC_FREE(pathreal);
1358 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1359 /* Needed to show the msdfs symlinks as
1362 if(lp_host_msdfs() &&
1363 lp_msdfs_root(SNUM(conn)) &&
1364 ((ms_dfs_link = is_msdfs_link(conn, pathreal, &sbuf)) == True)) {
1365 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
1368 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1372 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1373 pathreal,strerror(errno)));
1374 TALLOC_FREE(pathreal);
1380 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1382 mode = dos_mode(conn,pathreal,&sbuf);
1385 if (!dir_check_ftype(conn,mode,dirtype)) {
1386 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1387 TALLOC_FREE(pathreal);
1391 if (!(mode & aDIR)) {
1392 file_size = get_file_size(sbuf);
1394 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1396 mdate_ts = get_mtimespec(&sbuf);
1397 adate_ts = get_atimespec(&sbuf);
1398 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1400 if (lp_dos_filetime_resolution(SNUM(conn))) {
1401 dos_filetime_timespec(&create_date_ts);
1402 dos_filetime_timespec(&mdate_ts);
1403 dos_filetime_timespec(&adate_ts);
1406 create_date = convert_timespec_to_time_t(create_date_ts);
1407 mdate = convert_timespec_to_time_t(mdate_ts);
1408 adate = convert_timespec_to_time_t(adate_ts);
1410 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1414 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1421 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1423 switch (info_level) {
1424 case SMB_FIND_INFO_STANDARD:
1425 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1426 if(requires_resume_key) {
1430 srv_put_dos_date2(p,0,create_date);
1431 srv_put_dos_date2(p,4,adate);
1432 srv_put_dos_date2(p,8,mdate);
1433 SIVAL(p,12,(uint32)file_size);
1434 SIVAL(p,16,(uint32)allocation_size);
1438 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1439 p += ucs2_align(base_data, p, 0);
1441 len = srvstr_push(base_data, flags2, p,
1442 fname, PTR_DIFF(end_data, p),
1444 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1446 SCVAL(nameptr, -1, len - 2);
1448 SCVAL(nameptr, -1, 0);
1452 SCVAL(nameptr, -1, len - 1);
1454 SCVAL(nameptr, -1, 0);
1460 case SMB_FIND_EA_SIZE:
1461 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1462 if(requires_resume_key) {
1466 srv_put_dos_date2(p,0,create_date);
1467 srv_put_dos_date2(p,4,adate);
1468 srv_put_dos_date2(p,8,mdate);
1469 SIVAL(p,12,(uint32)file_size);
1470 SIVAL(p,16,(uint32)allocation_size);
1473 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1474 SIVAL(p,22,ea_size); /* Extended attributes */
1478 len = srvstr_push(base_data, flags2,
1479 p, fname, PTR_DIFF(end_data, p),
1480 STR_TERMINATE | STR_NOALIGN);
1481 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1494 SCVAL(nameptr,0,len);
1496 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1499 case SMB_FIND_EA_LIST:
1501 struct ea_list *file_list = NULL;
1504 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1508 if(requires_resume_key) {
1512 srv_put_dos_date2(p,0,create_date);
1513 srv_put_dos_date2(p,4,adate);
1514 srv_put_dos_date2(p,8,mdate);
1515 SIVAL(p,12,(uint32)file_size);
1516 SIVAL(p,16,(uint32)allocation_size);
1518 p += 22; /* p now points to the EA area. */
1520 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1521 name_list = ea_list_union(name_list, file_list, &ea_len);
1523 /* We need to determine if this entry will fit in the space available. */
1524 /* Max string size is 255 bytes. */
1525 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1526 /* Move the dirptr back to prev_dirpos */
1527 dptr_SeekDir(conn->dirptr, prev_dirpos);
1528 *out_of_space = True;
1529 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1530 return False; /* Not finished - just out of space */
1533 /* Push the ea_data followed by the name. */
1534 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1536 len = srvstr_push(base_data, flags2,
1537 p + 1, fname, PTR_DIFF(end_data, p+1),
1538 STR_TERMINATE | STR_NOALIGN);
1539 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1552 SCVAL(nameptr,0,len);
1554 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1558 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1559 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1560 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1562 SIVAL(p,0,reskey); p += 4;
1563 put_long_date_timespec(p,create_date_ts); p += 8;
1564 put_long_date_timespec(p,adate_ts); p += 8;
1565 put_long_date_timespec(p,mdate_ts); p += 8;
1566 put_long_date_timespec(p,mdate_ts); p += 8;
1567 SOFF_T(p,0,file_size); p += 8;
1568 SOFF_T(p,0,allocation_size); p += 8;
1569 SIVAL(p,0,nt_extmode); p += 4;
1570 q = p; p += 4; /* q is placeholder for name length. */
1572 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1573 SIVAL(p,0,ea_size); /* Extended attributes */
1576 /* Clear the short name buffer. This is
1577 * IMPORTANT as not doing so will trigger
1578 * a Win2k client bug. JRA.
1580 if (!was_8_3 && check_mangled_names) {
1581 if (!name_to_8_3(fname,mangled_name,True,
1583 /* Error - mangle failed ! */
1584 memset(mangled_name,'\0',12);
1586 mangled_name[12] = 0;
1587 len = srvstr_push(base_data, flags2,
1588 p+2, mangled_name, 24,
1589 STR_UPPER|STR_UNICODE);
1591 memset(p + 2 + len,'\0',24 - len);
1598 len = srvstr_push(base_data, flags2, p,
1599 fname, PTR_DIFF(end_data, p),
1600 STR_TERMINATE_ASCII);
1603 SIVAL(p,0,0); /* Ensure any padding is null. */
1604 len = PTR_DIFF(p, pdata);
1605 len = (len + 3) & ~3;
1610 case SMB_FIND_FILE_DIRECTORY_INFO:
1611 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1613 SIVAL(p,0,reskey); p += 4;
1614 put_long_date_timespec(p,create_date_ts); p += 8;
1615 put_long_date_timespec(p,adate_ts); p += 8;
1616 put_long_date_timespec(p,mdate_ts); p += 8;
1617 put_long_date_timespec(p,mdate_ts); p += 8;
1618 SOFF_T(p,0,file_size); p += 8;
1619 SOFF_T(p,0,allocation_size); p += 8;
1620 SIVAL(p,0,nt_extmode); p += 4;
1621 len = srvstr_push(base_data, flags2,
1622 p + 4, fname, PTR_DIFF(end_data, p+4),
1623 STR_TERMINATE_ASCII);
1626 SIVAL(p,0,0); /* Ensure any padding is null. */
1627 len = PTR_DIFF(p, pdata);
1628 len = (len + 3) & ~3;
1633 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1634 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1636 SIVAL(p,0,reskey); p += 4;
1637 put_long_date_timespec(p,create_date_ts); p += 8;
1638 put_long_date_timespec(p,adate_ts); p += 8;
1639 put_long_date_timespec(p,mdate_ts); p += 8;
1640 put_long_date_timespec(p,mdate_ts); p += 8;
1641 SOFF_T(p,0,file_size); p += 8;
1642 SOFF_T(p,0,allocation_size); p += 8;
1643 SIVAL(p,0,nt_extmode); p += 4;
1644 q = p; p += 4; /* q is placeholder for name length. */
1646 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1647 SIVAL(p,0,ea_size); /* Extended attributes */
1650 len = srvstr_push(base_data, flags2, p,
1651 fname, PTR_DIFF(end_data, p),
1652 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_NAMES_INFO:
1664 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1666 SIVAL(p,0,reskey); p += 4;
1668 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1669 acl on a dir (tridge) */
1670 len = srvstr_push(base_data, flags2, p,
1671 fname, PTR_DIFF(end_data, p),
1672 STR_TERMINATE_ASCII);
1675 SIVAL(p,0,0); /* Ensure any padding is null. */
1676 len = PTR_DIFF(p, pdata);
1677 len = (len + 3) & ~3;
1682 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1683 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1685 SIVAL(p,0,reskey); p += 4;
1686 put_long_date_timespec(p,create_date_ts); p += 8;
1687 put_long_date_timespec(p,adate_ts); p += 8;
1688 put_long_date_timespec(p,mdate_ts); p += 8;
1689 put_long_date_timespec(p,mdate_ts); p += 8;
1690 SOFF_T(p,0,file_size); p += 8;
1691 SOFF_T(p,0,allocation_size); p += 8;
1692 SIVAL(p,0,nt_extmode); p += 4;
1693 q = p; p += 4; /* q is placeholder for name length. */
1695 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1696 SIVAL(p,0,ea_size); /* Extended attributes */
1699 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1700 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1701 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1702 len = srvstr_push(base_data, flags2, p,
1703 fname, PTR_DIFF(end_data, p),
1704 STR_TERMINATE_ASCII);
1707 SIVAL(p,0,0); /* Ensure any padding is null. */
1708 len = PTR_DIFF(p, pdata);
1709 len = (len + 3) & ~3;
1714 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1715 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1716 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1718 SIVAL(p,0,reskey); p += 4;
1719 put_long_date_timespec(p,create_date_ts); p += 8;
1720 put_long_date_timespec(p,adate_ts); p += 8;
1721 put_long_date_timespec(p,mdate_ts); p += 8;
1722 put_long_date_timespec(p,mdate_ts); p += 8;
1723 SOFF_T(p,0,file_size); p += 8;
1724 SOFF_T(p,0,allocation_size); p += 8;
1725 SIVAL(p,0,nt_extmode); p += 4;
1726 q = p; p += 4; /* q is placeholder for name length */
1728 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1729 SIVAL(p,0,ea_size); /* Extended attributes */
1732 /* Clear the short name buffer. This is
1733 * IMPORTANT as not doing so will trigger
1734 * a Win2k client bug. JRA.
1736 if (!was_8_3 && check_mangled_names) {
1737 if (!name_to_8_3(fname,mangled_name,True,
1739 /* Error - mangle failed ! */
1740 memset(mangled_name,'\0',12);
1742 mangled_name[12] = 0;
1743 len = srvstr_push(base_data, flags2,
1744 p+2, mangled_name, 24,
1745 STR_UPPER|STR_UNICODE);
1748 memset(p + 2 + len,'\0',24 - len);
1755 SSVAL(p,0,0); p += 2; /* Reserved ? */
1756 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1757 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1758 len = srvstr_push(base_data, flags2, p,
1759 fname, PTR_DIFF(end_data, p),
1760 STR_TERMINATE_ASCII);
1763 SIVAL(p,0,0); /* Ensure any padding is null. */
1764 len = PTR_DIFF(p, pdata);
1765 len = (len + 3) & ~3;
1770 /* CIFS UNIX Extension. */
1772 case SMB_FIND_FILE_UNIX:
1773 case SMB_FIND_FILE_UNIX_INFO2:
1775 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1777 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1779 if (info_level == SMB_FIND_FILE_UNIX) {
1780 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1781 p = store_file_unix_basic(conn, p,
1783 len = srvstr_push(base_data, flags2, p,
1784 fname, PTR_DIFF(end_data, p),
1787 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1788 p = store_file_unix_basic_info2(conn, p,
1792 len = srvstr_push(base_data, flags2, p, fname,
1793 PTR_DIFF(end_data, p), 0);
1794 SIVAL(nameptr, 0, len);
1798 SIVAL(p,0,0); /* Ensure any padding is null. */
1800 len = PTR_DIFF(p, pdata);
1801 len = (len + 3) & ~3;
1802 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1804 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1813 if (PTR_DIFF(p,pdata) > space_remaining) {
1814 /* Move the dirptr back to prev_dirpos */
1815 dptr_SeekDir(conn->dirptr, prev_dirpos);
1816 *out_of_space = True;
1817 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1818 return False; /* Not finished - just out of space */
1821 /* Setup the last entry pointer, as an offset from base_data */
1822 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1823 /* Advance the data pointer to the next slot */
1829 /****************************************************************************
1830 Reply to a TRANS2_FINDFIRST.
1831 ****************************************************************************/
1833 static void call_trans2findfirst(connection_struct *conn,
1834 struct smb_request *req,
1835 char **pparams, int total_params,
1836 char **ppdata, int total_data,
1837 unsigned int max_data_bytes)
1839 /* We must be careful here that we don't return more than the
1840 allowed number of data bytes. If this means returning fewer than
1841 maxentries then so be it. We assume that the redirector has
1842 enough room for the fixed number of parameter bytes it has
1844 char *params = *pparams;
1845 char *pdata = *ppdata;
1849 uint16 findfirst_flags;
1850 bool close_after_first;
1852 bool requires_resume_key;
1854 char *directory = NULL;
1855 const char *mask = NULL;
1857 int last_entry_off=0;
1861 bool finished = False;
1862 bool dont_descend = False;
1863 bool out_of_space = False;
1864 int space_remaining;
1865 bool mask_contains_wcard = False;
1866 SMB_STRUCT_STAT sbuf;
1867 struct ea_list *ea_list = NULL;
1868 NTSTATUS ntstatus = NT_STATUS_OK;
1869 TALLOC_CTX *ctx = talloc_tos();
1871 if (total_params < 13) {
1872 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1876 dirtype = SVAL(params,0);
1877 maxentries = SVAL(params,2);
1878 findfirst_flags = SVAL(params,4);
1879 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1880 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1881 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1882 info_level = SVAL(params,6);
1884 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1885 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1886 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1887 info_level, max_data_bytes));
1890 /* W2K3 seems to treat zero as 1. */
1894 switch (info_level) {
1895 case SMB_FIND_INFO_STANDARD:
1896 case SMB_FIND_EA_SIZE:
1897 case SMB_FIND_EA_LIST:
1898 case SMB_FIND_FILE_DIRECTORY_INFO:
1899 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1900 case SMB_FIND_FILE_NAMES_INFO:
1901 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1902 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1903 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1905 case SMB_FIND_FILE_UNIX:
1906 case SMB_FIND_FILE_UNIX_INFO2:
1907 if (!lp_unix_extensions()) {
1908 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1913 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1917 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1918 params+12, total_params - 12,
1919 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1920 if (!NT_STATUS_IS_OK(ntstatus)) {
1921 reply_nterror(req, ntstatus);
1925 ntstatus = resolve_dfspath_wcard(ctx, conn,
1926 req->flags2 & FLAGS2_DFS_PATHNAMES,
1929 &mask_contains_wcard);
1930 if (!NT_STATUS_IS_OK(ntstatus)) {
1931 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1932 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1933 ERRSRV, ERRbadpath);
1936 reply_nterror(req, ntstatus);
1940 ntstatus = unix_convert(ctx, conn, directory, True, &directory, NULL, &sbuf);
1941 if (!NT_STATUS_IS_OK(ntstatus)) {
1942 reply_nterror(req, ntstatus);
1946 ntstatus = check_name(conn, directory);
1947 if (!NT_STATUS_IS_OK(ntstatus)) {
1948 reply_nterror(req, ntstatus);
1952 p = strrchr_m(directory,'/');
1954 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1955 if((directory[0] == '.') && (directory[1] == '\0')) {
1957 mask_contains_wcard = True;
1961 directory = talloc_strdup(talloc_tos(), "./");
1963 reply_nterror(req, NT_STATUS_NO_MEMORY);
1971 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1973 if (info_level == SMB_FIND_EA_LIST) {
1976 if (total_data < 4) {
1977 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1981 ea_size = IVAL(pdata,0);
1982 if (ea_size != total_data) {
1983 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1984 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1985 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1989 if (!lp_ea_support(SNUM(conn))) {
1990 reply_doserror(req, ERRDOS, ERReasnotsupported);
1994 /* Pull out the list of names. */
1995 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
1997 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2002 *ppdata = (char *)SMB_REALLOC(
2003 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2004 if(*ppdata == NULL ) {
2005 reply_nterror(req, NT_STATUS_NO_MEMORY);
2009 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2011 /* Realloc the params space */
2012 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2013 if (*pparams == NULL) {
2014 reply_nterror(req, NT_STATUS_NO_MEMORY);
2019 /* Save the wildcard match and attribs we are using on this directory -
2020 needed as lanman2 assumes these are being saved between calls */
2022 ntstatus = dptr_create(conn,
2028 mask_contains_wcard,
2032 if (!NT_STATUS_IS_OK(ntstatus)) {
2033 reply_nterror(req, ntstatus);
2037 dptr_num = dptr_dnum(conn->dirptr);
2038 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2040 /* We don't need to check for VOL here as this is returned by
2041 a different TRANS2 call. */
2043 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2044 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2045 dont_descend = True;
2048 space_remaining = max_data_bytes;
2049 out_of_space = False;
2051 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2052 bool got_exact_match = False;
2054 /* this is a heuristic to avoid seeking the dirptr except when
2055 absolutely necessary. It allows for a filename of about 40 chars */
2056 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2057 out_of_space = True;
2060 finished = !get_lanman2_dir_entry(ctx,
2063 mask,dirtype,info_level,
2064 requires_resume_key,dont_descend,
2066 space_remaining, &out_of_space,
2068 &last_entry_off, ea_list);
2071 if (finished && out_of_space)
2074 if (!finished && !out_of_space)
2078 * As an optimisation if we know we aren't looking
2079 * for a wildcard name (ie. the name matches the wildcard exactly)
2080 * then we can finish on any (first) match.
2081 * This speeds up large directory searches. JRA.
2087 /* Ensure space_remaining never goes -ve. */
2088 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2089 space_remaining = 0;
2090 out_of_space = true;
2092 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2096 /* Check if we can close the dirptr */
2097 if(close_after_first || (finished && close_if_end)) {
2098 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2099 dptr_close(&dptr_num);
2103 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2104 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2105 * the protocol level is less than NT1. Tested with smbclient. JRA.
2106 * This should fix the OS/2 client bug #2335.
2109 if(numentries == 0) {
2110 dptr_close(&dptr_num);
2111 if (Protocol < PROTOCOL_NT1) {
2112 reply_doserror(req, ERRDOS, ERRnofiles);
2115 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2116 ERRDOS, ERRbadfile);
2121 /* At this point pdata points to numentries directory entries. */
2123 /* Set up the return parameter block */
2124 SSVAL(params,0,dptr_num);
2125 SSVAL(params,2,numentries);
2126 SSVAL(params,4,finished);
2127 SSVAL(params,6,0); /* Never an EA error */
2128 SSVAL(params,8,last_entry_off);
2130 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2133 if ((! *directory) && dptr_path(dptr_num)) {
2134 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2136 reply_nterror(req, NT_STATUS_NO_MEMORY);
2140 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2141 smb_fn_name(CVAL(req->inbuf,smb_com)),
2142 mask, directory, dirtype, numentries ) );
2145 * Force a name mangle here to ensure that the
2146 * mask as an 8.3 name is top of the mangled cache.
2147 * The reasons for this are subtle. Don't remove
2148 * this code unless you know what you are doing
2149 * (see PR#13758). JRA.
2152 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2153 char mangled_name[13];
2154 name_to_8_3(mask, mangled_name, True, conn->params);
2160 /****************************************************************************
2161 Reply to a TRANS2_FINDNEXT.
2162 ****************************************************************************/
2164 static void call_trans2findnext(connection_struct *conn,
2165 struct smb_request *req,
2166 char **pparams, int total_params,
2167 char **ppdata, int total_data,
2168 unsigned int max_data_bytes)
2170 /* We must be careful here that we don't return more than the
2171 allowed number of data bytes. If this means returning fewer than
2172 maxentries then so be it. We assume that the redirector has
2173 enough room for the fixed number of parameter bytes it has
2175 char *params = *pparams;
2176 char *pdata = *ppdata;
2182 uint16 findnext_flags;
2183 bool close_after_request;
2185 bool requires_resume_key;
2187 bool mask_contains_wcard = False;
2188 char *resume_name = NULL;
2189 const char *mask = NULL;
2190 const char *directory = NULL;
2194 int i, last_entry_off=0;
2195 bool finished = False;
2196 bool dont_descend = False;
2197 bool out_of_space = False;
2198 int space_remaining;
2199 struct ea_list *ea_list = NULL;
2200 NTSTATUS ntstatus = NT_STATUS_OK;
2201 TALLOC_CTX *ctx = talloc_tos();
2203 if (total_params < 13) {
2204 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2208 dptr_num = SVAL(params,0);
2209 maxentries = SVAL(params,2);
2210 info_level = SVAL(params,4);
2211 resume_key = IVAL(params,6);
2212 findnext_flags = SVAL(params,10);
2213 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2214 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2215 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2216 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2218 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2220 total_params - 12, STR_TERMINATE, &ntstatus,
2221 &mask_contains_wcard);
2222 if (!NT_STATUS_IS_OK(ntstatus)) {
2223 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2224 complain (it thinks we're asking for the directory above the shared
2225 path or an invalid name). Catch this as the resume name is only compared, never used in
2226 a file access. JRA. */
2227 srvstr_pull_talloc(ctx, params, req->flags2,
2228 &resume_name, params+12,
2232 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2233 reply_nterror(req, ntstatus);
2238 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2239 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2240 resume_key = %d resume name = %s continue=%d level = %d\n",
2241 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2242 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2245 /* W2K3 seems to treat zero as 1. */
2249 switch (info_level) {
2250 case SMB_FIND_INFO_STANDARD:
2251 case SMB_FIND_EA_SIZE:
2252 case SMB_FIND_EA_LIST:
2253 case SMB_FIND_FILE_DIRECTORY_INFO:
2254 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2255 case SMB_FIND_FILE_NAMES_INFO:
2256 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2257 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2258 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2260 case SMB_FIND_FILE_UNIX:
2261 case SMB_FIND_FILE_UNIX_INFO2:
2262 if (!lp_unix_extensions()) {
2263 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2268 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2272 if (info_level == SMB_FIND_EA_LIST) {
2275 if (total_data < 4) {
2276 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2280 ea_size = IVAL(pdata,0);
2281 if (ea_size != total_data) {
2282 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2283 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2284 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2288 if (!lp_ea_support(SNUM(conn))) {
2289 reply_doserror(req, ERRDOS, ERReasnotsupported);
2293 /* Pull out the list of names. */
2294 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2296 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2301 *ppdata = (char *)SMB_REALLOC(
2302 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2303 if(*ppdata == NULL) {
2304 reply_nterror(req, NT_STATUS_NO_MEMORY);
2309 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2311 /* Realloc the params space */
2312 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2313 if(*pparams == NULL ) {
2314 reply_nterror(req, NT_STATUS_NO_MEMORY);
2320 /* Check that the dptr is valid */
2321 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2322 reply_doserror(req, ERRDOS, ERRnofiles);
2326 string_set(&conn->dirpath,dptr_path(dptr_num));
2328 /* Get the wildcard mask from the dptr */
2329 if((p = dptr_wcard(dptr_num))== NULL) {
2330 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2331 reply_doserror(req, ERRDOS, ERRnofiles);
2336 directory = conn->dirpath;
2338 /* Get the attr mask from the dptr */
2339 dirtype = dptr_attr(dptr_num);
2341 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2342 dptr_num, mask, dirtype,
2344 dptr_TellDir(conn->dirptr)));
2346 /* We don't need to check for VOL here as this is returned by
2347 a different TRANS2 call. */
2349 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2350 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2351 dont_descend = True;
2354 space_remaining = max_data_bytes;
2355 out_of_space = False;
2358 * Seek to the correct position. We no longer use the resume key but
2359 * depend on the last file name instead.
2362 if(*resume_name && !continue_bit) {
2365 long current_pos = 0;
2367 * Remember, name_to_8_3 is called by
2368 * get_lanman2_dir_entry(), so the resume name
2369 * could be mangled. Ensure we check the unmangled name.
2372 if (mangle_is_mangled(resume_name, conn->params)) {
2373 char *new_resume_name = NULL;
2374 mangle_lookup_name_from_8_3(ctx,
2378 if (new_resume_name) {
2379 resume_name = new_resume_name;
2384 * Fix for NT redirector problem triggered by resume key indexes
2385 * changing between directory scans. We now return a resume key of 0
2386 * and instead look for the filename to continue from (also given
2387 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2388 * findfirst/findnext (as is usual) then the directory pointer
2389 * should already be at the correct place.
2392 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2393 } /* end if resume_name && !continue_bit */
2395 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2396 bool got_exact_match = False;
2398 /* this is a heuristic to avoid seeking the dirptr except when
2399 absolutely necessary. It allows for a filename of about 40 chars */
2400 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2401 out_of_space = True;
2404 finished = !get_lanman2_dir_entry(ctx,
2407 mask,dirtype,info_level,
2408 requires_resume_key,dont_descend,
2410 space_remaining, &out_of_space,
2412 &last_entry_off, ea_list);
2415 if (finished && out_of_space)
2418 if (!finished && !out_of_space)
2422 * As an optimisation if we know we aren't looking
2423 * for a wildcard name (ie. the name matches the wildcard exactly)
2424 * then we can finish on any (first) match.
2425 * This speeds up large directory searches. JRA.
2431 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2434 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2435 smb_fn_name(CVAL(req->inbuf,smb_com)),
2436 mask, directory, dirtype, numentries ) );
2438 /* Check if we can close the dirptr */
2439 if(close_after_request || (finished && close_if_end)) {
2440 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2441 dptr_close(&dptr_num); /* This frees up the saved mask */
2444 /* Set up the return parameter block */
2445 SSVAL(params,0,numentries);
2446 SSVAL(params,2,finished);
2447 SSVAL(params,4,0); /* Never an EA error */
2448 SSVAL(params,6,last_entry_off);
2450 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2456 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2458 E_md4hash(lp_servicename(SNUM(conn)),objid);
2462 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2464 SMB_ASSERT(extended_info != NULL);
2466 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2467 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2468 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2469 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2470 #ifdef SAMBA_VERSION_REVISION
2471 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2473 #ifdef SAMBA_VERSION_RC_RELEASE
2474 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2476 #ifdef SAMBA_VERSION_PRE_RELEASE
2477 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2480 #ifdef SAMBA_VERSION_VENDOR_PATCH
2481 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2483 /* FIXME: samba_gitcommitdate should contain the git commit date. */
2484 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2485 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2488 memset(extended_info->samba_version_string, 0,
2489 sizeof(extended_info->samba_version_string));
2491 snprintf (extended_info->samba_version_string,
2492 sizeof(extended_info->samba_version_string),
2493 "%s", samba_version_string());
2496 /****************************************************************************
2497 Reply to a TRANS2_QFSINFO (query filesystem info).
2498 ****************************************************************************/
2500 static void call_trans2qfsinfo(connection_struct *conn,
2501 struct smb_request *req,
2502 char **pparams, int total_params,
2503 char **ppdata, int total_data,
2504 unsigned int max_data_bytes)
2506 char *pdata, *end_data;
2507 char *params = *pparams;
2511 const char *vname = volume_label(SNUM(conn));
2512 int snum = SNUM(conn);
2513 char *fstype = lp_fstype(SNUM(conn));
2514 uint32 additional_flags = 0;
2516 if (total_params < 2) {
2517 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2521 info_level = SVAL(params,0);
2524 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2525 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2526 "info level (0x%x) on IPC$.\n",
2527 (unsigned int)info_level));
2528 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2533 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2534 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2535 DEBUG(0,("call_trans2qfsinfo: encryption required "
2536 "and info level 0x%x sent.\n",
2537 (unsigned int)info_level));
2538 exit_server_cleanly("encryption required "
2544 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2546 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2547 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2548 reply_doserror(req, ERRSRV, ERRinvdevice);
2552 *ppdata = (char *)SMB_REALLOC(
2553 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2554 if (*ppdata == NULL ) {
2555 reply_nterror(req, NT_STATUS_NO_MEMORY);
2560 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2561 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2563 switch (info_level) {
2564 case SMB_INFO_ALLOCATION:
2566 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2568 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2569 reply_unixerror(req, ERRHRD, ERRgeneral);
2573 block_size = lp_block_size(snum);
2574 if (bsize < block_size) {
2575 SMB_BIG_UINT factor = block_size/bsize;
2580 if (bsize > block_size) {
2581 SMB_BIG_UINT factor = bsize/block_size;
2586 bytes_per_sector = 512;
2587 sectors_per_unit = bsize/bytes_per_sector;
2589 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2590 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2591 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2593 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2594 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2595 SIVAL(pdata,l1_cUnit,dsize);
2596 SIVAL(pdata,l1_cUnitAvail,dfree);
2597 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2601 case SMB_INFO_VOLUME:
2602 /* Return volume name */
2604 * Add volume serial number - hash of a combination of
2605 * the called hostname and the service name.
2607 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2609 * Win2k3 and previous mess this up by sending a name length
2610 * one byte short. I believe only older clients (OS/2 Win9x) use
2611 * this call so try fixing this by adding a terminating null to
2612 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2616 pdata+l2_vol_szVolLabel, vname,
2617 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2618 STR_NOALIGN|STR_TERMINATE);
2619 SCVAL(pdata,l2_vol_cch,len);
2620 data_len = l2_vol_szVolLabel + len;
2621 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2622 (unsigned)st.st_ctime, len, vname));
2625 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2626 case SMB_FS_ATTRIBUTE_INFORMATION:
2628 additional_flags = 0;
2629 #if defined(HAVE_SYS_QUOTAS)
2630 additional_flags |= FILE_VOLUME_QUOTAS;
2633 if(lp_nt_acl_support(SNUM(conn))) {
2634 additional_flags |= FILE_PERSISTENT_ACLS;
2637 /* Capabilities are filled in at connection time through STATVFS call */
2638 additional_flags |= conn->fs_capabilities;
2640 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2641 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2642 additional_flags); /* FS ATTRIBUTES */
2644 SIVAL(pdata,4,255); /* Max filename component length */
2645 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2646 and will think we can't do long filenames */
2647 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2648 PTR_DIFF(end_data, pdata+12),
2651 data_len = 12 + len;
2654 case SMB_QUERY_FS_LABEL_INFO:
2655 case SMB_FS_LABEL_INFORMATION:
2656 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2657 PTR_DIFF(end_data, pdata+4), 0);
2662 case SMB_QUERY_FS_VOLUME_INFO:
2663 case SMB_FS_VOLUME_INFORMATION:
2666 * Add volume serial number - hash of a combination of
2667 * the called hostname and the service name.
2669 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2670 (str_checksum(get_local_machine_name())<<16));
2672 /* Max label len is 32 characters. */
2673 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2674 PTR_DIFF(end_data, pdata+18),
2676 SIVAL(pdata,12,len);
2679 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2680 (int)strlen(vname),vname, lp_servicename(snum)));
2683 case SMB_QUERY_FS_SIZE_INFO:
2684 case SMB_FS_SIZE_INFORMATION:
2686 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2688 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2689 reply_unixerror(req, ERRHRD, ERRgeneral);
2692 block_size = lp_block_size(snum);
2693 if (bsize < block_size) {
2694 SMB_BIG_UINT factor = block_size/bsize;
2699 if (bsize > block_size) {
2700 SMB_BIG_UINT factor = bsize/block_size;
2705 bytes_per_sector = 512;
2706 sectors_per_unit = bsize/bytes_per_sector;
2707 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2708 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2709 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2710 SBIG_UINT(pdata,0,dsize);
2711 SBIG_UINT(pdata,8,dfree);
2712 SIVAL(pdata,16,sectors_per_unit);
2713 SIVAL(pdata,20,bytes_per_sector);
2717 case SMB_FS_FULL_SIZE_INFORMATION:
2719 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2721 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2722 reply_unixerror(req, ERRHRD, ERRgeneral);
2725 block_size = lp_block_size(snum);
2726 if (bsize < block_size) {
2727 SMB_BIG_UINT factor = block_size/bsize;
2732 if (bsize > block_size) {
2733 SMB_BIG_UINT factor = bsize/block_size;
2738 bytes_per_sector = 512;
2739 sectors_per_unit = bsize/bytes_per_sector;
2740 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2741 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2742 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2743 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2744 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2745 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2746 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2747 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2751 case SMB_QUERY_FS_DEVICE_INFO:
2752 case SMB_FS_DEVICE_INFORMATION:
2754 SIVAL(pdata,0,0); /* dev type */
2755 SIVAL(pdata,4,0); /* characteristics */
2758 #ifdef HAVE_SYS_QUOTAS
2759 case SMB_FS_QUOTA_INFORMATION:
2761 * what we have to send --metze:
2763 * Unknown1: 24 NULL bytes
2764 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2765 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2766 * Quota Flags: 2 byte :
2767 * Unknown3: 6 NULL bytes
2771 * details for Quota Flags:
2773 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2774 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2775 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2776 * 0x0001 Enable Quotas: enable quota for this fs
2780 /* we need to fake up a fsp here,
2781 * because its not send in this call
2784 SMB_NTQUOTA_STRUCT quotas;
2787 ZERO_STRUCT(quotas);
2793 if (current_user.ut.uid != 0) {
2794 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2795 lp_servicename(SNUM(conn)),conn->user));
2796 reply_doserror(req, ERRDOS, ERRnoaccess);
2800 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2801 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2802 reply_doserror(req, ERRSRV, ERRerror);
2808 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2810 /* Unknown1 24 NULL bytes*/
2811 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2812 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2813 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2815 /* Default Soft Quota 8 bytes */
2816 SBIG_UINT(pdata,24,quotas.softlim);
2818 /* Default Hard Quota 8 bytes */
2819 SBIG_UINT(pdata,32,quotas.hardlim);
2821 /* Quota flag 2 bytes */
2822 SSVAL(pdata,40,quotas.qflags);
2824 /* Unknown3 6 NULL bytes */
2830 #endif /* HAVE_SYS_QUOTAS */
2831 case SMB_FS_OBJECTID_INFORMATION:
2833 unsigned char objid[16];
2834 struct smb_extended_info extended_info;
2835 memcpy(pdata,create_volume_objectid(conn, objid),16);
2836 samba_extended_info_version (&extended_info);
2837 SIVAL(pdata,16,extended_info.samba_magic);
2838 SIVAL(pdata,20,extended_info.samba_version);
2839 SIVAL(pdata,24,extended_info.samba_subversion);
2840 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2841 memcpy(pdata+36,extended_info.samba_version_string,28);
2847 * Query the version and capabilities of the CIFS UNIX extensions
2851 case SMB_QUERY_CIFS_UNIX_INFO:
2853 bool large_write = lp_min_receive_file_size() &&
2854 !srv_is_signing_active();
2855 bool large_read = !srv_is_signing_active();
2856 int encrypt_caps = 0;
2858 if (!lp_unix_extensions()) {
2859 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2863 switch (conn->encrypt_level) {
2869 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2872 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2873 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2874 large_write = false;
2880 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2881 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2883 /* We have POSIX ACLs, pathname, encryption,
2884 * large read/write, and locking capability. */
2886 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2887 CIFS_UNIX_POSIX_ACLS_CAP|
2888 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2889 CIFS_UNIX_FCNTL_LOCKS_CAP|
2890 CIFS_UNIX_EXTATTR_CAP|
2891 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2893 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2895 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2899 case SMB_QUERY_POSIX_FS_INFO:
2902 vfs_statvfs_struct svfs;
2904 if (!lp_unix_extensions()) {
2905 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2909 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2913 SIVAL(pdata,0,svfs.OptimalTransferSize);
2914 SIVAL(pdata,4,svfs.BlockSize);
2915 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2916 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2917 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2918 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2919 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2920 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2921 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2923 } else if (rc == EOPNOTSUPP) {
2924 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2926 #endif /* EOPNOTSUPP */
2928 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2929 reply_doserror(req, ERRSRV, ERRerror);
2935 case SMB_QUERY_POSIX_WHOAMI:
2941 if (!lp_unix_extensions()) {
2942 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2946 if (max_data_bytes < 40) {
2947 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2951 /* We ARE guest if global_sid_Builtin_Guests is
2952 * in our list of SIDs.
2954 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2955 current_user.nt_user_token)) {
2956 flags |= SMB_WHOAMI_GUEST;
2959 /* We are NOT guest if global_sid_Authenticated_Users
2960 * is in our list of SIDs.
2962 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2963 current_user.nt_user_token)) {
2964 flags &= ~SMB_WHOAMI_GUEST;
2967 /* NOTE: 8 bytes for UID/GID, irrespective of native
2968 * platform size. This matches
2969 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2971 data_len = 4 /* flags */
2978 + 4 /* pad/reserved */
2979 + (current_user.ut.ngroups * 8)
2981 + (current_user.nt_user_token->num_sids *
2985 SIVAL(pdata, 0, flags);
2986 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2987 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2988 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2991 if (data_len >= max_data_bytes) {
2992 /* Potential overflow, skip the GIDs and SIDs. */
2994 SIVAL(pdata, 24, 0); /* num_groups */
2995 SIVAL(pdata, 28, 0); /* num_sids */
2996 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2997 SIVAL(pdata, 36, 0); /* reserved */
3003 SIVAL(pdata, 24, current_user.ut.ngroups);
3005 current_user.nt_user_token->num_sids);
3007 /* We walk the SID list twice, but this call is fairly
3008 * infrequent, and I don't expect that it's performance
3009 * sensitive -- jpeach
3011 for (i = 0, sid_bytes = 0;
3012 i < current_user.nt_user_token->num_sids; ++i) {
3013 sid_bytes += ndr_size_dom_sid(
3014 ¤t_user.nt_user_token->user_sids[i], 0);
3017 /* SID list byte count */
3018 SIVAL(pdata, 32, sid_bytes);
3020 /* 4 bytes pad/reserved - must be zero */
3021 SIVAL(pdata, 36, 0);
3025 for (i = 0; i < current_user.ut.ngroups; ++i) {
3026 SBIG_UINT(pdata, data_len,
3027 (SMB_BIG_UINT)current_user.ut.groups[i]);
3033 i < current_user.nt_user_token->num_sids; ++i) {
3034 int sid_len = ndr_size_dom_sid(
3035 ¤t_user.nt_user_token->user_sids[i], 0);
3037 sid_linearize(pdata + data_len, sid_len,
3038 ¤t_user.nt_user_token->user_sids[i]);
3039 data_len += sid_len;
3045 case SMB_MAC_QUERY_FS_INFO:
3047 * Thursby MAC extension... ONLY on NTFS filesystems
3048 * once we do streams then we don't need this
3050 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3052 SIVAL(pdata,84,0x100); /* Don't support mac... */
3057 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3062 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3065 DEBUG( 4, ( "%s info_level = %d\n",
3066 smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) );
3071 /****************************************************************************
3072 Reply to a TRANS2_SETFSINFO (set filesystem info).
3073 ****************************************************************************/
3075 static void call_trans2setfsinfo(connection_struct *conn,
3076 struct smb_request *req,
3077 char **pparams, int total_params,
3078 char **ppdata, int total_data,
3079 unsigned int max_data_bytes)
3081 char *pdata = *ppdata;
3082 char *params = *pparams;
3085 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3088 if (total_params < 4) {
3089 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3091 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3095 info_level = SVAL(params,2);
3098 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3099 info_level != SMB_SET_CIFS_UNIX_INFO) {
3100 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3101 "info level (0x%x) on IPC$.\n",
3102 (unsigned int)info_level));
3103 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3108 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3109 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3110 DEBUG(0,("call_trans2setfsinfo: encryption required "
3111 "and info level 0x%x sent.\n",
3112 (unsigned int)info_level));
3113 exit_server_cleanly("encryption required "
3119 switch(info_level) {
3120 case SMB_SET_CIFS_UNIX_INFO:
3122 uint16 client_unix_major;
3123 uint16 client_unix_minor;
3124 uint32 client_unix_cap_low;
3125 uint32 client_unix_cap_high;
3127 if (!lp_unix_extensions()) {
3129 NT_STATUS_INVALID_LEVEL);
3133 /* There should be 12 bytes of capabilities set. */
3134 if (total_data < 8) {
3137 NT_STATUS_INVALID_PARAMETER);
3140 client_unix_major = SVAL(pdata,0);
3141 client_unix_minor = SVAL(pdata,2);
3142 client_unix_cap_low = IVAL(pdata,4);
3143 client_unix_cap_high = IVAL(pdata,8);
3144 /* Just print these values for now. */
3145 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3146 cap_low = 0x%x, cap_high = 0x%x\n",
3147 (unsigned int)client_unix_major,
3148 (unsigned int)client_unix_minor,
3149 (unsigned int)client_unix_cap_low,
3150 (unsigned int)client_unix_cap_high ));
3152 /* Here is where we must switch to posix pathname processing... */
3153 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3154 lp_set_posix_pathnames();
3155 mangle_change_to_posix();
3158 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3159 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3160 /* Client that knows how to do posix locks,
3161 * but not posix open/mkdir operations. Set a
3162 * default type for read/write checks. */
3164 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3170 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3173 size_t param_len = 0;
3174 size_t data_len = total_data;
3176 if (!lp_unix_extensions()) {
3179 NT_STATUS_INVALID_LEVEL);
3183 if (lp_smb_encrypt(SNUM(conn)) == false) {
3186 NT_STATUS_NOT_SUPPORTED);
3190 DEBUG( 4,("call_trans2setfsinfo: "
3191 "request transport encrption.\n"));
3193 status = srv_request_encryption_setup(conn,
3194 (unsigned char **)ppdata,
3196 (unsigned char **)pparams,
3199 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3200 !NT_STATUS_IS_OK(status)) {
3201 reply_nterror(req, status);
3205 send_trans2_replies(conn, req,
3212 if (NT_STATUS_IS_OK(status)) {
3213 /* Server-side transport
3214 * encryption is now *on*. */
3215 status = srv_encryption_start(conn);
3216 if (!NT_STATUS_IS_OK(status)) {
3217 exit_server_cleanly(
3218 "Failure in setting "
3219 "up encrypted transport");
3225 case SMB_FS_QUOTA_INFORMATION:
3227 files_struct *fsp = NULL;
3228 SMB_NTQUOTA_STRUCT quotas;
3230 ZERO_STRUCT(quotas);
3233 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
3234 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3235 lp_servicename(SNUM(conn)),conn->user));
3236 reply_doserror(req, ERRSRV, ERRaccess);
3240 /* note: normaly there're 48 bytes,
3241 * but we didn't use the last 6 bytes for now
3244 fsp = file_fsp(SVAL(params,0));
3245 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
3246 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3248 req, NT_STATUS_INVALID_HANDLE);
3252 if (total_data < 42) {
3253 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3257 NT_STATUS_INVALID_PARAMETER);
3261 /* unknown_1 24 NULL bytes in pdata*/
3263 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3264 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
3265 #ifdef LARGE_SMB_OFF_T
3266 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
3267 #else /* LARGE_SMB_OFF_T */
3268 if ((IVAL(pdata,28) != 0)&&
3269 ((quotas.softlim != 0xFFFFFFFF)||
3270 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3271 /* more than 32 bits? */
3274 NT_STATUS_INVALID_PARAMETER);
3277 #endif /* LARGE_SMB_OFF_T */
3279 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3280 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
3281 #ifdef LARGE_SMB_OFF_T
3282 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
3283 #else /* LARGE_SMB_OFF_T */
3284 if ((IVAL(pdata,36) != 0)&&
3285 ((quotas.hardlim != 0xFFFFFFFF)||
3286 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3287 /* more than 32 bits? */
3290 NT_STATUS_INVALID_PARAMETER);
3293 #endif /* LARGE_SMB_OFF_T */
3295 /* quota_flags 2 bytes **/
3296 quotas.qflags = SVAL(pdata,40);
3298 /* unknown_2 6 NULL bytes follow*/
3300 /* now set the quotas */
3301 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3302 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3303 reply_doserror(req, ERRSRV, ERRerror);
3310 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3312 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3318 * sending this reply works fine,
3319 * but I'm not sure it's the same
3320 * like windows do...
3323 reply_outbuf(req, 10, 0);
3326 #if defined(HAVE_POSIX_ACLS)
3327 /****************************************************************************
3328 Utility function to count the number of entries in a POSIX acl.
3329 ****************************************************************************/
3331 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3333 unsigned int ace_count = 0;
3334 int entry_id = SMB_ACL_FIRST_ENTRY;
3335 SMB_ACL_ENTRY_T entry;
3337 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3339 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3340 entry_id = SMB_ACL_NEXT_ENTRY;
3347 /****************************************************************************
3348 Utility function to marshall a POSIX acl into wire format.
3349 ****************************************************************************/
3351 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3353 int entry_id = SMB_ACL_FIRST_ENTRY;
3354 SMB_ACL_ENTRY_T entry;
3356 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3357 SMB_ACL_TAG_T tagtype;
3358 SMB_ACL_PERMSET_T permset;
3359 unsigned char perms = 0;
3360 unsigned int own_grp;
3363 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3364 entry_id = SMB_ACL_NEXT_ENTRY;
3367 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3368 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3372 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3373 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3377 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3378 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3379 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3381 SCVAL(pdata,1,perms);
3384 case SMB_ACL_USER_OBJ:
3385 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3386 own_grp = (unsigned int)pst->st_uid;
3387 SIVAL(pdata,2,own_grp);
3392 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3394 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3397 own_grp = (unsigned int)*puid;
3398 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3399 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3400 SIVAL(pdata,2,own_grp);
3404 case SMB_ACL_GROUP_OBJ:
3405 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3406 own_grp = (unsigned int)pst->st_gid;
3407 SIVAL(pdata,2,own_grp);
3412 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3414 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3417 own_grp = (unsigned int)*pgid;
3418 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3419 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3420 SIVAL(pdata,2,own_grp);
3425 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3426 SIVAL(pdata,2,0xFFFFFFFF);
3427 SIVAL(pdata,6,0xFFFFFFFF);
3430 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3431 SIVAL(pdata,2,0xFFFFFFFF);
3432 SIVAL(pdata,6,0xFFFFFFFF);
3435 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3438 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3445 /****************************************************************************
3446 Store the FILE_UNIX_BASIC info.
3447 ****************************************************************************/
3449 static char *store_file_unix_basic(connection_struct *conn,
3452 const SMB_STRUCT_STAT *psbuf)
3454 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3455 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3457 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3460 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3463 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3464 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3465 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3468 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3472 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3476 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3479 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3483 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3487 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3490 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3494 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3501 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3502 * the chflags(2) (or equivalent) flags.
3504 * XXX: this really should be behind the VFS interface. To do this, we would
3505 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3506 * Each VFS module could then implement its own mapping as appropriate for the
3507 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3509 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3513 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3517 { UF_IMMUTABLE, EXT_IMMUTABLE },
3521 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3525 { UF_HIDDEN, EXT_HIDDEN },
3528 /* Do not remove. We need to guarantee that this array has at least one
3529 * entry to build on HP-UX.
3535 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3536 uint32 *smb_fflags, uint32 *smb_fmask)
3538 #ifdef HAVE_STAT_ST_FLAGS
3541 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3542 *smb_fmask |= info2_flags_map[i].smb_fflag;
3543 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3544 *smb_fflags |= info2_flags_map[i].smb_fflag;
3547 #endif /* HAVE_STAT_ST_FLAGS */
3550 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3551 const uint32 smb_fflags,
3552 const uint32 smb_fmask,
3555 #ifdef HAVE_STAT_ST_FLAGS
3556 uint32 max_fmask = 0;
3559 *stat_fflags = psbuf->st_flags;
3561 /* For each flags requested in smb_fmask, check the state of the
3562 * corresponding flag in smb_fflags and set or clear the matching
3566 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3567 max_fmask |= info2_flags_map[i].smb_fflag;
3568 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3569 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3570 *stat_fflags |= info2_flags_map[i].stat_fflag;
3572 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3577 /* If smb_fmask is asking to set any bits that are not supported by
3578 * our flag mappings, we should fail.
3580 if ((smb_fmask & max_fmask) != smb_fmask) {
3587 #endif /* HAVE_STAT_ST_FLAGS */
3591 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3592 * of file flags and birth (create) time.
3594 static char *store_file_unix_basic_info2(connection_struct *conn,
3597 const SMB_STRUCT_STAT *psbuf)
3599 uint32 file_flags = 0;
3600 uint32 flags_mask = 0;
3602 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3604 /* Create (birth) time 64 bit */
3605 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3608 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3609 SIVAL(pdata, 0, file_flags); /* flags */
3610 SIVAL(pdata, 4, flags_mask); /* mask */
3616 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3617 const struct stream_struct *streams,
3619 unsigned int max_data_bytes,
3620 unsigned int *data_size)
3623 unsigned int ofs = 0;
3625 for (i=0; i<num_streams; i++) {
3626 unsigned int next_offset;
3628 smb_ucs2_t *namebuf;
3630 namelen = push_ucs2_talloc(talloc_tos(), &namebuf,
3633 if ((namelen == (size_t)-1) || (namelen <= 2)) {
3634 return NT_STATUS_INVALID_PARAMETER;
3638 * name_buf is now null-terminated, we need to marshall as not
3644 if (ofs + 24 + namelen > max_data_bytes) {
3645 TALLOC_FREE(namebuf);
3646 return NT_STATUS_BUFFER_TOO_SMALL;
3649 SIVAL(data, ofs+4, namelen);
3650 SOFF_T(data, ofs+8, streams[i].size);
3651 SOFF_T(data, ofs+16, streams[i].alloc_size);
3652 memcpy(data+ofs+24, namebuf, namelen);
3653 TALLOC_FREE(namebuf);
3655 next_offset = ofs + 24 + namelen;
3657 if (i == num_streams-1) {
3658 SIVAL(data, ofs, 0);
3661 unsigned int align = ndr_align_size(next_offset, 8);
3663 if (next_offset + align > max_data_bytes) {
3664 return NT_STATUS_BUFFER_TOO_SMALL;
3667 memset(data+next_offset, 0, align);
3668 next_offset += align;
3670 SIVAL(data, ofs, next_offset - ofs);
3679 return NT_STATUS_OK;
3682 /****************************************************************************
3683 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3684 ****************************************************************************/
3686 static void call_trans2qpipeinfo(connection_struct *conn,
3687 struct smb_request *req,
3688 unsigned int tran_call,
3689 char **pparams, int total_params,
3690 char **ppdata, int total_data,
3691 unsigned int max_data_bytes)
3693 char *params = *pparams;
3694 char *pdata = *ppdata;
3695 unsigned int data_size = 0;
3696 unsigned int param_size = 2;
3698 smb_np_struct *p_pipe = NULL;
3701 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3705 if (total_params < 4) {
3706 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3710 p_pipe = get_rpc_pipe_p(SVAL(params,0));
3711 if (p_pipe == NULL) {
3712 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3716 info_level = SVAL(params,2);
3718 *pparams = (char *)SMB_REALLOC(*pparams,2);
3719 if (*pparams == NULL) {
3720 reply_nterror(req, NT_STATUS_NO_MEMORY);
3725 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3726 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3727 if (*ppdata == NULL ) {
3728 reply_nterror(req, NT_STATUS_NO_MEMORY);
3733 switch (info_level) {
3734 case SMB_FILE_STANDARD_INFORMATION:
3736 SOFF_T(pdata,0,4096LL);
3743 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3747 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3753 /****************************************************************************
3754 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3755 file name or file id).
3756 ****************************************************************************/
3758 static void call_trans2qfilepathinfo(connection_struct *conn,
3759 struct smb_request *req,
3760 unsigned int tran_call,
3761 char **pparams, int total_params,
3762 char **ppdata, int total_data,
3763 unsigned int max_data_bytes)
3765 char *params = *pparams;
3766 char *pdata = *ppdata;
3767 char *dstart, *dend;
3771 SMB_OFF_T file_size=0;
3772 SMB_BIG_UINT allocation_size=0;
3773 unsigned int data_size = 0;
3774 unsigned int param_size = 2;
3775 SMB_STRUCT_STAT sbuf;
3776 char *dos_fname = NULL;
3782 bool delete_pending = False;
3784 time_t create_time, mtime, atime;
3785 struct timespec create_time_ts, mtime_ts, atime_ts;
3786 files_struct *fsp = NULL;
3787 struct file_id fileid;
3788 struct ea_list *ea_list = NULL;
3789 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3790 char *lock_data = NULL;
3791 TALLOC_CTX *ctx = talloc_tos();
3794 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3800 if (tran_call == TRANSACT2_QFILEINFO) {
3801 if (total_params < 4) {
3802 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3807 call_trans2qpipeinfo(conn, req, tran_call,
3808 pparams, total_params,
3814 fsp = file_fsp(SVAL(params,0));
3815 info_level = SVAL(params,2);
3817 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3819 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3820 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3824 /* Initial check for valid fsp ptr. */
3825 if (!check_fsp_open(conn, req, fsp, ¤t_user)) {
3829 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3831 reply_nterror(req, NT_STATUS_NO_MEMORY);
3835 if(fsp->fake_file_handle) {
3837 * This is actually for the QUOTA_FAKE_FILE --metze
3840 /* We know this name is ok, it's already passed the checks. */
3842 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3844 * This is actually a QFILEINFO on a directory
3845 * handle (returned from an NT SMB). NT5.0 seems
3846 * to do this call. JRA.
3849 if (INFO_LEVEL_IS_UNIX(info_level)) {
3850 /* Always do lstat for UNIX calls. */
3851 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3852 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3853 reply_unixerror(req,ERRDOS,ERRbadpath);
3856 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3857 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3858 reply_unixerror(req, ERRDOS, ERRbadpath);
3862 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3863 delete_pending = get_delete_on_close_flag(fileid);
3866 * Original code - this is an open file.
3868 if (!check_fsp(conn, req, fsp, ¤t_user)) {
3872 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3873 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3874 reply_unixerror(req, ERRDOS, ERRbadfid);
3877 pos = fsp->fh->position_information;
3878 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3879 delete_pending = get_delete_on_close_flag(fileid);
3880 access_mask = fsp->access_mask;
3884 NTSTATUS status = NT_STATUS_OK;
3887 if (total_params < 7) {
3888 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3892 info_level = SVAL(params,0);
3894 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3896 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3897 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3901 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
3903 STR_TERMINATE, &status);
3904 if (!NT_STATUS_IS_OK(status)) {
3905 reply_nterror(req, status);
3909 status = resolve_dfspath(ctx,
3911 req->flags2 & FLAGS2_DFS_PATHNAMES,
3914 if (!NT_STATUS_IS_OK(status)) {
3915 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3916 reply_botherror(req,
3917 NT_STATUS_PATH_NOT_COVERED,
3918 ERRSRV, ERRbadpath);
3920 reply_nterror(req, status);
3924 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3925 if (!NT_STATUS_IS_OK(status)) {
3926 reply_nterror(req, status);
3929 status = check_name(conn, fname);
3930 if (!NT_STATUS_IS_OK(status)) {
3931 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3932 reply_nterror(req, status);
3936 if (INFO_LEVEL_IS_UNIX(info_level)) {
3937 /* Always do lstat for UNIX calls. */
3938 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3939 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3940 reply_unixerror(req, ERRDOS, ERRbadpath);
3943 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3944 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3945 reply_unixerror(req, ERRDOS, ERRbadpath);
3949 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3950 delete_pending = get_delete_on_close_flag(fileid);
3951 if (delete_pending) {
3952 reply_nterror(req, NT_STATUS_DELETE_PENDING);
3957 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3958 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3962 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3963 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3965 p = strrchr_m(fname,'/');
3971 mode = dos_mode(conn,fname,&sbuf);
3973 mode = FILE_ATTRIBUTE_NORMAL;
3975 nlink = sbuf.st_nlink;
3977 if (nlink && (mode&aDIR)) {
3981 if ((nlink > 0) && delete_pending) {
3985 fullpathname = fname;
3987 file_size = get_file_size(sbuf);
3989 /* Pull out any data sent here before we realloc. */
3990 switch (info_level) {
3991 case SMB_INFO_QUERY_EAS_FROM_LIST:
3993 /* Pull any EA list from the data portion. */
3996 if (total_data < 4) {
3998 req, NT_STATUS_INVALID_PARAMETER);
4001 ea_size = IVAL(pdata,0);
4003 if (total_data > 0 && ea_size != total_data) {
4004 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4005 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4007 req, NT_STATUS_INVALID_PARAMETER);
4011 if (!lp_ea_support(SNUM(conn))) {
4012 reply_doserror(req, ERRDOS,
4013 ERReasnotsupported);
4017 /* Pull out the list of names. */
4018 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4021 req, NT_STATUS_INVALID_PARAMETER);
4027 case SMB_QUERY_POSIX_LOCK:
4029 if (fsp == NULL || fsp->fh->fd == -1) {
4030 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4034 if (total_data != POSIX_LOCK_DATA_SIZE) {
4036 req, NT_STATUS_INVALID_PARAMETER);
4040 /* Copy the lock range data. */
4041 lock_data = (char *)TALLOC_MEMDUP(
4042 ctx, pdata, total_data);
4044 reply_nterror(req, NT_STATUS_NO_MEMORY);
4052 *pparams = (char *)SMB_REALLOC(*pparams,2);
4053 if (*pparams == NULL) {
4054 reply_nterror(req, NT_STATUS_NO_MEMORY);
4059 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4060 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4061 if (*ppdata == NULL ) {
4062 reply_nterror(req, NT_STATUS_NO_MEMORY);
4067 dend = dstart + data_size - 1;
4069 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
4070 mtime_ts = get_mtimespec(&sbuf);
4071 atime_ts = get_atimespec(&sbuf);
4073 allocation_size = get_allocation_size(conn,fsp,&sbuf);
4076 if (!null_timespec(fsp->pending_modtime)) {
4077 /* the pending modtime overrides the current modtime */
4078 mtime_ts = fsp->pending_modtime;
4082 /* Do we have this path open ? */
4083 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4084 fsp1 = file_find_di_first(fileid);
4085 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
4086 /* the pending modtime overrides the current modtime */
4087 mtime_ts = fsp1->pending_modtime;
4089 if (fsp1 && fsp1->initial_allocation_size) {
4090 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
4094 if (lp_dos_filetime_resolution(SNUM(conn))) {
4095 dos_filetime_timespec(&create_time_ts);
4096 dos_filetime_timespec(&mtime_ts);
4097 dos_filetime_timespec(&atime_ts);
4100 create_time = convert_timespec_to_time_t(create_time_ts);
4101 mtime = convert_timespec_to_time_t(mtime_ts);
4102 atime = convert_timespec_to_time_t(atime_ts);
4104 /* NT expects the name to be in an exact form of the *full*
4105 filename. See the trans2 torture test */
4106 if (ISDOT(base_name)) {
4107 dos_fname = talloc_strdup(ctx, "\\");
4109 reply_nterror(req, NT_STATUS_NO_MEMORY);
4113 dos_fname = talloc_asprintf(ctx,
4117 reply_nterror(req, NT_STATUS_NO_MEMORY);
4120 string_replace(dos_fname, '/', '\\');
4123 switch (info_level) {
4124 case SMB_INFO_STANDARD:
4125 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4127 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4128 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4129 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4130 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4131 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4132 SSVAL(pdata,l1_attrFile,mode);
4135 case SMB_INFO_QUERY_EA_SIZE:
4137 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4138 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4140 srv_put_dos_date2(pdata,0,create_time);
4141 srv_put_dos_date2(pdata,4,atime);
4142 srv_put_dos_date2(pdata,8,mtime); /* write time */
4143 SIVAL(pdata,12,(uint32)file_size);
4144 SIVAL(pdata,16,(uint32)allocation_size);
4145 SSVAL(pdata,20,mode);
4146 SIVAL(pdata,22,ea_size);
4150 case SMB_INFO_IS_NAME_VALID:
4151 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4152 if (tran_call == TRANSACT2_QFILEINFO) {
4153 /* os/2 needs this ? really ?*/
4154 reply_doserror(req, ERRDOS, ERRbadfunc);
4161 case SMB_INFO_QUERY_EAS_FROM_LIST:
4163 size_t total_ea_len = 0;
4164 struct ea_list *ea_file_list = NULL;
4166 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4168 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4169 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4171 if (!ea_list || (total_ea_len > data_size)) {
4173 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4177 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4181 case SMB_INFO_QUERY_ALL_EAS:
4183 /* We have data_size bytes to put EA's into. */
4184 size_t total_ea_len = 0;
4186 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4188 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4189 if (!ea_list || (total_ea_len > data_size)) {
4191 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4195 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4199 case SMB_FILE_BASIC_INFORMATION:
4200 case SMB_QUERY_FILE_BASIC_INFO:
4202 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4203 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4204 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4206 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4210 put_long_date_timespec(pdata,create_time_ts);
4211 put_long_date_timespec(pdata+8,atime_ts);
4212 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4213 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4214 SIVAL(pdata,32,mode);
4216 DEBUG(5,("SMB_QFBI - "));
4217 DEBUG(5,("create: %s ", ctime(&create_time)));
4218 DEBUG(5,("access: %s ", ctime(&atime)));
4219 DEBUG(5,("write: %s ", ctime(&mtime)));
4220 DEBUG(5,("change: %s ", ctime(&mtime)));
4221 DEBUG(5,("mode: %x\n", mode));
4224 case SMB_FILE_STANDARD_INFORMATION:
4225 case SMB_QUERY_FILE_STANDARD_INFO:
4227 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4229 SOFF_T(pdata,0,allocation_size);
4230 SOFF_T(pdata,8,file_size);
4231 SIVAL(pdata,16,nlink);
4232 SCVAL(pdata,20,delete_pending?1:0);
4233 SCVAL(pdata,21,(mode&aDIR)?1:0);
4234 SSVAL(pdata,22,0); /* Padding. */
4237 case SMB_FILE_EA_INFORMATION:
4238 case SMB_QUERY_FILE_EA_INFO:
4240 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4241 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4243 SIVAL(pdata,0,ea_size);
4247 /* Get the 8.3 name - used if NT SMB was negotiated. */
4248 case SMB_QUERY_FILE_ALT_NAME_INFO:
4249 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4251 char mangled_name[13];
4252 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4253 if (!name_to_8_3(base_name,mangled_name,
4254 True,conn->params)) {
4257 NT_STATUS_NO_MEMORY);
4259 len = srvstr_push(dstart, req->flags2,
4260 pdata+4, mangled_name,
4261 PTR_DIFF(dend, pdata+4),
4263 data_size = 4 + len;
4268 case SMB_QUERY_FILE_NAME_INFO:
4270 this must be *exactly* right for ACLs on mapped drives to work
4272 len = srvstr_push(dstart, req->flags2,
4274 PTR_DIFF(dend, pdata+4),
4276 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4277 data_size = 4 + len;
4281 case SMB_FILE_ALLOCATION_INFORMATION:
4282 case SMB_QUERY_FILE_ALLOCATION_INFO:
4283 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4285 SOFF_T(pdata,0,allocation_size);
4288 case SMB_FILE_END_OF_FILE_INFORMATION:
4289 case SMB_QUERY_FILE_END_OF_FILEINFO:
4290 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4292 SOFF_T(pdata,0,file_size);
4295 case SMB_QUERY_FILE_ALL_INFO:
4296 case SMB_FILE_ALL_INFORMATION:
4298 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4299 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4300 put_long_date_timespec(pdata,create_time_ts);
4301 put_long_date_timespec(pdata+8,atime_ts);
4302 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4303 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4304 SIVAL(pdata,32,mode);
4305 SIVAL(pdata,36,0); /* padding. */
4307 SOFF_T(pdata,0,allocation_size);
4308 SOFF_T(pdata,8,file_size);
4309 SIVAL(pdata,16,nlink);
4310 SCVAL(pdata,20,delete_pending);
4311 SCVAL(pdata,21,(mode&aDIR)?1:0);
4314 SIVAL(pdata,0,ea_size);
4315 pdata += 4; /* EA info */
4316 len = srvstr_push(dstart, req->flags2,
4318 PTR_DIFF(dend, pdata+4),
4322 data_size = PTR_DIFF(pdata,(*ppdata));
4325 case SMB_FILE_INTERNAL_INFORMATION:
4326 /* This should be an index number - looks like
4329 I think this causes us to fail the IFSKIT
4330 BasicFileInformationTest. -tpot */
4332 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4333 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4334 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4338 case SMB_FILE_ACCESS_INFORMATION:
4339 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4340 SIVAL(pdata,0,access_mask);
4344 case SMB_FILE_NAME_INFORMATION:
4345 /* Pathname with leading '\'. */
4348 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4349 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4350 SIVAL(pdata,0,byte_len);
4351 data_size = 4 + byte_len;
4355 case SMB_FILE_DISPOSITION_INFORMATION:
4356 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4358 SCVAL(pdata,0,delete_pending);
4361 case SMB_FILE_POSITION_INFORMATION:
4362 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4364 SOFF_T(pdata,0,pos);
4367 case SMB_FILE_MODE_INFORMATION:
4368 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4369 SIVAL(pdata,0,mode);
4373 case SMB_FILE_ALIGNMENT_INFORMATION:
4374 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4375 SIVAL(pdata,0,0); /* No alignment needed. */
4380 * NT4 server just returns "invalid query" to this - if we try
4381 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4384 /* The first statement above is false - verified using Thursby
4385 * client against NT4 -- gcolley.
4387 case SMB_QUERY_FILE_STREAM_INFO:
4388 case SMB_FILE_STREAM_INFORMATION: {
4389 unsigned int num_streams;
4390 struct stream_struct *streams;
4393 DEBUG(10,("call_trans2qfilepathinfo: "
4394 "SMB_FILE_STREAM_INFORMATION\n"));
4396 status = SMB_VFS_STREAMINFO(
4397 conn, fsp, fname, talloc_tos(),
4398 &num_streams, &streams);
4400 if (!NT_STATUS_IS_OK(status)) {
4401 DEBUG(10, ("could not get stream info: %s\n",
4402 nt_errstr(status)));
4403 reply_nterror(req, status);
4407 status = marshall_stream_info(num_streams, streams,
4408 pdata, max_data_bytes,
4411 if (!NT_STATUS_IS_OK(status)) {
4412 DEBUG(10, ("marshall_stream_info failed: %s\n",
4413 nt_errstr(status)));
4414 reply_nterror(req, status);
4418 TALLOC_FREE(streams);
4422 case SMB_QUERY_COMPRESSION_INFO:
4423 case SMB_FILE_COMPRESSION_INFORMATION:
4424 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4425 SOFF_T(pdata,0,file_size);
4426 SIVAL(pdata,8,0); /* ??? */
4427 SIVAL(pdata,12,0); /* ??? */
4431 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4432 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4433 put_long_date_timespec(pdata,create_time_ts);
4434 put_long_date_timespec(pdata+8,atime_ts);
4435 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4436 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4437 SOFF_T(pdata,32,allocation_size);
4438 SOFF_T(pdata,40,file_size);
4439 SIVAL(pdata,48,mode);
4440 SIVAL(pdata,52,0); /* ??? */
4444 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4445 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4446 SIVAL(pdata,0,mode);
4452 * CIFS UNIX Extensions.
4455 case SMB_QUERY_FILE_UNIX_BASIC:
4457 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4458 data_size = PTR_DIFF(pdata,(*ppdata));
4462 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4464 for (i=0; i<100; i++)
4465 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4471 case SMB_QUERY_FILE_UNIX_INFO2:
4473 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4474 data_size = PTR_DIFF(pdata,(*ppdata));
4478 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4480 for (i=0; i<100; i++)
4481 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4487 case SMB_QUERY_FILE_UNIX_LINK:
4489 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4492 reply_nterror(req, NT_STATUS_NO_MEMORY);
4496 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4498 if(!S_ISLNK(sbuf.st_mode)) {
4499 reply_unixerror(req, ERRSRV,
4504 reply_unixerror(req, ERRDOS, ERRbadlink);
4507 len = SMB_VFS_READLINK(conn,fullpathname,
4510 reply_unixerror(req, ERRDOS,
4515 len = srvstr_push(dstart, req->flags2,
4517 PTR_DIFF(dend, pdata),
4520 data_size = PTR_DIFF(pdata,(*ppdata));
4525 #if defined(HAVE_POSIX_ACLS)
4526 case SMB_QUERY_POSIX_ACL:
4528 SMB_ACL_T file_acl = NULL;
4529 SMB_ACL_T def_acl = NULL;
4530 uint16 num_file_acls = 0;
4531 uint16 num_def_acls = 0;
4533 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4534 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4536 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4539 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4540 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4544 NT_STATUS_NOT_IMPLEMENTED);
4548 if (S_ISDIR(sbuf.st_mode)) {
4549 if (fsp && fsp->is_directory) {
4550 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4552 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4554 def_acl = free_empty_sys_acl(conn, def_acl);
4557 num_file_acls = count_acl_entries(conn, file_acl);
4558 num_def_acls = count_acl_entries(conn, def_acl);
4560 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4561 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4563 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4564 SMB_POSIX_ACL_HEADER_SIZE) ));
4566 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4569 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4573 NT_STATUS_BUFFER_TOO_SMALL);
4577 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4578 SSVAL(pdata,2,num_file_acls);
4579 SSVAL(pdata,4,num_def_acls);
4580 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4582 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4585 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4588 req, NT_STATUS_INTERNAL_ERROR);
4591 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4593 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4596 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4600 NT_STATUS_INTERNAL_ERROR);
4605 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4608 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4610 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4616 case SMB_QUERY_POSIX_LOCK:
4618 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4620 SMB_BIG_UINT offset;
4622 enum brl_type lock_type;
4624 if (total_data != POSIX_LOCK_DATA_SIZE) {
4626 req, NT_STATUS_INVALID_PARAMETER);
4630 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4631 case POSIX_LOCK_TYPE_READ:
4632 lock_type = READ_LOCK;
4634 case POSIX_LOCK_TYPE_WRITE:
4635 lock_type = WRITE_LOCK;
4637 case POSIX_LOCK_TYPE_UNLOCK:
4639 /* There's no point in asking for an unlock... */
4642 NT_STATUS_INVALID_PARAMETER);
4646 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4647 #if defined(HAVE_LONGLONG)
4648 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4649 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4650 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4651 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4652 #else /* HAVE_LONGLONG */
4653 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4654 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4655 #endif /* HAVE_LONGLONG */
4657 status = query_lock(fsp,
4664 if (ERROR_WAS_LOCK_DENIED(status)) {
4665 /* Here we need to report who has it locked... */
4666 data_size = POSIX_LOCK_DATA_SIZE;
4668 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4669 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4670 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4671 #if defined(HAVE_LONGLONG)
4672 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4673 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4674 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4675 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4676 #else /* HAVE_LONGLONG */
4677 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4678 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4679 #endif /* HAVE_LONGLONG */
4681 } else if (NT_STATUS_IS_OK(status)) {
4682 /* For success we just return a copy of what we sent
4683 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4684 data_size = POSIX_LOCK_DATA_SIZE;
4685 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4686 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4688 reply_nterror(req, status);
4695 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4699 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4705 /****************************************************************************
4706 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4708 ****************************************************************************/
4710 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4711 connection_struct *conn,
4712 const char *oldname_in,
4713 const char *newname_in)
4715 SMB_STRUCT_STAT sbuf1, sbuf2;
4716 char *last_component_oldname = NULL;
4717 char *last_component_newname = NULL;
4718 char *oldname = NULL;
4719 char *newname = NULL;
4720 NTSTATUS status = NT_STATUS_OK;
4725 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4726 &last_component_oldname, &sbuf1);
4727 if (!NT_STATUS_IS_OK(status)) {
4731 status = check_name(conn, oldname);
4732 if (!NT_STATUS_IS_OK(status)) {
4736 /* source must already exist. */
4737 if (!VALID_STAT(sbuf1)) {
4738 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4741 status = unix_convert(ctx, conn, newname_in, False, &newname,
4742 &last_component_newname, &sbuf2);
4743 if (!NT_STATUS_IS_OK(status)) {
4747 status = check_name(conn, newname);
4748 if (!NT_STATUS_IS_OK(status)) {
4752 /* Disallow if newname already exists. */
4753 if (VALID_STAT(sbuf2)) {
4754 return NT_STATUS_OBJECT_NAME_COLLISION;
4757 /* No links from a directory. */
4758 if (S_ISDIR(sbuf1.st_mode)) {
4759 return NT_STATUS_FILE_IS_A_DIRECTORY;
4762 /* Ensure this is within the share. */
4763 status = check_reduced_name(conn, oldname);
4764 if (!NT_STATUS_IS_OK(status)) {
4768 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4770 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4771 status = map_nt_error_from_unix(errno);
4772 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4773 nt_errstr(status), newname, oldname));
4779 /****************************************************************************
4780 Deal with setting the time from any of the setfilepathinfo functions.
4781 ****************************************************************************/
4783 static NTSTATUS smb_set_file_time(connection_struct *conn,
4786 const SMB_STRUCT_STAT *psbuf,
4787 struct timespec ts[2],
4788 bool setting_write_time)
4791 FILE_NOTIFY_CHANGE_LAST_ACCESS
4792 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4794 if (!VALID_STAT(*psbuf)) {
4795 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4798 /* get some defaults (no modifications) if any info is zero or -1. */
4799 if (null_timespec(ts[0])) {
4800 ts[0] = get_atimespec(psbuf);
4801 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4804 if (null_timespec(ts[1])) {
4805 ts[1] = get_mtimespec(psbuf);
4806 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4809 if (!setting_write_time) {
4810 /* ts[1] comes from change time, not write time. */
4811 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4814 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4815 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4818 * Try and set the times of this file if
4819 * they are different from the current values.
4823 struct timespec mts = get_mtimespec(psbuf);
4824 struct timespec ats = get_atimespec(psbuf);
4825 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4826 return NT_STATUS_OK;
4832 * This was a setfileinfo on an open file.
4833 * NT does this a lot. We also need to
4834 * set the time here, as it can be read by
4835 * FindFirst/FindNext and with the patch for bug #2045
4836 * in smbd/fileio.c it ensures that this timestamp is
4837 * kept sticky even after a write. We save the request
4838 * away and will set it on file close and after a write. JRA.
4841 if (!null_timespec(ts[1])) {
4842 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4843 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4844 fsp_set_pending_modtime(fsp, ts[1]);
4848 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4850 if(file_ntimes(conn, fname, ts)!=0) {
4851 return map_nt_error_from_unix(errno);
4853 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4855 return NT_STATUS_OK;
4858 /****************************************************************************
4859 Deal with setting the dosmode from any of the setfilepathinfo functions.
4860 ****************************************************************************/
4862 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4864 SMB_STRUCT_STAT *psbuf,
4867 if (!VALID_STAT(*psbuf)) {
4868 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4872 if (S_ISDIR(psbuf->st_mode)) {
4879 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4881 /* check the mode isn't different, before changing it */
4882 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4884 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4885 fname, (unsigned int)dosmode ));
4887 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
4888 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4889 fname, strerror(errno)));
4890 return map_nt_error_from_unix(errno);
4893 return NT_STATUS_OK;
4896 /****************************************************************************
4897 Deal with setting the size from any of the setfilepathinfo functions.
4898 ****************************************************************************/
4900 static NTSTATUS smb_set_file_size(connection_struct *conn,
4901 struct smb_request *req,
4904 SMB_STRUCT_STAT *psbuf,
4907 NTSTATUS status = NT_STATUS_OK;
4908 files_struct *new_fsp = NULL;
4910 if (!VALID_STAT(*psbuf)) {
4911 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4914 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4916 if (size == get_file_size(*psbuf)) {
4917 return NT_STATUS_OK;
4920 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4921 fname, (double)size ));
4923 if (fsp && fsp->fh->fd != -1) {
4924 /* Handle based call. */
4925 if (vfs_set_filelen(fsp, size) == -1) {
4926 return map_nt_error_from_unix(errno);
4928 return NT_STATUS_OK;
4931 status = open_file_ntcreate(conn, req, fname, psbuf,
4933 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4936 FILE_ATTRIBUTE_NORMAL,
4937 FORCE_OPLOCK_BREAK_TO_NONE,
4940 if (!NT_STATUS_IS_OK(status)) {
4941 /* NB. We check for open_was_deferred in the caller. */
4945 if (vfs_set_filelen(new_fsp, size) == -1) {
4946 status = map_nt_error_from_unix(errno);
4947 close_file(new_fsp,NORMAL_CLOSE);
4951 close_file(new_fsp,NORMAL_CLOSE);
4952 return NT_STATUS_OK;
4955 /****************************************************************************
4956 Deal with SMB_INFO_SET_EA.
4957 ****************************************************************************/
4959 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4965 struct ea_list *ea_list = NULL;
4966 TALLOC_CTX *ctx = NULL;
4967 NTSTATUS status = NT_STATUS_OK;
4969 if (total_data < 10) {
4971 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4972 length. They seem to have no effect. Bug #3212. JRA */
4974 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4975 /* We're done. We only get EA info in this call. */
4976 return NT_STATUS_OK;
4979 return NT_STATUS_INVALID_PARAMETER;
4982 if (IVAL(pdata,0) > total_data) {
4983 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4984 IVAL(pdata,0), (unsigned int)total_data));
4985 return NT_STATUS_INVALID_PARAMETER;
4989 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4991 return NT_STATUS_INVALID_PARAMETER;
4993 status = set_ea(conn, fsp, fname, ea_list);
4998 /****************************************************************************
4999 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5000 ****************************************************************************/
5002 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5007 SMB_STRUCT_STAT *psbuf)
5009 NTSTATUS status = NT_STATUS_OK;
5010 bool delete_on_close;
5013 if (total_data < 1) {
5014 return NT_STATUS_INVALID_PARAMETER;
5018 return NT_STATUS_INVALID_HANDLE;
5021 delete_on_close = (CVAL(pdata,0) ? True : False);
5022 dosmode = dos_mode(conn, fname, psbuf);
5024 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5025 "delete_on_close = %u\n",
5027 (unsigned int)dosmode,
5028 (unsigned int)delete_on_close ));
5030 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5032 if (!NT_STATUS_IS_OK(status)) {
5036 /* The set is across all open files on this dev/inode pair. */
5037 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
5038 return NT_STATUS_ACCESS_DENIED;
5040 return NT_STATUS_OK;
5043 /****************************************************************************
5044 Deal with SMB_FILE_POSITION_INFORMATION.
5045 ****************************************************************************/
5047 static NTSTATUS smb_file_position_information(connection_struct *conn,
5052 SMB_BIG_UINT position_information;
5054 if (total_data < 8) {
5055 return NT_STATUS_INVALID_PARAMETER;
5059 /* Ignore on pathname based set. */
5060 return NT_STATUS_OK;
5063 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
5064 #ifdef LARGE_SMB_OFF_T
5065 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5066 #else /* LARGE_SMB_OFF_T */
5067 if (IVAL(pdata,4) != 0) {
5068 /* more than 32 bits? */
5069 return NT_STATUS_INVALID_PARAMETER;
5071 #endif /* LARGE_SMB_OFF_T */
5073 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5074 fsp->fsp_name, (double)position_information ));
5075 fsp->fh->position_information = position_information;
5076 return NT_STATUS_OK;
5079 /****************************************************************************
5080 Deal with SMB_FILE_MODE_INFORMATION.
5081 ****************************************************************************/
5083 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5089 if (total_data < 4) {
5090 return NT_STATUS_INVALID_PARAMETER;
5092 mode = IVAL(pdata,0);
5093 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5094 return NT_STATUS_INVALID_PARAMETER;
5096 return NT_STATUS_OK;
5099 /****************************************************************************
5100 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5101 ****************************************************************************/
5103 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5104 struct smb_request *req,
5109 char *link_target = NULL;
5110 const char *newname = fname;
5111 NTSTATUS status = NT_STATUS_OK;
5112 TALLOC_CTX *ctx = talloc_tos();
5114 /* Set a symbolic link. */
5115 /* Don't allow this if follow links is false. */
5117 if (total_data == 0) {
5118 return NT_STATUS_INVALID_PARAMETER;
5121 if (!lp_symlinks(SNUM(conn))) {
5122 return NT_STATUS_ACCESS_DENIED;
5125 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5126 total_data, STR_TERMINATE);
5129 return NT_STATUS_INVALID_PARAMETER;
5132 /* !widelinks forces the target path to be within the share. */
5133 /* This means we can interpret the target as a pathname. */
5134 if (!lp_widelinks(SNUM(conn))) {
5135 char *rel_name = NULL;
5136 char *last_dirp = NULL;
5138 if (*link_target == '/') {
5139 /* No absolute paths allowed. */
5140 return NT_STATUS_ACCESS_DENIED;
5142 rel_name = talloc_strdup(ctx,newname);
5144 return NT_STATUS_NO_MEMORY;
5146 last_dirp = strrchr_m(rel_name, '/');
5148 last_dirp[1] = '\0';
5150 rel_name = talloc_strdup(ctx,"./");
5152 return NT_STATUS_NO_MEMORY;
5155 rel_name = talloc_asprintf_append(rel_name,
5159 return NT_STATUS_NO_MEMORY;
5162 status = check_name(conn, rel_name);
5163 if (!NT_STATUS_IS_OK(status)) {
5168 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5169 newname, link_target ));
5171 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5172 return map_nt_error_from_unix(errno);
5175 return NT_STATUS_OK;
5178 /****************************************************************************
5179 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5180 ****************************************************************************/
5182 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5183 struct smb_request *req,
5184 const char *pdata, int total_data,
5187 char *oldname = NULL;
5188 TALLOC_CTX *ctx = talloc_tos();
5189 NTSTATUS status = NT_STATUS_OK;
5191 /* Set a hard link. */
5192 if (total_data == 0) {
5193 return NT_STATUS_INVALID_PARAMETER;
5196 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5197 total_data, STR_TERMINATE, &status);
5198 if (!NT_STATUS_IS_OK(status)) {
5202 status = resolve_dfspath(ctx, conn,
5203 req->flags2 & FLAGS2_DFS_PATHNAMES,
5206 if (!NT_STATUS_IS_OK(status)) {
5210 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5213 return hardlink_internals(ctx, conn, oldname, fname);
5216 /****************************************************************************
5217 Deal with SMB_FILE_RENAME_INFORMATION.
5218 ****************************************************************************/
5220 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5221 struct smb_request *req,
5230 char *newname = NULL;
5231 char *base_name = NULL;
5232 bool dest_has_wcard = False;
5233 NTSTATUS status = NT_STATUS_OK;
5235 TALLOC_CTX *ctx = talloc_tos();
5237 if (total_data < 13) {
5238 return NT_STATUS_INVALID_PARAMETER;
5241 overwrite = (CVAL(pdata,0) ? True : False);
5242 root_fid = IVAL(pdata,4);
5243 len = IVAL(pdata,8);
5245 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5246 return NT_STATUS_INVALID_PARAMETER;
5249 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5252 if (!NT_STATUS_IS_OK(status)) {
5256 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5259 status = resolve_dfspath_wcard(ctx, conn,
5260 req->flags2 & FLAGS2_DFS_PATHNAMES,
5264 if (!NT_STATUS_IS_OK(status)) {
5268 /* Check the new name has no '/' characters. */
5269 if (strchr_m(newname, '/')) {
5270 return NT_STATUS_NOT_SUPPORTED;
5273 /* Create the base directory. */
5274 base_name = talloc_strdup(ctx, fname);
5276 return NT_STATUS_NO_MEMORY;
5278 p = strrchr_m(base_name, '/');
5282 base_name = talloc_strdup(ctx, "./");
5284 return NT_STATUS_NO_MEMORY;
5287 /* Append the new name. */
5288 base_name = talloc_asprintf_append(base_name,
5292 return NT_STATUS_NO_MEMORY;
5296 SMB_STRUCT_STAT sbuf;
5297 char *newname_last_component = NULL;
5301 status = unix_convert(ctx, conn, newname, False,
5303 &newname_last_component,
5306 /* If an error we expect this to be
5307 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5309 if (!NT_STATUS_IS_OK(status)
5310 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5315 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5316 fsp->fnum, fsp->fsp_name, base_name ));
5317 status = rename_internals_fsp(conn, fsp, base_name,
5318 newname_last_component, 0,
5321 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5322 fname, base_name ));
5323 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5324 overwrite, False, dest_has_wcard);
5330 /****************************************************************************
5331 Deal with SMB_SET_POSIX_ACL.
5332 ****************************************************************************/
5334 #if defined(HAVE_POSIX_ACLS)
5335 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5340 SMB_STRUCT_STAT *psbuf)
5342 uint16 posix_acl_version;
5343 uint16 num_file_acls;
5344 uint16 num_def_acls;
5345 bool valid_file_acls = True;
5346 bool valid_def_acls = True;
5348 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5349 return NT_STATUS_INVALID_PARAMETER;
5351 posix_acl_version = SVAL(pdata,0);
5352 num_file_acls = SVAL(pdata,2);
5353 num_def_acls = SVAL(pdata,4);
5355 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5356 valid_file_acls = False;
5360 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5361 valid_def_acls = False;
5365 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5366 return NT_STATUS_INVALID_PARAMETER;
5369 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5370 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5371 return NT_STATUS_INVALID_PARAMETER;
5374 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5375 fname ? fname : fsp->fsp_name,
5376 (unsigned int)num_file_acls,
5377 (unsigned int)num_def_acls));
5379 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5380 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5381 return map_nt_error_from_unix(errno);
5384 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5385 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5386 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5387 return map_nt_error_from_unix(errno);
5389 return NT_STATUS_OK;
5393 /****************************************************************************
5394 Deal with SMB_SET_POSIX_LOCK.
5395 ****************************************************************************/
5397 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5398 const struct smb_request *req,
5404 SMB_BIG_UINT offset;
5406 bool blocking_lock = False;
5407 enum brl_type lock_type;
5409 NTSTATUS status = NT_STATUS_OK;
5411 if (fsp == NULL || fsp->fh->fd == -1) {
5412 return NT_STATUS_INVALID_HANDLE;
5415 if (total_data != POSIX_LOCK_DATA_SIZE) {
5416 return NT_STATUS_INVALID_PARAMETER;
5419 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5420 case POSIX_LOCK_TYPE_READ:
5421 lock_type = READ_LOCK;
5423 case POSIX_LOCK_TYPE_WRITE:
5424 /* Return the right POSIX-mappable error code for files opened read-only. */
5425 if (!fsp->can_write) {
5426 return NT_STATUS_INVALID_HANDLE;
5428 lock_type = WRITE_LOCK;
5430 case POSIX_LOCK_TYPE_UNLOCK:
5431 lock_type = UNLOCK_LOCK;
5434 return NT_STATUS_INVALID_PARAMETER;
5437 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5438 blocking_lock = False;
5439 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5440 blocking_lock = True;
5442 return NT_STATUS_INVALID_PARAMETER;
5445 if (!lp_blocking_locks(SNUM(conn))) {
5446 blocking_lock = False;
5449 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5450 #if defined(HAVE_LONGLONG)
5451 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5452 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5453 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5454 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5455 #else /* HAVE_LONGLONG */
5456 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5457 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5458 #endif /* HAVE_LONGLONG */
5460 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5461 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5463 (unsigned int)lock_type,
5464 (unsigned int)lock_pid,
5468 if (lock_type == UNLOCK_LOCK) {
5469 status = do_unlock(smbd_messaging_context(),
5476 uint32 block_smbpid;
5478 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5489 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5491 * A blocking lock was requested. Package up
5492 * this smb into a queued request and push it
5493 * onto the blocking lock queue.
5495 if(push_blocking_lock_request(br_lck,
5498 -1, /* infinite timeout. */
5506 TALLOC_FREE(br_lck);
5510 TALLOC_FREE(br_lck);
5516 /****************************************************************************
5517 Deal with SMB_INFO_STANDARD.
5518 ****************************************************************************/
5520 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5525 const SMB_STRUCT_STAT *psbuf)
5527 struct timespec ts[2];
5529 if (total_data < 12) {
5530 return NT_STATUS_INVALID_PARAMETER;
5534 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5536 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5538 DEBUG(10,("smb_set_info_standard: file %s\n",
5539 fname ? fname : fsp->fsp_name ));
5541 return smb_set_file_time(conn,
5549 /****************************************************************************
5550 Deal with SMB_SET_FILE_BASIC_INFO.
5551 ****************************************************************************/
5553 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5558 SMB_STRUCT_STAT *psbuf)
5560 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5561 struct timespec write_time;
5562 struct timespec changed_time;
5564 struct timespec ts[2];
5565 NTSTATUS status = NT_STATUS_OK;
5566 bool setting_write_time = true;
5568 if (total_data < 36) {
5569 return NT_STATUS_INVALID_PARAMETER;
5572 /* Set the attributes */
5573 dosmode = IVAL(pdata,32);
5574 status = smb_set_file_dosmode(conn,
5578 if (!NT_STATUS_IS_OK(status)) {
5582 /* Ignore create time at offset pdata. */
5585 ts[0] = interpret_long_date(pdata+8);
5587 write_time = interpret_long_date(pdata+16);
5588 changed_time = interpret_long_date(pdata+24);
5591 ts[1] = timespec_min(&write_time, &changed_time);
5593 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5597 /* Prefer a defined time to an undefined one. */
5598 if (null_timespec(ts[1])) {
5599 if (null_timespec(write_time)) {
5600 ts[1] = changed_time;
5601 setting_write_time = false;
5607 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5608 fname ? fname : fsp->fsp_name ));
5610 return smb_set_file_time(conn,
5615 setting_write_time);
5618 /****************************************************************************
5619 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5620 ****************************************************************************/
5622 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5623 struct smb_request *req,
5628 SMB_STRUCT_STAT *psbuf)
5630 SMB_BIG_UINT allocation_size = 0;
5631 NTSTATUS status = NT_STATUS_OK;
5632 files_struct *new_fsp = NULL;
5634 if (!VALID_STAT(*psbuf)) {
5635 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5638 if (total_data < 8) {
5639 return NT_STATUS_INVALID_PARAMETER;
5642 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5643 #ifdef LARGE_SMB_OFF_T
5644 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5645 #else /* LARGE_SMB_OFF_T */
5646 if (IVAL(pdata,4) != 0) {
5647 /* more than 32 bits? */
5648 return NT_STATUS_INVALID_PARAMETER;
5650 #endif /* LARGE_SMB_OFF_T */
5652 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5653 fname, (double)allocation_size ));
5655 if (allocation_size) {
5656 allocation_size = smb_roundup(conn, allocation_size);
5659 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5660 fname, (double)allocation_size ));
5662 if (fsp && fsp->fh->fd != -1) {
5663 /* Open file handle. */
5664 /* Only change if needed. */
5665 if (allocation_size != get_file_size(*psbuf)) {
5666 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5667 return map_nt_error_from_unix(errno);
5670 /* But always update the time. */
5671 if (null_timespec(fsp->pending_modtime)) {
5673 * This is equivalent to a write. Ensure it's seen immediately
5674 * if there are no pending writes.
5676 set_filetime(fsp->conn, fsp->fsp_name,
5677 timespec_current());
5679 return NT_STATUS_OK;
5682 /* Pathname or stat or directory file. */
5684 status = open_file_ntcreate(conn, req, fname, psbuf,
5686 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5689 FILE_ATTRIBUTE_NORMAL,
5690 FORCE_OPLOCK_BREAK_TO_NONE,
5693 if (!NT_STATUS_IS_OK(status)) {
5694 /* NB. We check for open_was_deferred in the caller. */
5698 /* Only change if needed. */
5699 if (allocation_size != get_file_size(*psbuf)) {
5700 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5701 status = map_nt_error_from_unix(errno);
5702 close_file(new_fsp,NORMAL_CLOSE);
5707 /* Changing the allocation size should set the last mod time. */
5708 /* Don't need to call set_filetime as this will be flushed on
5711 fsp_set_pending_modtime(new_fsp, timespec_current());
5713 close_file(new_fsp,NORMAL_CLOSE);
5714 return NT_STATUS_OK;
5717 /****************************************************************************
5718 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5719 ****************************************************************************/
5721 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5722 struct smb_request *req,
5727 SMB_STRUCT_STAT *psbuf)
5731 if (total_data < 8) {
5732 return NT_STATUS_INVALID_PARAMETER;
5735 size = IVAL(pdata,0);
5736 #ifdef LARGE_SMB_OFF_T
5737 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5738 #else /* LARGE_SMB_OFF_T */
5739 if (IVAL(pdata,4) != 0) {
5740 /* more than 32 bits? */
5741 return NT_STATUS_INVALID_PARAMETER;
5743 #endif /* LARGE_SMB_OFF_T */
5744 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5745 "file %s to %.0f\n", fname, (double)size ));
5747 return smb_set_file_size(conn, req,
5754 /****************************************************************************
5755 Allow a UNIX info mknod.
5756 ****************************************************************************/
5758 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5762 SMB_STRUCT_STAT *psbuf)
5764 uint32 file_type = IVAL(pdata,56);
5765 #if defined(HAVE_MAKEDEV)
5766 uint32 dev_major = IVAL(pdata,60);
5767 uint32 dev_minor = IVAL(pdata,68);
5769 SMB_DEV_T dev = (SMB_DEV_T)0;
5770 uint32 raw_unixmode = IVAL(pdata,84);
5774 if (total_data < 100) {
5775 return NT_STATUS_INVALID_PARAMETER;
5778 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5779 if (!NT_STATUS_IS_OK(status)) {
5783 #if defined(HAVE_MAKEDEV)
5784 dev = makedev(dev_major, dev_minor);
5787 switch (file_type) {
5788 #if defined(S_IFIFO)
5789 case UNIX_TYPE_FIFO:
5790 unixmode |= S_IFIFO;
5793 #if defined(S_IFSOCK)
5794 case UNIX_TYPE_SOCKET:
5795 unixmode |= S_IFSOCK;
5798 #if defined(S_IFCHR)
5799 case UNIX_TYPE_CHARDEV:
5800 unixmode |= S_IFCHR;
5803 #if defined(S_IFBLK)
5804 case UNIX_TYPE_BLKDEV:
5805 unixmode |= S_IFBLK;
5809 return NT_STATUS_INVALID_PARAMETER;
5812 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5813 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5815 /* Ok - do the mknod. */
5816 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5817 return map_nt_error_from_unix(errno);
5820 /* If any of the other "set" calls fail we
5821 * don't want to end up with a half-constructed mknod.
5824 if (lp_inherit_perms(SNUM(conn))) {
5826 conn, parent_dirname(fname),
5830 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5831 status = map_nt_error_from_unix(errno);
5832 SMB_VFS_UNLINK(conn,fname);
5835 return NT_STATUS_OK;
5838 /****************************************************************************
5839 Deal with SMB_SET_FILE_UNIX_BASIC.
5840 ****************************************************************************/
5842 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5843 struct smb_request *req,
5848 SMB_STRUCT_STAT *psbuf)
5850 struct timespec ts[2];
5851 uint32 raw_unixmode;
5854 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5855 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5856 NTSTATUS status = NT_STATUS_OK;
5857 bool delete_on_fail = False;
5858 enum perm_type ptype;
5860 if (total_data < 100) {
5861 return NT_STATUS_INVALID_PARAMETER;
5864 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5865 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5866 size=IVAL(pdata,0); /* first 8 Bytes are size */
5867 #ifdef LARGE_SMB_OFF_T
5868 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5869 #else /* LARGE_SMB_OFF_T */
5870 if (IVAL(pdata,4) != 0) {
5871 /* more than 32 bits? */
5872 return NT_STATUS_INVALID_PARAMETER;
5874 #endif /* LARGE_SMB_OFF_T */
5877 ts[0] = interpret_long_date(pdata+24); /* access_time */
5878 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5879 set_owner = (uid_t)IVAL(pdata,40);
5880 set_grp = (gid_t)IVAL(pdata,48);
5881 raw_unixmode = IVAL(pdata,84);
5883 if (VALID_STAT(*psbuf)) {
5884 if (S_ISDIR(psbuf->st_mode)) {
5885 ptype = PERM_EXISTING_DIR;
5887 ptype = PERM_EXISTING_FILE;
5890 ptype = PERM_NEW_FILE;
5893 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5894 if (!NT_STATUS_IS_OK(status)) {
5898 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5899 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5900 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5902 if (!VALID_STAT(*psbuf)) {
5904 * The only valid use of this is to create character and block
5905 * devices, and named pipes. This is deprecated (IMHO) and
5906 * a new info level should be used for mknod. JRA.
5909 status = smb_unix_mknod(conn,
5914 if (!NT_STATUS_IS_OK(status)) {
5918 /* Ensure we don't try and change anything else. */
5919 raw_unixmode = SMB_MODE_NO_CHANGE;
5920 size = get_file_size(*psbuf);
5921 ts[0] = get_atimespec(psbuf);
5922 ts[1] = get_mtimespec(psbuf);
5924 * We continue here as we might want to change the
5927 delete_on_fail = True;
5931 /* Horrible backwards compatibility hack as an old server bug
5932 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5936 size = get_file_size(*psbuf);
5941 * Deal with the UNIX specific mode set.
5944 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5945 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5946 (unsigned int)unixmode, fname ));
5947 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5948 return map_nt_error_from_unix(errno);
5953 * Deal with the UNIX specific uid set.
5956 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5959 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
5960 (unsigned int)set_owner, fname ));
5962 if (S_ISLNK(psbuf->st_mode)) {
5963 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
5965 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
5969 status = map_nt_error_from_unix(errno);
5970 if (delete_on_fail) {
5971 SMB_VFS_UNLINK(conn,fname);
5978 * Deal with the UNIX specific gid set.
5981 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5982 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5983 (unsigned int)set_owner, fname ));
5984 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5985 status = map_nt_error_from_unix(errno);
5986 if (delete_on_fail) {
5987 SMB_VFS_UNLINK(conn,fname);
5993 /* Deal with any size changes. */
5995 status = smb_set_file_size(conn, req,
6000 if (!NT_STATUS_IS_OK(status)) {
6004 /* Deal with any time changes. */
6006 return smb_set_file_time(conn,
6014 /****************************************************************************
6015 Deal with SMB_SET_FILE_UNIX_INFO2.
6016 ****************************************************************************/
6018 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6019 struct smb_request *req,
6024 SMB_STRUCT_STAT *psbuf)
6030 if (total_data < 116) {
6031 return NT_STATUS_INVALID_PARAMETER;
6034 /* Start by setting all the fields that are common between UNIX_BASIC
6037 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6039 if (!NT_STATUS_IS_OK(status)) {
6043 smb_fflags = IVAL(pdata, 108);
6044 smb_fmask = IVAL(pdata, 112);
6046 /* NB: We should only attempt to alter the file flags if the client
6047 * sends a non-zero mask.
6049 if (smb_fmask != 0) {
6050 int stat_fflags = 0;
6052 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6054 /* Client asked to alter a flag we don't understand. */
6055 return NT_STATUS_INVALID_PARAMETER;
6058 if (fsp && fsp->fh->fd != -1) {
6059 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6060 return NT_STATUS_NOT_SUPPORTED;
6062 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6063 return map_nt_error_from_unix(errno);
6068 /* XXX: need to add support for changing the create_time here. You
6069 * can do this for paths on Darwin with setattrlist(2). The right way
6070 * to hook this up is probably by extending the VFS utimes interface.
6073 return NT_STATUS_OK;
6076 /****************************************************************************
6077 Create a directory with POSIX semantics.
6078 ****************************************************************************/
6080 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6081 struct smb_request *req,
6085 SMB_STRUCT_STAT *psbuf,
6086 int *pdata_return_size)
6088 NTSTATUS status = NT_STATUS_OK;
6089 uint32 raw_unixmode = 0;
6090 uint32 mod_unixmode = 0;
6091 mode_t unixmode = (mode_t)0;
6092 files_struct *fsp = NULL;
6093 uint16 info_level_return = 0;
6095 char *pdata = *ppdata;
6097 if (total_data < 18) {
6098 return NT_STATUS_INVALID_PARAMETER;
6101 raw_unixmode = IVAL(pdata,8);
6102 /* Next 4 bytes are not yet defined. */
6104 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6105 if (!NT_STATUS_IS_OK(status)) {
6109 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6111 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6112 fname, (unsigned int)unixmode ));
6114 status = open_directory(conn, req,
6117 FILE_READ_ATTRIBUTES, /* Just a stat open */
6118 FILE_SHARE_NONE, /* Ignored for stat opens */
6125 if (NT_STATUS_IS_OK(status)) {
6126 close_file(fsp, NORMAL_CLOSE);
6129 info_level_return = SVAL(pdata,16);
6131 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6132 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6133 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6134 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6136 *pdata_return_size = 12;
6139 /* Realloc the data size */
6140 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6141 if (*ppdata == NULL) {
6142 *pdata_return_size = 0;
6143 return NT_STATUS_NO_MEMORY;
6147 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6148 SSVAL(pdata,2,0); /* No fnum. */
6149 SIVAL(pdata,4,info); /* Was directory created. */
6151 switch (info_level_return) {
6152 case SMB_QUERY_FILE_UNIX_BASIC:
6153 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6154 SSVAL(pdata,10,0); /* Padding. */
6155 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6157 case SMB_QUERY_FILE_UNIX_INFO2:
6158 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6159 SSVAL(pdata,10,0); /* Padding. */
6160 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6163 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6164 SSVAL(pdata,10,0); /* Padding. */
6171 /****************************************************************************
6172 Open/Create a file with POSIX semantics.
6173 ****************************************************************************/
6175 static NTSTATUS smb_posix_open(connection_struct *conn,
6176 struct smb_request *req,
6180 SMB_STRUCT_STAT *psbuf,
6181 int *pdata_return_size)
6183 bool extended_oplock_granted = False;
6184 char *pdata = *ppdata;
6186 uint32 wire_open_mode = 0;
6187 uint32 raw_unixmode = 0;
6188 uint32 mod_unixmode = 0;
6189 uint32 create_disp = 0;
6190 uint32 access_mask = 0;
6191 uint32 create_options = 0;
6192 NTSTATUS status = NT_STATUS_OK;
6193 mode_t unixmode = (mode_t)0;
6194 files_struct *fsp = NULL;
6195 int oplock_request = 0;
6197 uint16 info_level_return = 0;
6199 if (total_data < 18) {
6200 return NT_STATUS_INVALID_PARAMETER;
6203 flags = IVAL(pdata,0);
6204 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6205 if (oplock_request) {
6206 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6209 wire_open_mode = IVAL(pdata,4);
6211 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6212 return smb_posix_mkdir(conn, req,
6220 switch (wire_open_mode & SMB_ACCMODE) {
6222 access_mask = FILE_READ_DATA;
6225 access_mask = FILE_WRITE_DATA;
6228 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6231 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6232 (unsigned int)wire_open_mode ));
6233 return NT_STATUS_INVALID_PARAMETER;
6236 wire_open_mode &= ~SMB_ACCMODE;
6238 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6239 create_disp = FILE_CREATE;
6240 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6241 create_disp = FILE_OVERWRITE_IF;
6242 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6243 create_disp = FILE_OPEN_IF;
6245 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6246 (unsigned int)wire_open_mode ));
6247 return NT_STATUS_INVALID_PARAMETER;
6250 raw_unixmode = IVAL(pdata,8);
6251 /* Next 4 bytes are not yet defined. */
6253 status = unix_perms_from_wire(conn,
6256 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6259 if (!NT_STATUS_IS_OK(status)) {
6263 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6265 if (wire_open_mode & SMB_O_SYNC) {
6266 create_options |= FILE_WRITE_THROUGH;
6268 if (wire_open_mode & SMB_O_APPEND) {
6269 access_mask |= FILE_APPEND_DATA;
6271 if (wire_open_mode & SMB_O_DIRECT) {
6272 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6275 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6277 (unsigned int)wire_open_mode,
6278 (unsigned int)unixmode ));
6280 status = open_file_ntcreate(conn, req,
6284 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6286 0, /* no create options yet. */
6292 if (!NT_STATUS_IS_OK(status)) {
6296 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6297 extended_oplock_granted = True;
6300 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6301 extended_oplock_granted = True;
6304 info_level_return = SVAL(pdata,16);
6306 /* Allocate the correct return size. */
6308 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6309 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6310 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6311 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6313 *pdata_return_size = 12;
6316 /* Realloc the data size */
6317 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6318 if (*ppdata == NULL) {
6319 close_file(fsp,ERROR_CLOSE);
6320 *pdata_return_size = 0;
6321 return NT_STATUS_NO_MEMORY;
6325 if (extended_oplock_granted) {
6326 if (flags & REQUEST_BATCH_OPLOCK) {
6327 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6329 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6331 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6332 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6334 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6337 SSVAL(pdata,2,fsp->fnum);
6338 SIVAL(pdata,4,info); /* Was file created etc. */
6340 switch (info_level_return) {
6341 case SMB_QUERY_FILE_UNIX_BASIC:
6342 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6343 SSVAL(pdata,10,0); /* padding. */
6344 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6346 case SMB_QUERY_FILE_UNIX_INFO2:
6347 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6348 SSVAL(pdata,10,0); /* padding. */
6349 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6352 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6353 SSVAL(pdata,10,0); /* padding. */
6356 return NT_STATUS_OK;
6359 /****************************************************************************
6360 Delete a file with POSIX semantics.
6361 ****************************************************************************/
6363 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6364 struct smb_request *req,
6368 SMB_STRUCT_STAT *psbuf)
6370 NTSTATUS status = NT_STATUS_OK;
6371 files_struct *fsp = NULL;
6376 struct share_mode_lock *lck = NULL;
6378 if (total_data < 2) {
6379 return NT_STATUS_INVALID_PARAMETER;
6382 flags = SVAL(pdata,0);
6384 if (!VALID_STAT(*psbuf)) {
6385 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6388 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6389 !VALID_STAT_OF_DIR(*psbuf)) {
6390 return NT_STATUS_NOT_A_DIRECTORY;
6393 DEBUG(10,("smb_posix_unlink: %s %s\n",
6394 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6397 if (VALID_STAT_OF_DIR(*psbuf)) {
6398 status = open_directory(conn, req,
6402 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6405 FILE_FLAG_POSIX_SEMANTICS|0777,
6410 status = open_file_ntcreate(conn, req,
6414 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6417 FILE_FLAG_POSIX_SEMANTICS|0777,
6418 0, /* No oplock, but break existing ones. */
6423 if (!NT_STATUS_IS_OK(status)) {
6428 * Don't lie to client. If we can't really delete due to
6429 * non-POSIX opens return SHARING_VIOLATION.
6432 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL);
6434 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6435 "lock for file %s\n", fsp->fsp_name));
6436 close_file(fsp, NORMAL_CLOSE);
6437 return NT_STATUS_INVALID_PARAMETER;
6441 * See if others still have the file open. If this is the case, then
6442 * don't delete. If all opens are POSIX delete we can set the delete
6443 * on close disposition.
6445 for (i=0; i<lck->num_share_modes; i++) {
6446 struct share_mode_entry *e = &lck->share_modes[i];
6447 if (is_valid_share_mode_entry(e)) {
6448 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6451 /* Fail with sharing violation. */
6452 close_file(fsp, NORMAL_CLOSE);
6454 return NT_STATUS_SHARING_VIOLATION;
6459 * Set the delete on close.
6461 status = smb_set_file_disposition_info(conn,
6468 if (!NT_STATUS_IS_OK(status)) {
6469 close_file(fsp, NORMAL_CLOSE);
6474 return close_file(fsp, NORMAL_CLOSE);
6477 /****************************************************************************
6478 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6479 ****************************************************************************/
6481 static void call_trans2setfilepathinfo(connection_struct *conn,
6482 struct smb_request *req,
6483 unsigned int tran_call,
6484 char **pparams, int total_params,
6485 char **ppdata, int total_data,
6486 unsigned int max_data_bytes)
6488 char *params = *pparams;
6489 char *pdata = *ppdata;
6491 SMB_STRUCT_STAT sbuf;
6493 files_struct *fsp = NULL;
6494 NTSTATUS status = NT_STATUS_OK;
6495 int data_return_size = 0;
6496 TALLOC_CTX *ctx = talloc_tos();
6499 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6505 if (tran_call == TRANSACT2_SETFILEINFO) {
6506 if (total_params < 4) {
6507 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6511 fsp = file_fsp(SVAL(params,0));
6512 /* Basic check for non-null fsp. */
6513 if (!check_fsp_open(conn, req, fsp, ¤t_user)) {
6516 info_level = SVAL(params,2);
6518 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6520 reply_nterror(req, NT_STATUS_NO_MEMORY);
6524 if(fsp->is_directory || fsp->fh->fd == -1) {
6526 * This is actually a SETFILEINFO on a directory
6527 * handle (returned from an NT SMB). NT5.0 seems
6528 * to do this call. JRA.
6530 if (INFO_LEVEL_IS_UNIX(info_level)) {
6531 /* Always do lstat for UNIX calls. */
6532 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6533 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6534 reply_unixerror(req,ERRDOS,ERRbadpath);
6538 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6539 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6540 reply_unixerror(req,ERRDOS,ERRbadpath);
6544 } else if (fsp->print_file) {
6546 * Doing a DELETE_ON_CLOSE should cancel a print job.
6548 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6549 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6551 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6554 send_trans2_replies(conn, req, params, 2,
6559 reply_unixerror(req, ERRDOS, ERRbadpath);
6564 * Original code - this is an open file.
6566 if (!check_fsp(conn, req, fsp, ¤t_user)) {
6570 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6571 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6572 reply_unixerror(req, ERRDOS, ERRbadfid);
6578 if (total_params < 7) {
6579 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6583 info_level = SVAL(params,0);
6584 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
6585 total_params - 6, STR_TERMINATE,
6587 if (!NT_STATUS_IS_OK(status)) {
6588 reply_nterror(req, status);
6592 status = resolve_dfspath(ctx, conn,
6593 req->flags2 & FLAGS2_DFS_PATHNAMES,
6596 if (!NT_STATUS_IS_OK(status)) {
6597 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6598 reply_botherror(req,
6599 NT_STATUS_PATH_NOT_COVERED,
6600 ERRSRV, ERRbadpath);
6603 reply_nterror(req, status);
6607 status = unix_convert(ctx, conn, fname, False,
6608 &fname, NULL, &sbuf);
6609 if (!NT_STATUS_IS_OK(status)) {
6610 reply_nterror(req, status);
6614 status = check_name(conn, fname);
6615 if (!NT_STATUS_IS_OK(status)) {
6616 reply_nterror(req, status);
6620 if (INFO_LEVEL_IS_UNIX(info_level)) {
6622 * For CIFS UNIX extensions the target name may not exist.
6625 /* Always do lstat for UNIX calls. */
6626 SMB_VFS_LSTAT(conn,fname,&sbuf);
6628 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6629 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6630 reply_unixerror(req, ERRDOS, ERRbadpath);
6635 if (!CAN_WRITE(conn)) {
6636 reply_doserror(req, ERRSRV, ERRaccess);
6640 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6641 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6645 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6646 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6648 /* Realloc the parameter size */
6649 *pparams = (char *)SMB_REALLOC(*pparams,2);
6650 if (*pparams == NULL) {
6651 reply_nterror(req, NT_STATUS_NO_MEMORY);
6658 if (fsp && !null_timespec(fsp->pending_modtime)) {
6659 /* the pending modtime overrides the current modtime */
6660 set_mtimespec(&sbuf, fsp->pending_modtime);
6663 switch (info_level) {
6665 case SMB_INFO_STANDARD:
6667 status = smb_set_info_standard(conn,
6676 case SMB_INFO_SET_EA:
6678 status = smb_info_set_ea(conn,
6686 case SMB_SET_FILE_BASIC_INFO:
6687 case SMB_FILE_BASIC_INFORMATION:
6689 status = smb_set_file_basic_info(conn,
6698 case SMB_FILE_ALLOCATION_INFORMATION:
6699 case SMB_SET_FILE_ALLOCATION_INFO:
6701 status = smb_set_file_allocation_info(conn, req,
6710 case SMB_FILE_END_OF_FILE_INFORMATION:
6711 case SMB_SET_FILE_END_OF_FILE_INFO:
6713 status = smb_set_file_end_of_file_info(conn, req,
6722 case SMB_FILE_DISPOSITION_INFORMATION:
6723 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6726 /* JRA - We used to just ignore this on a path ?
6727 * Shouldn't this be invalid level on a pathname
6730 if (tran_call != TRANSACT2_SETFILEINFO) {
6731 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6734 status = smb_set_file_disposition_info(conn,
6743 case SMB_FILE_POSITION_INFORMATION:
6745 status = smb_file_position_information(conn,
6752 /* From tridge Samba4 :
6753 * MODE_INFORMATION in setfileinfo (I have no
6754 * idea what "mode information" on a file is - it takes a value of 0,
6755 * 2, 4 or 6. What could it be?).
6758 case SMB_FILE_MODE_INFORMATION:
6760 status = smb_file_mode_information(conn,
6767 * CIFS UNIX extensions.
6770 case SMB_SET_FILE_UNIX_BASIC:
6772 status = smb_set_file_unix_basic(conn, req,
6781 case SMB_SET_FILE_UNIX_INFO2:
6783 status = smb_set_file_unix_info2(conn, req,
6792 case SMB_SET_FILE_UNIX_LINK:
6794 if (tran_call != TRANSACT2_SETPATHINFO) {
6795 /* We must have a pathname for this. */
6796 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6799 status = smb_set_file_unix_link(conn, req, pdata,
6804 case SMB_SET_FILE_UNIX_HLINK:
6806 if (tran_call != TRANSACT2_SETPATHINFO) {
6807 /* We must have a pathname for this. */
6808 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6811 status = smb_set_file_unix_hlink(conn, req,
6817 case SMB_FILE_RENAME_INFORMATION:
6819 status = smb_file_rename_information(conn, req,
6825 #if defined(HAVE_POSIX_ACLS)
6826 case SMB_SET_POSIX_ACL:
6828 status = smb_set_posix_acl(conn,
6838 case SMB_SET_POSIX_LOCK:
6840 if (tran_call != TRANSACT2_SETFILEINFO) {
6841 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6844 status = smb_set_posix_lock(conn, req,
6845 pdata, total_data, fsp);
6849 case SMB_POSIX_PATH_OPEN:
6851 if (tran_call != TRANSACT2_SETPATHINFO) {
6852 /* We must have a pathname for this. */
6853 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6857 status = smb_posix_open(conn, req,
6866 case SMB_POSIX_PATH_UNLINK:
6868 if (tran_call != TRANSACT2_SETPATHINFO) {
6869 /* We must have a pathname for this. */
6870 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6874 status = smb_posix_unlink(conn, req,
6883 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6888 if (!NT_STATUS_IS_OK(status)) {
6889 if (open_was_deferred(req->mid)) {
6890 /* We have re-scheduled this call. */
6893 if (blocking_lock_was_deferred(req->mid)) {
6894 /* We have re-scheduled this call. */
6897 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6898 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6899 ERRSRV, ERRbadpath);
6902 if (info_level == SMB_POSIX_PATH_OPEN) {
6903 reply_openerror(req, status);
6907 reply_nterror(req, status);
6912 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
6918 /****************************************************************************
6919 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6920 ****************************************************************************/
6922 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
6923 char **pparams, int total_params,
6924 char **ppdata, int total_data,
6925 unsigned int max_data_bytes)
6927 char *params = *pparams;
6928 char *pdata = *ppdata;
6929 char *directory = NULL;
6930 SMB_STRUCT_STAT sbuf;
6931 NTSTATUS status = NT_STATUS_OK;
6932 struct ea_list *ea_list = NULL;
6933 TALLOC_CTX *ctx = talloc_tos();
6935 if (!CAN_WRITE(conn)) {
6936 reply_doserror(req, ERRSRV, ERRaccess);
6940 if (total_params < 5) {
6941 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6945 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
6946 total_params - 4, STR_TERMINATE,
6948 if (!NT_STATUS_IS_OK(status)) {
6949 reply_nterror(req, status);
6953 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6955 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
6956 if (!NT_STATUS_IS_OK(status)) {
6957 reply_nterror(req, status);
6961 status = check_name(conn, directory);
6962 if (!NT_STATUS_IS_OK(status)) {
6963 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6964 reply_nterror(req, status);
6968 /* Any data in this call is an EA list. */
6969 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6970 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6975 * OS/2 workplace shell seems to send SET_EA requests of "null"
6976 * length (4 bytes containing IVAL 4).
6977 * They seem to have no effect. Bug #3212. JRA.
6980 if (total_data != 4) {
6981 if (total_data < 10) {
6982 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6986 if (IVAL(pdata,0) > total_data) {
6987 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6988 IVAL(pdata,0), (unsigned int)total_data));
6989 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6993 ea_list = read_ea_list(talloc_tos(), pdata + 4,
6996 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6999 } else if (IVAL(pdata,0) != 4) {
7000 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7004 status = create_directory(conn, req, directory);
7006 if (!NT_STATUS_IS_OK(status)) {
7007 reply_nterror(req, status);
7011 /* Try and set any given EA. */
7013 status = set_ea(conn, NULL, directory, ea_list);
7014 if (!NT_STATUS_IS_OK(status)) {
7015 reply_nterror(req, status);
7020 /* Realloc the parameter and data sizes */
7021 *pparams = (char *)SMB_REALLOC(*pparams,2);
7022 if(*pparams == NULL) {
7023 reply_nterror(req, NT_STATUS_NO_MEMORY);
7030 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7035 /****************************************************************************
7036 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7037 We don't actually do this - we just send a null response.
7038 ****************************************************************************/
7040 static void call_trans2findnotifyfirst(connection_struct *conn,
7041 struct smb_request *req,
7042 char **pparams, int total_params,
7043 char **ppdata, int total_data,
7044 unsigned int max_data_bytes)
7046 static uint16 fnf_handle = 257;
7047 char *params = *pparams;
7050 if (total_params < 6) {
7051 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7055 info_level = SVAL(params,4);
7056 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7058 switch (info_level) {
7063 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7067 /* Realloc the parameter and data sizes */
7068 *pparams = (char *)SMB_REALLOC(*pparams,6);
7069 if (*pparams == NULL) {
7070 reply_nterror(req, NT_STATUS_NO_MEMORY);
7075 SSVAL(params,0,fnf_handle);
7076 SSVAL(params,2,0); /* No changes */
7077 SSVAL(params,4,0); /* No EA errors */
7084 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7089 /****************************************************************************
7090 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7091 changes). Currently this does nothing.
7092 ****************************************************************************/
7094 static void call_trans2findnotifynext(connection_struct *conn,
7095 struct smb_request *req,
7096 char **pparams, int total_params,
7097 char **ppdata, int total_data,
7098 unsigned int max_data_bytes)
7100 char *params = *pparams;
7102 DEBUG(3,("call_trans2findnotifynext\n"));
7104 /* Realloc the parameter and data sizes */
7105 *pparams = (char *)SMB_REALLOC(*pparams,4);
7106 if (*pparams == NULL) {
7107 reply_nterror(req, NT_STATUS_NO_MEMORY);
7112 SSVAL(params,0,0); /* No changes */
7113 SSVAL(params,2,0); /* No EA errors */
7115 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7120 /****************************************************************************
7121 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7122 ****************************************************************************/
7124 static void call_trans2getdfsreferral(connection_struct *conn,
7125 struct smb_request *req,
7126 char **pparams, int total_params,
7127 char **ppdata, int total_data,
7128 unsigned int max_data_bytes)
7130 char *params = *pparams;
7131 char *pathname = NULL;
7133 int max_referral_level;
7134 NTSTATUS status = NT_STATUS_OK;
7135 TALLOC_CTX *ctx = talloc_tos();
7137 DEBUG(10,("call_trans2getdfsreferral\n"));
7139 if (total_params < 3) {
7140 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7144 max_referral_level = SVAL(params,0);
7146 if(!lp_host_msdfs()) {
7147 reply_doserror(req, ERRDOS, ERRbadfunc);
7151 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7152 total_params - 2, STR_TERMINATE);
7154 reply_nterror(req, NT_STATUS_NOT_FOUND);
7157 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7158 ppdata,&status)) < 0) {
7159 reply_nterror(req, status);
7163 SSVAL(req->inbuf, smb_flg2,
7164 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7165 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7170 #define LMCAT_SPL 0x53
7171 #define LMFUNC_GETJOBID 0x60
7173 /****************************************************************************
7174 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7175 ****************************************************************************/
7177 static void call_trans2ioctl(connection_struct *conn,
7178 struct smb_request *req,
7179 char **pparams, int total_params,
7180 char **ppdata, int total_data,
7181 unsigned int max_data_bytes)
7183 char *pdata = *ppdata;
7184 files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15));
7186 /* check for an invalid fid before proceeding */
7189 reply_doserror(req, ERRDOS, ERRbadfid);
7193 if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7194 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7195 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7196 if (*ppdata == NULL) {
7197 reply_nterror(req, NT_STATUS_NO_MEMORY);
7202 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7203 CAN ACCEPT THIS IN UNICODE. JRA. */
7205 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7206 srvstr_push(pdata, req->flags2, pdata + 2,
7207 global_myname(), 15,
7208 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7209 srvstr_push(pdata, req->flags2, pdata+18,
7210 lp_servicename(SNUM(conn)), 13,
7211 STR_ASCII|STR_TERMINATE); /* Service name */
7212 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7217 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7218 reply_doserror(req, ERRSRV, ERRerror);
7221 /****************************************************************************
7222 Reply to a SMBfindclose (stop trans2 directory search).
7223 ****************************************************************************/
7225 void reply_findclose(struct smb_request *req)
7229 START_PROFILE(SMBfindclose);
7232 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7233 END_PROFILE(SMBfindclose);
7237 dptr_num = SVALS(req->inbuf,smb_vwv0);
7239 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7241 dptr_close(&dptr_num);
7243 reply_outbuf(req, 0, 0);
7245 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7247 END_PROFILE(SMBfindclose);
7251 /****************************************************************************
7252 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7253 ****************************************************************************/
7255 void reply_findnclose(struct smb_request *req)
7259 START_PROFILE(SMBfindnclose);
7262 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7263 END_PROFILE(SMBfindnclose);
7267 dptr_num = SVAL(req->inbuf,smb_vwv0);
7269 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7271 /* We never give out valid handles for a
7272 findnotifyfirst - so any dptr_num is ok here.
7275 reply_outbuf(req, 0, 0);
7277 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7279 END_PROFILE(SMBfindnclose);
7283 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7284 struct trans_state *state)
7286 if (Protocol >= PROTOCOL_NT1) {
7287 req->flags2 |= 0x40; /* IS_LONG_NAME */
7288 SSVAL(req->inbuf,smb_flg2,req->flags2);
7291 if (conn->encrypt_level == Required && !req->encrypted) {
7292 if (state->call != TRANSACT2_QFSINFO &&
7293 state->call != TRANSACT2_SETFSINFO) {
7294 DEBUG(0,("handle_trans2: encryption required "
7296 (unsigned int)state->call));
7297 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7302 /* Now we must call the relevant TRANS2 function */
7303 switch(state->call) {
7304 case TRANSACT2_OPEN:
7306 START_PROFILE(Trans2_open);
7307 call_trans2open(conn, req,
7308 &state->param, state->total_param,
7309 &state->data, state->total_data,
7310 state->max_data_return);
7311 END_PROFILE(Trans2_open);
7315 case TRANSACT2_FINDFIRST:
7317 START_PROFILE(Trans2_findfirst);
7318 call_trans2findfirst(conn, req,
7319 &state->param, state->total_param,
7320 &state->data, state->total_data,
7321 state->max_data_return);
7322 END_PROFILE(Trans2_findfirst);
7326 case TRANSACT2_FINDNEXT:
7328 START_PROFILE(Trans2_findnext);
7329 call_trans2findnext(conn, req,
7330 &state->param, state->total_param,
7331 &state->data, state->total_data,
7332 state->max_data_return);
7333 END_PROFILE(Trans2_findnext);
7337 case TRANSACT2_QFSINFO:
7339 START_PROFILE(Trans2_qfsinfo);
7340 call_trans2qfsinfo(conn, req,
7341 &state->param, state->total_param,
7342 &state->data, state->total_data,
7343 state->max_data_return);
7344 END_PROFILE(Trans2_qfsinfo);
7348 case TRANSACT2_SETFSINFO:
7350 START_PROFILE(Trans2_setfsinfo);
7351 call_trans2setfsinfo(conn, req,
7352 &state->param, state->total_param,
7353 &state->data, state->total_data,
7354 state->max_data_return);
7355 END_PROFILE(Trans2_setfsinfo);
7359 case TRANSACT2_QPATHINFO:
7360 case TRANSACT2_QFILEINFO:
7362 START_PROFILE(Trans2_qpathinfo);
7363 call_trans2qfilepathinfo(conn, req, state->call,
7364 &state->param, state->total_param,
7365 &state->data, state->total_data,
7366 state->max_data_return);
7367 END_PROFILE(Trans2_qpathinfo);
7371 case TRANSACT2_SETPATHINFO:
7372 case TRANSACT2_SETFILEINFO:
7374 START_PROFILE(Trans2_setpathinfo);
7375 call_trans2setfilepathinfo(conn, req, state->call,
7376 &state->param, state->total_param,
7377 &state->data, state->total_data,
7378 state->max_data_return);
7379 END_PROFILE(Trans2_setpathinfo);
7383 case TRANSACT2_FINDNOTIFYFIRST:
7385 START_PROFILE(Trans2_findnotifyfirst);
7386 call_trans2findnotifyfirst(conn, req,
7387 &state->param, state->total_param,
7388 &state->data, state->total_data,
7389 state->max_data_return);
7390 END_PROFILE(Trans2_findnotifyfirst);
7394 case TRANSACT2_FINDNOTIFYNEXT:
7396 START_PROFILE(Trans2_findnotifynext);
7397 call_trans2findnotifynext(conn, req,
7398 &state->param, state->total_param,
7399 &state->data, state->total_data,
7400 state->max_data_return);
7401 END_PROFILE(Trans2_findnotifynext);
7405 case TRANSACT2_MKDIR:
7407 START_PROFILE(Trans2_mkdir);
7408 call_trans2mkdir(conn, req,
7409 &state->param, state->total_param,
7410 &state->data, state->total_data,
7411 state->max_data_return);
7412 END_PROFILE(Trans2_mkdir);
7416 case TRANSACT2_GET_DFS_REFERRAL:
7418 START_PROFILE(Trans2_get_dfs_referral);
7419 call_trans2getdfsreferral(conn, req,
7420 &state->param, state->total_param,
7421 &state->data, state->total_data,
7422 state->max_data_return);
7423 END_PROFILE(Trans2_get_dfs_referral);
7427 case TRANSACT2_IOCTL:
7429 START_PROFILE(Trans2_ioctl);
7430 call_trans2ioctl(conn, req,
7431 &state->param, state->total_param,
7432 &state->data, state->total_data,
7433 state->max_data_return);
7434 END_PROFILE(Trans2_ioctl);
7439 /* Error in request */
7440 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7441 reply_doserror(req, ERRSRV,ERRerror);
7445 /****************************************************************************
7446 Reply to a SMBtrans2.
7447 ****************************************************************************/
7449 void reply_trans2(struct smb_request *req)
7451 connection_struct *conn = req->conn;
7456 unsigned int tran_call;
7458 struct trans_state *state;
7461 START_PROFILE(SMBtrans2);
7463 if (req->wct < 14) {
7464 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7465 END_PROFILE(SMBtrans2);
7469 dsoff = SVAL(req->inbuf, smb_dsoff);
7470 dscnt = SVAL(req->inbuf, smb_dscnt);
7471 psoff = SVAL(req->inbuf, smb_psoff);
7472 pscnt = SVAL(req->inbuf, smb_pscnt);
7473 tran_call = SVAL(req->inbuf, smb_setup0);
7474 size = smb_len(req->inbuf) + 4;
7476 result = allow_new_trans(conn->pending_trans, req->mid);
7477 if (!NT_STATUS_IS_OK(result)) {
7478 DEBUG(2, ("Got invalid trans2 request: %s\n",
7479 nt_errstr(result)));
7480 reply_nterror(req, result);
7481 END_PROFILE(SMBtrans2);
7486 switch (tran_call) {
7487 /* List the allowed trans2 calls on IPC$ */
7488 case TRANSACT2_OPEN:
7489 case TRANSACT2_GET_DFS_REFERRAL:
7490 case TRANSACT2_QFILEINFO:
7491 case TRANSACT2_QFSINFO:
7492 case TRANSACT2_SETFSINFO:
7495 reply_doserror(req, ERRSRV, ERRaccess);
7496 END_PROFILE(SMBtrans2);
7501 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
7502 DEBUG(0, ("talloc failed\n"));
7503 reply_nterror(req, NT_STATUS_NO_MEMORY);
7504 END_PROFILE(SMBtrans2);
7508 state->cmd = SMBtrans2;
7510 state->mid = req->mid;
7511 state->vuid = req->vuid;
7512 state->setup_count = SVAL(req->inbuf, smb_suwcnt);
7513 state->setup = NULL;
7514 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7515 state->param = NULL;
7516 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7518 state->max_param_return = SVAL(req->inbuf, smb_mprcnt);
7519 state->max_data_return = SVAL(req->inbuf, smb_mdrcnt);
7520 state->max_setup_return = SVAL(req->inbuf, smb_msrcnt);
7521 state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0);
7522 state->one_way = BITSETW(req->inbuf+smb_vwv5,1);
7524 state->call = tran_call;
7526 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7527 is so as a sanity check */
7528 if (state->setup_count != 1) {
7530 * Need to have rc=0 for ioctl to get job id for OS/2.
7531 * Network printing will fail if function is not successful.
7532 * Similar function in reply.c will be used if protocol
7533 * is LANMAN1.0 instead of LM1.2X002.
7534 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7535 * outbuf doesn't have to be set(only job id is used).
7537 if ( (state->setup_count == 4)
7538 && (tran_call == TRANSACT2_IOCTL)
7539 && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7540 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7541 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7543 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7544 DEBUG(2,("Transaction is %d\n",tran_call));
7546 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7547 END_PROFILE(SMBtrans2);
7552 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7555 if (state->total_data) {
7556 /* Can't use talloc here, the core routines do realloc on the
7557 * params and data. */
7558 state->data = (char *)SMB_MALLOC(state->total_data);
7559 if (state->data == NULL) {
7560 DEBUG(0,("reply_trans2: data malloc fail for %u "
7561 "bytes !\n", (unsigned int)state->total_data));
7563 reply_nterror(req, NT_STATUS_NO_MEMORY);
7564 END_PROFILE(SMBtrans2);
7567 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
7569 if ((smb_base(req->inbuf)+dsoff+dscnt
7570 > (char *)req->inbuf + size) ||
7571 (smb_base(req->inbuf)+dsoff+dscnt < smb_base(req->inbuf)))
7574 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7577 if (state->total_param) {
7578 /* Can't use talloc here, the core routines do realloc on the
7579 * params and data. */
7580 state->param = (char *)SMB_MALLOC(state->total_param);
7581 if (state->param == NULL) {
7582 DEBUG(0,("reply_trans: param malloc fail for %u "
7583 "bytes !\n", (unsigned int)state->total_param));
7584 SAFE_FREE(state->data);
7586 reply_nterror(req, NT_STATUS_NO_MEMORY);
7587 END_PROFILE(SMBtrans2);
7590 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
7592 if ((smb_base(req->inbuf)+psoff+pscnt
7593 > (char *)req->inbuf + size) ||
7594 (smb_base(req->inbuf)+psoff+pscnt < smb_base(req->inbuf)))
7597 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7600 state->received_data = dscnt;
7601 state->received_param = pscnt;
7603 if ((state->received_param == state->total_param) &&
7604 (state->received_data == state->total_data)) {
7606 handle_trans2(conn, req, state);
7608 SAFE_FREE(state->data);
7609 SAFE_FREE(state->param);
7611 END_PROFILE(SMBtrans2);
7615 DLIST_ADD(conn->pending_trans, state);
7617 /* We need to send an interim response then receive the rest
7618 of the parameter/data bytes */
7619 reply_outbuf(req, 0, 0);
7620 show_msg((char *)req->outbuf);
7621 END_PROFILE(SMBtrans2);
7626 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7627 SAFE_FREE(state->data);
7628 SAFE_FREE(state->param);
7630 END_PROFILE(SMBtrans2);
7631 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7635 /****************************************************************************
7636 Reply to a SMBtranss2
7637 ****************************************************************************/
7639 void reply_transs2(struct smb_request *req)
7641 connection_struct *conn = req->conn;
7642 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7643 struct trans_state *state;
7646 START_PROFILE(SMBtranss2);
7648 show_msg((char *)req->inbuf);
7651 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7652 END_PROFILE(SMBtranss2);
7656 size = smb_len(req->inbuf)+4;
7658 for (state = conn->pending_trans; state != NULL;
7659 state = state->next) {
7660 if (state->mid == req->mid) {
7665 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7666 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7667 END_PROFILE(SMBtranss2);
7671 /* Revise state->total_param and state->total_data in case they have
7672 changed downwards */
7674 if (SVAL(req->inbuf, smb_tpscnt) < state->total_param)
7675 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7676 if (SVAL(req->inbuf, smb_tdscnt) < state->total_data)
7677 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7679 pcnt = SVAL(req->inbuf, smb_spscnt);
7680 poff = SVAL(req->inbuf, smb_spsoff);
7681 pdisp = SVAL(req->inbuf, smb_spsdisp);
7683 dcnt = SVAL(req->inbuf, smb_sdscnt);
7684 doff = SVAL(req->inbuf, smb_sdsoff);
7685 ddisp = SVAL(req->inbuf, smb_sdsdisp);
7687 state->received_param += pcnt;
7688 state->received_data += dcnt;
7690 if ((state->received_data > state->total_data) ||
7691 (state->received_param > state->total_param))
7695 if (pdisp+pcnt > state->total_param)
7697 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
7699 if (pdisp > state->total_param)
7701 if ((smb_base(req->inbuf) + poff + pcnt
7702 > (char *)req->inbuf + size) ||
7703 (smb_base(req->inbuf) + poff + pcnt < smb_base(req->inbuf)))
7705 if (state->param + pdisp < state->param)
7708 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,
7713 if (ddisp+dcnt > state->total_data)
7715 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
7717 if (ddisp > state->total_data)
7719 if ((smb_base(req->inbuf) + doff + dcnt
7720 > (char *)req->inbuf + size) ||
7721 (smb_base(req->inbuf) + doff + dcnt < smb_base(req->inbuf)))
7723 if (state->data + ddisp < state->data)
7726 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
7730 if ((state->received_param < state->total_param) ||
7731 (state->received_data < state->total_data)) {
7732 END_PROFILE(SMBtranss2);
7737 * construct_reply_common will copy smb_com from inbuf to
7738 * outbuf. SMBtranss2 is wrong here.
7740 SCVAL(req->inbuf,smb_com,SMBtrans2);
7742 handle_trans2(conn, req, state);
7744 DLIST_REMOVE(conn->pending_trans, state);
7745 SAFE_FREE(state->data);
7746 SAFE_FREE(state->param);
7749 END_PROFILE(SMBtranss2);
7754 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7755 DLIST_REMOVE(conn->pending_trans, state);
7756 SAFE_FREE(state->data);
7757 SAFE_FREE(state->param);
7759 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7760 END_PROFILE(SMBtranss2);