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 unix_to_nt_time(&extended_info->samba_gitcommitdate, time(NULL));
2486 memset(extended_info->samba_version_string, 0,
2487 sizeof(extended_info->samba_version_string));
2489 snprintf (extended_info->samba_version_string,
2490 sizeof(extended_info->samba_version_string),
2491 "%s", samba_version_string());
2494 /****************************************************************************
2495 Reply to a TRANS2_QFSINFO (query filesystem info).
2496 ****************************************************************************/
2498 static void call_trans2qfsinfo(connection_struct *conn,
2499 struct smb_request *req,
2500 char **pparams, int total_params,
2501 char **ppdata, int total_data,
2502 unsigned int max_data_bytes)
2504 char *pdata, *end_data;
2505 char *params = *pparams;
2509 const char *vname = volume_label(SNUM(conn));
2510 int snum = SNUM(conn);
2511 char *fstype = lp_fstype(SNUM(conn));
2512 uint32 additional_flags = 0;
2514 if (total_params < 2) {
2515 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2519 info_level = SVAL(params,0);
2522 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2523 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2524 "info level (0x%x) on IPC$.\n",
2525 (unsigned int)info_level));
2526 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2531 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2532 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2533 DEBUG(0,("call_trans2qfsinfo: encryption required "
2534 "and info level 0x%x sent.\n",
2535 (unsigned int)info_level));
2536 exit_server_cleanly("encryption required "
2542 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2544 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2545 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2546 reply_doserror(req, ERRSRV, ERRinvdevice);
2550 *ppdata = (char *)SMB_REALLOC(
2551 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2552 if (*ppdata == NULL ) {
2553 reply_nterror(req, NT_STATUS_NO_MEMORY);
2558 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2559 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2561 switch (info_level) {
2562 case SMB_INFO_ALLOCATION:
2564 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2566 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2567 reply_unixerror(req, ERRHRD, ERRgeneral);
2571 block_size = lp_block_size(snum);
2572 if (bsize < block_size) {
2573 SMB_BIG_UINT factor = block_size/bsize;
2578 if (bsize > block_size) {
2579 SMB_BIG_UINT factor = bsize/block_size;
2584 bytes_per_sector = 512;
2585 sectors_per_unit = bsize/bytes_per_sector;
2587 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2588 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2589 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2591 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2592 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2593 SIVAL(pdata,l1_cUnit,dsize);
2594 SIVAL(pdata,l1_cUnitAvail,dfree);
2595 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2599 case SMB_INFO_VOLUME:
2600 /* Return volume name */
2602 * Add volume serial number - hash of a combination of
2603 * the called hostname and the service name.
2605 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2607 * Win2k3 and previous mess this up by sending a name length
2608 * one byte short. I believe only older clients (OS/2 Win9x) use
2609 * this call so try fixing this by adding a terminating null to
2610 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2614 pdata+l2_vol_szVolLabel, vname,
2615 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2616 STR_NOALIGN|STR_TERMINATE);
2617 SCVAL(pdata,l2_vol_cch,len);
2618 data_len = l2_vol_szVolLabel + len;
2619 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2620 (unsigned)st.st_ctime, len, vname));
2623 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2624 case SMB_FS_ATTRIBUTE_INFORMATION:
2626 additional_flags = 0;
2627 #if defined(HAVE_SYS_QUOTAS)
2628 additional_flags |= FILE_VOLUME_QUOTAS;
2631 if(lp_nt_acl_support(SNUM(conn))) {
2632 additional_flags |= FILE_PERSISTENT_ACLS;
2635 /* Capabilities are filled in at connection time through STATVFS call */
2636 additional_flags |= conn->fs_capabilities;
2638 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2639 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2640 additional_flags); /* FS ATTRIBUTES */
2642 SIVAL(pdata,4,255); /* Max filename component length */
2643 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2644 and will think we can't do long filenames */
2645 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2646 PTR_DIFF(end_data, pdata+12),
2649 data_len = 12 + len;
2652 case SMB_QUERY_FS_LABEL_INFO:
2653 case SMB_FS_LABEL_INFORMATION:
2654 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2655 PTR_DIFF(end_data, pdata+4), 0);
2660 case SMB_QUERY_FS_VOLUME_INFO:
2661 case SMB_FS_VOLUME_INFORMATION:
2664 * Add volume serial number - hash of a combination of
2665 * the called hostname and the service name.
2667 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2668 (str_checksum(get_local_machine_name())<<16));
2670 /* Max label len is 32 characters. */
2671 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2672 PTR_DIFF(end_data, pdata+18),
2674 SIVAL(pdata,12,len);
2677 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2678 (int)strlen(vname),vname, lp_servicename(snum)));
2681 case SMB_QUERY_FS_SIZE_INFO:
2682 case SMB_FS_SIZE_INFORMATION:
2684 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2686 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2687 reply_unixerror(req, ERRHRD, ERRgeneral);
2690 block_size = lp_block_size(snum);
2691 if (bsize < block_size) {
2692 SMB_BIG_UINT factor = block_size/bsize;
2697 if (bsize > block_size) {
2698 SMB_BIG_UINT factor = bsize/block_size;
2703 bytes_per_sector = 512;
2704 sectors_per_unit = bsize/bytes_per_sector;
2705 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2706 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2707 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2708 SBIG_UINT(pdata,0,dsize);
2709 SBIG_UINT(pdata,8,dfree);
2710 SIVAL(pdata,16,sectors_per_unit);
2711 SIVAL(pdata,20,bytes_per_sector);
2715 case SMB_FS_FULL_SIZE_INFORMATION:
2717 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2719 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2720 reply_unixerror(req, ERRHRD, ERRgeneral);
2723 block_size = lp_block_size(snum);
2724 if (bsize < block_size) {
2725 SMB_BIG_UINT factor = block_size/bsize;
2730 if (bsize > block_size) {
2731 SMB_BIG_UINT factor = bsize/block_size;
2736 bytes_per_sector = 512;
2737 sectors_per_unit = bsize/bytes_per_sector;
2738 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2739 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2740 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2741 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2742 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2743 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2744 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2745 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2749 case SMB_QUERY_FS_DEVICE_INFO:
2750 case SMB_FS_DEVICE_INFORMATION:
2752 SIVAL(pdata,0,0); /* dev type */
2753 SIVAL(pdata,4,0); /* characteristics */
2756 #ifdef HAVE_SYS_QUOTAS
2757 case SMB_FS_QUOTA_INFORMATION:
2759 * what we have to send --metze:
2761 * Unknown1: 24 NULL bytes
2762 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2763 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2764 * Quota Flags: 2 byte :
2765 * Unknown3: 6 NULL bytes
2769 * details for Quota Flags:
2771 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2772 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2773 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2774 * 0x0001 Enable Quotas: enable quota for this fs
2778 /* we need to fake up a fsp here,
2779 * because its not send in this call
2782 SMB_NTQUOTA_STRUCT quotas;
2785 ZERO_STRUCT(quotas);
2791 if (current_user.ut.uid != 0) {
2792 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2793 lp_servicename(SNUM(conn)),conn->user));
2794 reply_doserror(req, ERRDOS, ERRnoaccess);
2798 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2799 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2800 reply_doserror(req, ERRSRV, ERRerror);
2806 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2808 /* Unknown1 24 NULL bytes*/
2809 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2810 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2811 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2813 /* Default Soft Quota 8 bytes */
2814 SBIG_UINT(pdata,24,quotas.softlim);
2816 /* Default Hard Quota 8 bytes */
2817 SBIG_UINT(pdata,32,quotas.hardlim);
2819 /* Quota flag 2 bytes */
2820 SSVAL(pdata,40,quotas.qflags);
2822 /* Unknown3 6 NULL bytes */
2828 #endif /* HAVE_SYS_QUOTAS */
2829 case SMB_FS_OBJECTID_INFORMATION:
2831 unsigned char objid[16];
2832 struct smb_extended_info extended_info;
2833 memcpy(pdata,create_volume_objectid(conn, objid),16);
2834 samba_extended_info_version (&extended_info);
2835 SIVAL(pdata,16,extended_info.samba_magic);
2836 SIVAL(pdata,20,extended_info.samba_version);
2837 SIVAL(pdata,24,extended_info.samba_subversion);
2838 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2839 memcpy(pdata+36,extended_info.samba_version_string,28);
2845 * Query the version and capabilities of the CIFS UNIX extensions
2849 case SMB_QUERY_CIFS_UNIX_INFO:
2851 bool large_write = lp_min_receive_file_size() &&
2852 !srv_is_signing_active();
2853 bool large_read = !srv_is_signing_active();
2854 int encrypt_caps = 0;
2856 if (!lp_unix_extensions()) {
2857 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2861 switch (conn->encrypt_level) {
2867 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2870 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2871 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2872 large_write = false;
2878 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2879 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2881 /* We have POSIX ACLs, pathname, encryption,
2882 * large read/write, and locking capability. */
2884 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2885 CIFS_UNIX_POSIX_ACLS_CAP|
2886 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2887 CIFS_UNIX_FCNTL_LOCKS_CAP|
2888 CIFS_UNIX_EXTATTR_CAP|
2889 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2891 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2893 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2897 case SMB_QUERY_POSIX_FS_INFO:
2900 vfs_statvfs_struct svfs;
2902 if (!lp_unix_extensions()) {
2903 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2907 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2911 SIVAL(pdata,0,svfs.OptimalTransferSize);
2912 SIVAL(pdata,4,svfs.BlockSize);
2913 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2914 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2915 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2916 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2917 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2918 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2919 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2921 } else if (rc == EOPNOTSUPP) {
2922 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2924 #endif /* EOPNOTSUPP */
2926 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2927 reply_doserror(req, ERRSRV, ERRerror);
2933 case SMB_QUERY_POSIX_WHOAMI:
2939 if (!lp_unix_extensions()) {
2940 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2944 if (max_data_bytes < 40) {
2945 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2949 /* We ARE guest if global_sid_Builtin_Guests is
2950 * in our list of SIDs.
2952 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2953 current_user.nt_user_token)) {
2954 flags |= SMB_WHOAMI_GUEST;
2957 /* We are NOT guest if global_sid_Authenticated_Users
2958 * is in our list of SIDs.
2960 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2961 current_user.nt_user_token)) {
2962 flags &= ~SMB_WHOAMI_GUEST;
2965 /* NOTE: 8 bytes for UID/GID, irrespective of native
2966 * platform size. This matches
2967 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2969 data_len = 4 /* flags */
2976 + 4 /* pad/reserved */
2977 + (current_user.ut.ngroups * 8)
2979 + (current_user.nt_user_token->num_sids *
2983 SIVAL(pdata, 0, flags);
2984 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2985 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2986 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2989 if (data_len >= max_data_bytes) {
2990 /* Potential overflow, skip the GIDs and SIDs. */
2992 SIVAL(pdata, 24, 0); /* num_groups */
2993 SIVAL(pdata, 28, 0); /* num_sids */
2994 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2995 SIVAL(pdata, 36, 0); /* reserved */
3001 SIVAL(pdata, 24, current_user.ut.ngroups);
3003 current_user.nt_user_token->num_sids);
3005 /* We walk the SID list twice, but this call is fairly
3006 * infrequent, and I don't expect that it's performance
3007 * sensitive -- jpeach
3009 for (i = 0, sid_bytes = 0;
3010 i < current_user.nt_user_token->num_sids; ++i) {
3011 sid_bytes += ndr_size_dom_sid(
3012 ¤t_user.nt_user_token->user_sids[i], 0);
3015 /* SID list byte count */
3016 SIVAL(pdata, 32, sid_bytes);
3018 /* 4 bytes pad/reserved - must be zero */
3019 SIVAL(pdata, 36, 0);
3023 for (i = 0; i < current_user.ut.ngroups; ++i) {
3024 SBIG_UINT(pdata, data_len,
3025 (SMB_BIG_UINT)current_user.ut.groups[i]);
3031 i < current_user.nt_user_token->num_sids; ++i) {
3032 int sid_len = ndr_size_dom_sid(
3033 ¤t_user.nt_user_token->user_sids[i], 0);
3035 sid_linearize(pdata + data_len, sid_len,
3036 ¤t_user.nt_user_token->user_sids[i]);
3037 data_len += sid_len;
3043 case SMB_MAC_QUERY_FS_INFO:
3045 * Thursby MAC extension... ONLY on NTFS filesystems
3046 * once we do streams then we don't need this
3048 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3050 SIVAL(pdata,84,0x100); /* Don't support mac... */
3055 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3060 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3063 DEBUG( 4, ( "%s info_level = %d\n",
3064 smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) );
3069 /****************************************************************************
3070 Reply to a TRANS2_SETFSINFO (set filesystem info).
3071 ****************************************************************************/
3073 static void call_trans2setfsinfo(connection_struct *conn,
3074 struct smb_request *req,
3075 char **pparams, int total_params,
3076 char **ppdata, int total_data,
3077 unsigned int max_data_bytes)
3079 char *pdata = *ppdata;
3080 char *params = *pparams;
3083 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3086 if (total_params < 4) {
3087 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3089 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3093 info_level = SVAL(params,2);
3096 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3097 info_level != SMB_SET_CIFS_UNIX_INFO) {
3098 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3099 "info level (0x%x) on IPC$.\n",
3100 (unsigned int)info_level));
3101 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3106 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3107 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3108 DEBUG(0,("call_trans2setfsinfo: encryption required "
3109 "and info level 0x%x sent.\n",
3110 (unsigned int)info_level));
3111 exit_server_cleanly("encryption required "
3117 switch(info_level) {
3118 case SMB_SET_CIFS_UNIX_INFO:
3120 uint16 client_unix_major;
3121 uint16 client_unix_minor;
3122 uint32 client_unix_cap_low;
3123 uint32 client_unix_cap_high;
3125 if (!lp_unix_extensions()) {
3127 NT_STATUS_INVALID_LEVEL);
3131 /* There should be 12 bytes of capabilities set. */
3132 if (total_data < 8) {
3135 NT_STATUS_INVALID_PARAMETER);
3138 client_unix_major = SVAL(pdata,0);
3139 client_unix_minor = SVAL(pdata,2);
3140 client_unix_cap_low = IVAL(pdata,4);
3141 client_unix_cap_high = IVAL(pdata,8);
3142 /* Just print these values for now. */
3143 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3144 cap_low = 0x%x, cap_high = 0x%x\n",
3145 (unsigned int)client_unix_major,
3146 (unsigned int)client_unix_minor,
3147 (unsigned int)client_unix_cap_low,
3148 (unsigned int)client_unix_cap_high ));
3150 /* Here is where we must switch to posix pathname processing... */
3151 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3152 lp_set_posix_pathnames();
3153 mangle_change_to_posix();
3156 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3157 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3158 /* Client that knows how to do posix locks,
3159 * but not posix open/mkdir operations. Set a
3160 * default type for read/write checks. */
3162 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3168 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3171 size_t param_len = 0;
3172 size_t data_len = total_data;
3174 if (!lp_unix_extensions()) {
3177 NT_STATUS_INVALID_LEVEL);
3181 if (lp_smb_encrypt(SNUM(conn)) == false) {
3184 NT_STATUS_NOT_SUPPORTED);
3188 DEBUG( 4,("call_trans2setfsinfo: "
3189 "request transport encrption.\n"));
3191 status = srv_request_encryption_setup(conn,
3192 (unsigned char **)ppdata,
3194 (unsigned char **)pparams,
3197 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3198 !NT_STATUS_IS_OK(status)) {
3199 reply_nterror(req, status);
3203 send_trans2_replies(conn, req,
3210 if (NT_STATUS_IS_OK(status)) {
3211 /* Server-side transport
3212 * encryption is now *on*. */
3213 status = srv_encryption_start(conn);
3214 if (!NT_STATUS_IS_OK(status)) {
3215 exit_server_cleanly(
3216 "Failure in setting "
3217 "up encrypted transport");
3223 case SMB_FS_QUOTA_INFORMATION:
3225 files_struct *fsp = NULL;
3226 SMB_NTQUOTA_STRUCT quotas;
3228 ZERO_STRUCT(quotas);
3231 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
3232 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3233 lp_servicename(SNUM(conn)),conn->user));
3234 reply_doserror(req, ERRSRV, ERRaccess);
3238 /* note: normaly there're 48 bytes,
3239 * but we didn't use the last 6 bytes for now
3242 fsp = file_fsp(SVAL(params,0));
3243 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
3244 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3246 req, NT_STATUS_INVALID_HANDLE);
3250 if (total_data < 42) {
3251 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3255 NT_STATUS_INVALID_PARAMETER);
3259 /* unknown_1 24 NULL bytes in pdata*/
3261 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3262 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
3263 #ifdef LARGE_SMB_OFF_T
3264 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
3265 #else /* LARGE_SMB_OFF_T */
3266 if ((IVAL(pdata,28) != 0)&&
3267 ((quotas.softlim != 0xFFFFFFFF)||
3268 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3269 /* more than 32 bits? */
3272 NT_STATUS_INVALID_PARAMETER);
3275 #endif /* LARGE_SMB_OFF_T */
3277 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3278 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
3279 #ifdef LARGE_SMB_OFF_T
3280 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
3281 #else /* LARGE_SMB_OFF_T */
3282 if ((IVAL(pdata,36) != 0)&&
3283 ((quotas.hardlim != 0xFFFFFFFF)||
3284 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3285 /* more than 32 bits? */
3288 NT_STATUS_INVALID_PARAMETER);
3291 #endif /* LARGE_SMB_OFF_T */
3293 /* quota_flags 2 bytes **/
3294 quotas.qflags = SVAL(pdata,40);
3296 /* unknown_2 6 NULL bytes follow*/
3298 /* now set the quotas */
3299 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3300 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3301 reply_doserror(req, ERRSRV, ERRerror);
3308 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3310 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3316 * sending this reply works fine,
3317 * but I'm not sure it's the same
3318 * like windows do...
3321 reply_outbuf(req, 10, 0);
3324 #if defined(HAVE_POSIX_ACLS)
3325 /****************************************************************************
3326 Utility function to count the number of entries in a POSIX acl.
3327 ****************************************************************************/
3329 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3331 unsigned int ace_count = 0;
3332 int entry_id = SMB_ACL_FIRST_ENTRY;
3333 SMB_ACL_ENTRY_T entry;
3335 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3337 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3338 entry_id = SMB_ACL_NEXT_ENTRY;
3345 /****************************************************************************
3346 Utility function to marshall a POSIX acl into wire format.
3347 ****************************************************************************/
3349 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3351 int entry_id = SMB_ACL_FIRST_ENTRY;
3352 SMB_ACL_ENTRY_T entry;
3354 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3355 SMB_ACL_TAG_T tagtype;
3356 SMB_ACL_PERMSET_T permset;
3357 unsigned char perms = 0;
3358 unsigned int own_grp;
3361 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3362 entry_id = SMB_ACL_NEXT_ENTRY;
3365 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3366 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3370 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3371 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3375 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3376 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3377 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3379 SCVAL(pdata,1,perms);
3382 case SMB_ACL_USER_OBJ:
3383 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3384 own_grp = (unsigned int)pst->st_uid;
3385 SIVAL(pdata,2,own_grp);
3390 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3392 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3395 own_grp = (unsigned int)*puid;
3396 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3397 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3398 SIVAL(pdata,2,own_grp);
3402 case SMB_ACL_GROUP_OBJ:
3403 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3404 own_grp = (unsigned int)pst->st_gid;
3405 SIVAL(pdata,2,own_grp);
3410 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3412 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3415 own_grp = (unsigned int)*pgid;
3416 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3417 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3418 SIVAL(pdata,2,own_grp);
3423 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3424 SIVAL(pdata,2,0xFFFFFFFF);
3425 SIVAL(pdata,6,0xFFFFFFFF);
3428 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3429 SIVAL(pdata,2,0xFFFFFFFF);
3430 SIVAL(pdata,6,0xFFFFFFFF);
3433 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3436 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3443 /****************************************************************************
3444 Store the FILE_UNIX_BASIC info.
3445 ****************************************************************************/
3447 static char *store_file_unix_basic(connection_struct *conn,
3450 const SMB_STRUCT_STAT *psbuf)
3452 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3453 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3455 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3458 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3461 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3462 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3463 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3466 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3470 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3474 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3477 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3481 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3485 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3488 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3492 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3499 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3500 * the chflags(2) (or equivalent) flags.
3502 * XXX: this really should be behind the VFS interface. To do this, we would
3503 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3504 * Each VFS module could then implement its own mapping as appropriate for the
3505 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3507 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3511 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3515 { UF_IMMUTABLE, EXT_IMMUTABLE },
3519 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3523 { UF_HIDDEN, EXT_HIDDEN },
3526 /* Do not remove. We need to guarantee that this array has at least one
3527 * entry to build on HP-UX.
3533 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3534 uint32 *smb_fflags, uint32 *smb_fmask)
3536 #ifdef HAVE_STAT_ST_FLAGS
3539 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3540 *smb_fmask |= info2_flags_map[i].smb_fflag;
3541 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3542 *smb_fflags |= info2_flags_map[i].smb_fflag;
3545 #endif /* HAVE_STAT_ST_FLAGS */
3548 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3549 const uint32 smb_fflags,
3550 const uint32 smb_fmask,
3553 #ifdef HAVE_STAT_ST_FLAGS
3554 uint32 max_fmask = 0;
3557 *stat_fflags = psbuf->st_flags;
3559 /* For each flags requested in smb_fmask, check the state of the
3560 * corresponding flag in smb_fflags and set or clear the matching
3564 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3565 max_fmask |= info2_flags_map[i].smb_fflag;
3566 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3567 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3568 *stat_fflags |= info2_flags_map[i].stat_fflag;
3570 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3575 /* If smb_fmask is asking to set any bits that are not supported by
3576 * our flag mappings, we should fail.
3578 if ((smb_fmask & max_fmask) != smb_fmask) {
3585 #endif /* HAVE_STAT_ST_FLAGS */
3589 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3590 * of file flags and birth (create) time.
3592 static char *store_file_unix_basic_info2(connection_struct *conn,
3595 const SMB_STRUCT_STAT *psbuf)
3597 uint32 file_flags = 0;
3598 uint32 flags_mask = 0;
3600 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3602 /* Create (birth) time 64 bit */
3603 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3606 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3607 SIVAL(pdata, 0, file_flags); /* flags */
3608 SIVAL(pdata, 4, flags_mask); /* mask */
3614 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3615 const struct stream_struct *streams,
3617 unsigned int max_data_bytes,
3618 unsigned int *data_size)
3621 unsigned int ofs = 0;
3623 for (i=0; i<num_streams; i++) {
3624 unsigned int next_offset;
3626 smb_ucs2_t *namebuf;
3628 namelen = push_ucs2_talloc(talloc_tos(), &namebuf,
3631 if ((namelen == (size_t)-1) || (namelen <= 2)) {
3632 return NT_STATUS_INVALID_PARAMETER;
3636 * name_buf is now null-terminated, we need to marshall as not
3642 if (ofs + 24 + namelen > max_data_bytes) {
3643 TALLOC_FREE(namebuf);
3644 return NT_STATUS_BUFFER_TOO_SMALL;
3647 SIVAL(data, ofs+4, namelen);
3648 SOFF_T(data, ofs+8, streams[i].size);
3649 SOFF_T(data, ofs+16, streams[i].alloc_size);
3650 memcpy(data+ofs+24, namebuf, namelen);
3651 TALLOC_FREE(namebuf);
3653 next_offset = ofs + 24 + namelen;
3655 if (i == num_streams-1) {
3656 SIVAL(data, ofs, 0);
3659 unsigned int align = ndr_align_size(next_offset, 8);
3661 if (next_offset + align > max_data_bytes) {
3662 return NT_STATUS_BUFFER_TOO_SMALL;
3665 memset(data+next_offset, 0, align);
3666 next_offset += align;
3668 SIVAL(data, ofs, next_offset - ofs);
3677 return NT_STATUS_OK;
3680 /****************************************************************************
3681 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3682 ****************************************************************************/
3684 static void call_trans2qpipeinfo(connection_struct *conn,
3685 struct smb_request *req,
3686 unsigned int tran_call,
3687 char **pparams, int total_params,
3688 char **ppdata, int total_data,
3689 unsigned int max_data_bytes)
3691 char *params = *pparams;
3692 char *pdata = *ppdata;
3693 unsigned int data_size = 0;
3694 unsigned int param_size = 2;
3696 smb_np_struct *p_pipe = NULL;
3699 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3703 if (total_params < 4) {
3704 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3708 p_pipe = get_rpc_pipe_p(SVAL(params,0));
3709 if (p_pipe == NULL) {
3710 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3714 info_level = SVAL(params,2);
3716 *pparams = (char *)SMB_REALLOC(*pparams,2);
3717 if (*pparams == NULL) {
3718 reply_nterror(req, NT_STATUS_NO_MEMORY);
3723 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3724 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3725 if (*ppdata == NULL ) {
3726 reply_nterror(req, NT_STATUS_NO_MEMORY);
3731 switch (info_level) {
3732 case SMB_FILE_STANDARD_INFORMATION:
3734 SOFF_T(pdata,0,4096LL);
3741 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3745 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3751 /****************************************************************************
3752 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3753 file name or file id).
3754 ****************************************************************************/
3756 static void call_trans2qfilepathinfo(connection_struct *conn,
3757 struct smb_request *req,
3758 unsigned int tran_call,
3759 char **pparams, int total_params,
3760 char **ppdata, int total_data,
3761 unsigned int max_data_bytes)
3763 char *params = *pparams;
3764 char *pdata = *ppdata;
3765 char *dstart, *dend;
3769 SMB_OFF_T file_size=0;
3770 SMB_BIG_UINT allocation_size=0;
3771 unsigned int data_size = 0;
3772 unsigned int param_size = 2;
3773 SMB_STRUCT_STAT sbuf;
3774 char *dos_fname = NULL;
3780 bool delete_pending = False;
3782 time_t create_time, mtime, atime;
3783 struct timespec create_time_ts, mtime_ts, atime_ts;
3784 files_struct *fsp = NULL;
3785 struct file_id fileid;
3786 struct ea_list *ea_list = NULL;
3787 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3788 char *lock_data = NULL;
3789 TALLOC_CTX *ctx = talloc_tos();
3792 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3798 if (tran_call == TRANSACT2_QFILEINFO) {
3799 if (total_params < 4) {
3800 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3805 call_trans2qpipeinfo(conn, req, tran_call,
3806 pparams, total_params,
3812 fsp = file_fsp(SVAL(params,0));
3813 info_level = SVAL(params,2);
3815 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3817 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3818 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3822 /* Initial check for valid fsp ptr. */
3823 if (!check_fsp_open(conn, req, fsp, ¤t_user)) {
3827 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3829 reply_nterror(req, NT_STATUS_NO_MEMORY);
3833 if(fsp->fake_file_handle) {
3835 * This is actually for the QUOTA_FAKE_FILE --metze
3838 /* We know this name is ok, it's already passed the checks. */
3840 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3842 * This is actually a QFILEINFO on a directory
3843 * handle (returned from an NT SMB). NT5.0 seems
3844 * to do this call. JRA.
3847 if (INFO_LEVEL_IS_UNIX(info_level)) {
3848 /* Always do lstat for UNIX calls. */
3849 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3850 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3851 reply_unixerror(req,ERRDOS,ERRbadpath);
3854 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3855 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3856 reply_unixerror(req, ERRDOS, ERRbadpath);
3860 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3861 delete_pending = get_delete_on_close_flag(fileid);
3864 * Original code - this is an open file.
3866 if (!check_fsp(conn, req, fsp, ¤t_user)) {
3870 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3871 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3872 reply_unixerror(req, ERRDOS, ERRbadfid);
3875 pos = fsp->fh->position_information;
3876 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3877 delete_pending = get_delete_on_close_flag(fileid);
3878 access_mask = fsp->access_mask;
3882 NTSTATUS status = NT_STATUS_OK;
3885 if (total_params < 7) {
3886 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3890 info_level = SVAL(params,0);
3892 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3894 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3895 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3899 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
3901 STR_TERMINATE, &status);
3902 if (!NT_STATUS_IS_OK(status)) {
3903 reply_nterror(req, status);
3907 status = resolve_dfspath(ctx,
3909 req->flags2 & FLAGS2_DFS_PATHNAMES,
3912 if (!NT_STATUS_IS_OK(status)) {
3913 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3914 reply_botherror(req,
3915 NT_STATUS_PATH_NOT_COVERED,
3916 ERRSRV, ERRbadpath);
3918 reply_nterror(req, status);
3922 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3923 if (!NT_STATUS_IS_OK(status)) {
3924 reply_nterror(req, status);
3927 status = check_name(conn, fname);
3928 if (!NT_STATUS_IS_OK(status)) {
3929 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3930 reply_nterror(req, status);
3934 if (INFO_LEVEL_IS_UNIX(info_level)) {
3935 /* Always do lstat for UNIX calls. */
3936 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3937 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3938 reply_unixerror(req, ERRDOS, ERRbadpath);
3941 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3942 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3943 reply_unixerror(req, ERRDOS, ERRbadpath);
3947 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3948 delete_pending = get_delete_on_close_flag(fileid);
3949 if (delete_pending) {
3950 reply_nterror(req, NT_STATUS_DELETE_PENDING);
3955 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3956 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3960 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3961 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3963 p = strrchr_m(fname,'/');
3969 mode = dos_mode(conn,fname,&sbuf);
3971 mode = FILE_ATTRIBUTE_NORMAL;
3973 nlink = sbuf.st_nlink;
3975 if (nlink && (mode&aDIR)) {
3979 if ((nlink > 0) && delete_pending) {
3983 fullpathname = fname;
3985 file_size = get_file_size(sbuf);
3987 /* Pull out any data sent here before we realloc. */
3988 switch (info_level) {
3989 case SMB_INFO_QUERY_EAS_FROM_LIST:
3991 /* Pull any EA list from the data portion. */
3994 if (total_data < 4) {
3996 req, NT_STATUS_INVALID_PARAMETER);
3999 ea_size = IVAL(pdata,0);
4001 if (total_data > 0 && ea_size != total_data) {
4002 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4003 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4005 req, NT_STATUS_INVALID_PARAMETER);
4009 if (!lp_ea_support(SNUM(conn))) {
4010 reply_doserror(req, ERRDOS,
4011 ERReasnotsupported);
4015 /* Pull out the list of names. */
4016 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4019 req, NT_STATUS_INVALID_PARAMETER);
4025 case SMB_QUERY_POSIX_LOCK:
4027 if (fsp == NULL || fsp->fh->fd == -1) {
4028 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4032 if (total_data != POSIX_LOCK_DATA_SIZE) {
4034 req, NT_STATUS_INVALID_PARAMETER);
4038 /* Copy the lock range data. */
4039 lock_data = (char *)TALLOC_MEMDUP(
4040 ctx, pdata, total_data);
4042 reply_nterror(req, NT_STATUS_NO_MEMORY);
4050 *pparams = (char *)SMB_REALLOC(*pparams,2);
4051 if (*pparams == NULL) {
4052 reply_nterror(req, NT_STATUS_NO_MEMORY);
4057 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4058 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4059 if (*ppdata == NULL ) {
4060 reply_nterror(req, NT_STATUS_NO_MEMORY);
4065 dend = dstart + data_size - 1;
4067 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
4068 mtime_ts = get_mtimespec(&sbuf);
4069 atime_ts = get_atimespec(&sbuf);
4071 allocation_size = get_allocation_size(conn,fsp,&sbuf);
4074 if (!null_timespec(fsp->pending_modtime)) {
4075 /* the pending modtime overrides the current modtime */
4076 mtime_ts = fsp->pending_modtime;
4080 /* Do we have this path open ? */
4081 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4082 fsp1 = file_find_di_first(fileid);
4083 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
4084 /* the pending modtime overrides the current modtime */
4085 mtime_ts = fsp1->pending_modtime;
4087 if (fsp1 && fsp1->initial_allocation_size) {
4088 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
4092 if (lp_dos_filetime_resolution(SNUM(conn))) {
4093 dos_filetime_timespec(&create_time_ts);
4094 dos_filetime_timespec(&mtime_ts);
4095 dos_filetime_timespec(&atime_ts);
4098 create_time = convert_timespec_to_time_t(create_time_ts);
4099 mtime = convert_timespec_to_time_t(mtime_ts);
4100 atime = convert_timespec_to_time_t(atime_ts);
4102 /* NT expects the name to be in an exact form of the *full*
4103 filename. See the trans2 torture test */
4104 if (ISDOT(base_name)) {
4105 dos_fname = talloc_strdup(ctx, "\\");
4107 reply_nterror(req, NT_STATUS_NO_MEMORY);
4111 dos_fname = talloc_asprintf(ctx,
4115 reply_nterror(req, NT_STATUS_NO_MEMORY);
4118 string_replace(dos_fname, '/', '\\');
4121 switch (info_level) {
4122 case SMB_INFO_STANDARD:
4123 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4125 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4126 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4127 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4128 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4129 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4130 SSVAL(pdata,l1_attrFile,mode);
4133 case SMB_INFO_QUERY_EA_SIZE:
4135 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4136 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4138 srv_put_dos_date2(pdata,0,create_time);
4139 srv_put_dos_date2(pdata,4,atime);
4140 srv_put_dos_date2(pdata,8,mtime); /* write time */
4141 SIVAL(pdata,12,(uint32)file_size);
4142 SIVAL(pdata,16,(uint32)allocation_size);
4143 SSVAL(pdata,20,mode);
4144 SIVAL(pdata,22,ea_size);
4148 case SMB_INFO_IS_NAME_VALID:
4149 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4150 if (tran_call == TRANSACT2_QFILEINFO) {
4151 /* os/2 needs this ? really ?*/
4152 reply_doserror(req, ERRDOS, ERRbadfunc);
4159 case SMB_INFO_QUERY_EAS_FROM_LIST:
4161 size_t total_ea_len = 0;
4162 struct ea_list *ea_file_list = NULL;
4164 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4166 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4167 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4169 if (!ea_list || (total_ea_len > data_size)) {
4171 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4175 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4179 case SMB_INFO_QUERY_ALL_EAS:
4181 /* We have data_size bytes to put EA's into. */
4182 size_t total_ea_len = 0;
4184 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4186 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4187 if (!ea_list || (total_ea_len > data_size)) {
4189 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4193 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4197 case SMB_FILE_BASIC_INFORMATION:
4198 case SMB_QUERY_FILE_BASIC_INFO:
4200 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4201 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4202 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4204 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4208 put_long_date_timespec(pdata,create_time_ts);
4209 put_long_date_timespec(pdata+8,atime_ts);
4210 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4211 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4212 SIVAL(pdata,32,mode);
4214 DEBUG(5,("SMB_QFBI - "));
4215 DEBUG(5,("create: %s ", ctime(&create_time)));
4216 DEBUG(5,("access: %s ", ctime(&atime)));
4217 DEBUG(5,("write: %s ", ctime(&mtime)));
4218 DEBUG(5,("change: %s ", ctime(&mtime)));
4219 DEBUG(5,("mode: %x\n", mode));
4222 case SMB_FILE_STANDARD_INFORMATION:
4223 case SMB_QUERY_FILE_STANDARD_INFO:
4225 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4227 SOFF_T(pdata,0,allocation_size);
4228 SOFF_T(pdata,8,file_size);
4229 SIVAL(pdata,16,nlink);
4230 SCVAL(pdata,20,delete_pending?1:0);
4231 SCVAL(pdata,21,(mode&aDIR)?1:0);
4232 SSVAL(pdata,22,0); /* Padding. */
4235 case SMB_FILE_EA_INFORMATION:
4236 case SMB_QUERY_FILE_EA_INFO:
4238 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4239 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4241 SIVAL(pdata,0,ea_size);
4245 /* Get the 8.3 name - used if NT SMB was negotiated. */
4246 case SMB_QUERY_FILE_ALT_NAME_INFO:
4247 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4249 char mangled_name[13];
4250 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4251 if (!name_to_8_3(base_name,mangled_name,
4252 True,conn->params)) {
4255 NT_STATUS_NO_MEMORY);
4257 len = srvstr_push(dstart, req->flags2,
4258 pdata+4, mangled_name,
4259 PTR_DIFF(dend, pdata+4),
4261 data_size = 4 + len;
4266 case SMB_QUERY_FILE_NAME_INFO:
4268 this must be *exactly* right for ACLs on mapped drives to work
4270 len = srvstr_push(dstart, req->flags2,
4272 PTR_DIFF(dend, pdata+4),
4274 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4275 data_size = 4 + len;
4279 case SMB_FILE_ALLOCATION_INFORMATION:
4280 case SMB_QUERY_FILE_ALLOCATION_INFO:
4281 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4283 SOFF_T(pdata,0,allocation_size);
4286 case SMB_FILE_END_OF_FILE_INFORMATION:
4287 case SMB_QUERY_FILE_END_OF_FILEINFO:
4288 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4290 SOFF_T(pdata,0,file_size);
4293 case SMB_QUERY_FILE_ALL_INFO:
4294 case SMB_FILE_ALL_INFORMATION:
4296 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4297 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4298 put_long_date_timespec(pdata,create_time_ts);
4299 put_long_date_timespec(pdata+8,atime_ts);
4300 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4301 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4302 SIVAL(pdata,32,mode);
4303 SIVAL(pdata,36,0); /* padding. */
4305 SOFF_T(pdata,0,allocation_size);
4306 SOFF_T(pdata,8,file_size);
4307 SIVAL(pdata,16,nlink);
4308 SCVAL(pdata,20,delete_pending);
4309 SCVAL(pdata,21,(mode&aDIR)?1:0);
4312 SIVAL(pdata,0,ea_size);
4313 pdata += 4; /* EA info */
4314 len = srvstr_push(dstart, req->flags2,
4316 PTR_DIFF(dend, pdata+4),
4320 data_size = PTR_DIFF(pdata,(*ppdata));
4323 case SMB_FILE_INTERNAL_INFORMATION:
4324 /* This should be an index number - looks like
4327 I think this causes us to fail the IFSKIT
4328 BasicFileInformationTest. -tpot */
4330 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4331 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4332 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4336 case SMB_FILE_ACCESS_INFORMATION:
4337 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4338 SIVAL(pdata,0,access_mask);
4342 case SMB_FILE_NAME_INFORMATION:
4343 /* Pathname with leading '\'. */
4346 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4347 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4348 SIVAL(pdata,0,byte_len);
4349 data_size = 4 + byte_len;
4353 case SMB_FILE_DISPOSITION_INFORMATION:
4354 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4356 SCVAL(pdata,0,delete_pending);
4359 case SMB_FILE_POSITION_INFORMATION:
4360 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4362 SOFF_T(pdata,0,pos);
4365 case SMB_FILE_MODE_INFORMATION:
4366 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4367 SIVAL(pdata,0,mode);
4371 case SMB_FILE_ALIGNMENT_INFORMATION:
4372 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4373 SIVAL(pdata,0,0); /* No alignment needed. */
4378 * NT4 server just returns "invalid query" to this - if we try
4379 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4382 /* The first statement above is false - verified using Thursby
4383 * client against NT4 -- gcolley.
4385 case SMB_QUERY_FILE_STREAM_INFO:
4386 case SMB_FILE_STREAM_INFORMATION: {
4387 unsigned int num_streams;
4388 struct stream_struct *streams;
4391 DEBUG(10,("call_trans2qfilepathinfo: "
4392 "SMB_FILE_STREAM_INFORMATION\n"));
4394 status = SMB_VFS_STREAMINFO(
4395 conn, fsp, fname, talloc_tos(),
4396 &num_streams, &streams);
4398 if (!NT_STATUS_IS_OK(status)) {
4399 DEBUG(10, ("could not get stream info: %s\n",
4400 nt_errstr(status)));
4401 reply_nterror(req, status);
4405 status = marshall_stream_info(num_streams, streams,
4406 pdata, max_data_bytes,
4409 if (!NT_STATUS_IS_OK(status)) {
4410 DEBUG(10, ("marshall_stream_info failed: %s\n",
4411 nt_errstr(status)));
4412 reply_nterror(req, status);
4416 TALLOC_FREE(streams);
4420 case SMB_QUERY_COMPRESSION_INFO:
4421 case SMB_FILE_COMPRESSION_INFORMATION:
4422 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4423 SOFF_T(pdata,0,file_size);
4424 SIVAL(pdata,8,0); /* ??? */
4425 SIVAL(pdata,12,0); /* ??? */
4429 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4430 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4431 put_long_date_timespec(pdata,create_time_ts);
4432 put_long_date_timespec(pdata+8,atime_ts);
4433 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4434 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4435 SOFF_T(pdata,32,allocation_size);
4436 SOFF_T(pdata,40,file_size);
4437 SIVAL(pdata,48,mode);
4438 SIVAL(pdata,52,0); /* ??? */
4442 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4443 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4444 SIVAL(pdata,0,mode);
4450 * CIFS UNIX Extensions.
4453 case SMB_QUERY_FILE_UNIX_BASIC:
4455 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4456 data_size = PTR_DIFF(pdata,(*ppdata));
4460 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4462 for (i=0; i<100; i++)
4463 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4469 case SMB_QUERY_FILE_UNIX_INFO2:
4471 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4472 data_size = PTR_DIFF(pdata,(*ppdata));
4476 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4478 for (i=0; i<100; i++)
4479 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4485 case SMB_QUERY_FILE_UNIX_LINK:
4487 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4490 reply_nterror(req, NT_STATUS_NO_MEMORY);
4494 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4496 if(!S_ISLNK(sbuf.st_mode)) {
4497 reply_unixerror(req, ERRSRV,
4502 reply_unixerror(req, ERRDOS, ERRbadlink);
4505 len = SMB_VFS_READLINK(conn,fullpathname,
4508 reply_unixerror(req, ERRDOS,
4513 len = srvstr_push(dstart, req->flags2,
4515 PTR_DIFF(dend, pdata),
4518 data_size = PTR_DIFF(pdata,(*ppdata));
4523 #if defined(HAVE_POSIX_ACLS)
4524 case SMB_QUERY_POSIX_ACL:
4526 SMB_ACL_T file_acl = NULL;
4527 SMB_ACL_T def_acl = NULL;
4528 uint16 num_file_acls = 0;
4529 uint16 num_def_acls = 0;
4531 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4532 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4534 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4537 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4538 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4542 NT_STATUS_NOT_IMPLEMENTED);
4546 if (S_ISDIR(sbuf.st_mode)) {
4547 if (fsp && fsp->is_directory) {
4548 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4550 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4552 def_acl = free_empty_sys_acl(conn, def_acl);
4555 num_file_acls = count_acl_entries(conn, file_acl);
4556 num_def_acls = count_acl_entries(conn, def_acl);
4558 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4559 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4561 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4562 SMB_POSIX_ACL_HEADER_SIZE) ));
4564 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4567 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4571 NT_STATUS_BUFFER_TOO_SMALL);
4575 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4576 SSVAL(pdata,2,num_file_acls);
4577 SSVAL(pdata,4,num_def_acls);
4578 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4580 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4583 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4586 req, NT_STATUS_INTERNAL_ERROR);
4589 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4591 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4594 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4598 NT_STATUS_INTERNAL_ERROR);
4603 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4606 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4608 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4614 case SMB_QUERY_POSIX_LOCK:
4616 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4618 SMB_BIG_UINT offset;
4620 enum brl_type lock_type;
4622 if (total_data != POSIX_LOCK_DATA_SIZE) {
4624 req, NT_STATUS_INVALID_PARAMETER);
4628 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4629 case POSIX_LOCK_TYPE_READ:
4630 lock_type = READ_LOCK;
4632 case POSIX_LOCK_TYPE_WRITE:
4633 lock_type = WRITE_LOCK;
4635 case POSIX_LOCK_TYPE_UNLOCK:
4637 /* There's no point in asking for an unlock... */
4640 NT_STATUS_INVALID_PARAMETER);
4644 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4645 #if defined(HAVE_LONGLONG)
4646 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4647 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4648 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4649 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4650 #else /* HAVE_LONGLONG */
4651 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4652 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4653 #endif /* HAVE_LONGLONG */
4655 status = query_lock(fsp,
4662 if (ERROR_WAS_LOCK_DENIED(status)) {
4663 /* Here we need to report who has it locked... */
4664 data_size = POSIX_LOCK_DATA_SIZE;
4666 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4667 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4668 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4669 #if defined(HAVE_LONGLONG)
4670 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4671 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4672 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4673 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4674 #else /* HAVE_LONGLONG */
4675 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4676 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4677 #endif /* HAVE_LONGLONG */
4679 } else if (NT_STATUS_IS_OK(status)) {
4680 /* For success we just return a copy of what we sent
4681 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4682 data_size = POSIX_LOCK_DATA_SIZE;
4683 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4684 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4686 reply_nterror(req, status);
4693 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4697 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4703 /****************************************************************************
4704 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4706 ****************************************************************************/
4708 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4709 connection_struct *conn,
4710 const char *oldname_in,
4711 const char *newname_in)
4713 SMB_STRUCT_STAT sbuf1, sbuf2;
4714 char *last_component_oldname = NULL;
4715 char *last_component_newname = NULL;
4716 char *oldname = NULL;
4717 char *newname = NULL;
4718 NTSTATUS status = NT_STATUS_OK;
4723 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4724 &last_component_oldname, &sbuf1);
4725 if (!NT_STATUS_IS_OK(status)) {
4729 status = check_name(conn, oldname);
4730 if (!NT_STATUS_IS_OK(status)) {
4734 /* source must already exist. */
4735 if (!VALID_STAT(sbuf1)) {
4736 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4739 status = unix_convert(ctx, conn, newname_in, False, &newname,
4740 &last_component_newname, &sbuf2);
4741 if (!NT_STATUS_IS_OK(status)) {
4745 status = check_name(conn, newname);
4746 if (!NT_STATUS_IS_OK(status)) {
4750 /* Disallow if newname already exists. */
4751 if (VALID_STAT(sbuf2)) {
4752 return NT_STATUS_OBJECT_NAME_COLLISION;
4755 /* No links from a directory. */
4756 if (S_ISDIR(sbuf1.st_mode)) {
4757 return NT_STATUS_FILE_IS_A_DIRECTORY;
4760 /* Ensure this is within the share. */
4761 status = check_reduced_name(conn, oldname);
4762 if (!NT_STATUS_IS_OK(status)) {
4766 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4768 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4769 status = map_nt_error_from_unix(errno);
4770 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4771 nt_errstr(status), newname, oldname));
4777 /****************************************************************************
4778 Deal with setting the time from any of the setfilepathinfo functions.
4779 ****************************************************************************/
4781 static NTSTATUS smb_set_file_time(connection_struct *conn,
4784 const SMB_STRUCT_STAT *psbuf,
4785 struct timespec ts[2],
4786 bool setting_write_time)
4789 FILE_NOTIFY_CHANGE_LAST_ACCESS
4790 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4792 if (!VALID_STAT(*psbuf)) {
4793 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4796 /* get some defaults (no modifications) if any info is zero or -1. */
4797 if (null_timespec(ts[0])) {
4798 ts[0] = get_atimespec(psbuf);
4799 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4802 if (null_timespec(ts[1])) {
4803 ts[1] = get_mtimespec(psbuf);
4804 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4807 if (!setting_write_time) {
4808 /* ts[1] comes from change time, not write time. */
4809 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4812 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4813 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4816 * Try and set the times of this file if
4817 * they are different from the current values.
4821 struct timespec mts = get_mtimespec(psbuf);
4822 struct timespec ats = get_atimespec(psbuf);
4823 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4824 return NT_STATUS_OK;
4830 * This was a setfileinfo on an open file.
4831 * NT does this a lot. We also need to
4832 * set the time here, as it can be read by
4833 * FindFirst/FindNext and with the patch for bug #2045
4834 * in smbd/fileio.c it ensures that this timestamp is
4835 * kept sticky even after a write. We save the request
4836 * away and will set it on file close and after a write. JRA.
4839 if (!null_timespec(ts[1])) {
4840 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4841 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4842 fsp_set_pending_modtime(fsp, ts[1]);
4846 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4848 if(file_ntimes(conn, fname, ts)!=0) {
4849 return map_nt_error_from_unix(errno);
4851 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4853 return NT_STATUS_OK;
4856 /****************************************************************************
4857 Deal with setting the dosmode from any of the setfilepathinfo functions.
4858 ****************************************************************************/
4860 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4862 SMB_STRUCT_STAT *psbuf,
4865 if (!VALID_STAT(*psbuf)) {
4866 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4870 if (S_ISDIR(psbuf->st_mode)) {
4877 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4879 /* check the mode isn't different, before changing it */
4880 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4882 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4883 fname, (unsigned int)dosmode ));
4885 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
4886 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4887 fname, strerror(errno)));
4888 return map_nt_error_from_unix(errno);
4891 return NT_STATUS_OK;
4894 /****************************************************************************
4895 Deal with setting the size from any of the setfilepathinfo functions.
4896 ****************************************************************************/
4898 static NTSTATUS smb_set_file_size(connection_struct *conn,
4899 struct smb_request *req,
4902 SMB_STRUCT_STAT *psbuf,
4905 NTSTATUS status = NT_STATUS_OK;
4906 files_struct *new_fsp = NULL;
4908 if (!VALID_STAT(*psbuf)) {
4909 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4912 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4914 if (size == get_file_size(*psbuf)) {
4915 return NT_STATUS_OK;
4918 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4919 fname, (double)size ));
4921 if (fsp && fsp->fh->fd != -1) {
4922 /* Handle based call. */
4923 if (vfs_set_filelen(fsp, size) == -1) {
4924 return map_nt_error_from_unix(errno);
4926 return NT_STATUS_OK;
4929 status = open_file_ntcreate(conn, req, fname, psbuf,
4931 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4934 FILE_ATTRIBUTE_NORMAL,
4935 FORCE_OPLOCK_BREAK_TO_NONE,
4938 if (!NT_STATUS_IS_OK(status)) {
4939 /* NB. We check for open_was_deferred in the caller. */
4943 if (vfs_set_filelen(new_fsp, size) == -1) {
4944 status = map_nt_error_from_unix(errno);
4945 close_file(new_fsp,NORMAL_CLOSE);
4949 close_file(new_fsp,NORMAL_CLOSE);
4950 return NT_STATUS_OK;
4953 /****************************************************************************
4954 Deal with SMB_INFO_SET_EA.
4955 ****************************************************************************/
4957 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4963 struct ea_list *ea_list = NULL;
4964 TALLOC_CTX *ctx = NULL;
4965 NTSTATUS status = NT_STATUS_OK;
4967 if (total_data < 10) {
4969 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4970 length. They seem to have no effect. Bug #3212. JRA */
4972 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4973 /* We're done. We only get EA info in this call. */
4974 return NT_STATUS_OK;
4977 return NT_STATUS_INVALID_PARAMETER;
4980 if (IVAL(pdata,0) > total_data) {
4981 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4982 IVAL(pdata,0), (unsigned int)total_data));
4983 return NT_STATUS_INVALID_PARAMETER;
4987 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4989 return NT_STATUS_INVALID_PARAMETER;
4991 status = set_ea(conn, fsp, fname, ea_list);
4996 /****************************************************************************
4997 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4998 ****************************************************************************/
5000 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5005 SMB_STRUCT_STAT *psbuf)
5007 NTSTATUS status = NT_STATUS_OK;
5008 bool delete_on_close;
5011 if (total_data < 1) {
5012 return NT_STATUS_INVALID_PARAMETER;
5016 return NT_STATUS_INVALID_HANDLE;
5019 delete_on_close = (CVAL(pdata,0) ? True : False);
5020 dosmode = dos_mode(conn, fname, psbuf);
5022 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5023 "delete_on_close = %u\n",
5025 (unsigned int)dosmode,
5026 (unsigned int)delete_on_close ));
5028 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5030 if (!NT_STATUS_IS_OK(status)) {
5034 /* The set is across all open files on this dev/inode pair. */
5035 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
5036 return NT_STATUS_ACCESS_DENIED;
5038 return NT_STATUS_OK;
5041 /****************************************************************************
5042 Deal with SMB_FILE_POSITION_INFORMATION.
5043 ****************************************************************************/
5045 static NTSTATUS smb_file_position_information(connection_struct *conn,
5050 SMB_BIG_UINT position_information;
5052 if (total_data < 8) {
5053 return NT_STATUS_INVALID_PARAMETER;
5057 /* Ignore on pathname based set. */
5058 return NT_STATUS_OK;
5061 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
5062 #ifdef LARGE_SMB_OFF_T
5063 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5064 #else /* LARGE_SMB_OFF_T */
5065 if (IVAL(pdata,4) != 0) {
5066 /* more than 32 bits? */
5067 return NT_STATUS_INVALID_PARAMETER;
5069 #endif /* LARGE_SMB_OFF_T */
5071 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5072 fsp->fsp_name, (double)position_information ));
5073 fsp->fh->position_information = position_information;
5074 return NT_STATUS_OK;
5077 /****************************************************************************
5078 Deal with SMB_FILE_MODE_INFORMATION.
5079 ****************************************************************************/
5081 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5087 if (total_data < 4) {
5088 return NT_STATUS_INVALID_PARAMETER;
5090 mode = IVAL(pdata,0);
5091 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5092 return NT_STATUS_INVALID_PARAMETER;
5094 return NT_STATUS_OK;
5097 /****************************************************************************
5098 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5099 ****************************************************************************/
5101 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5102 struct smb_request *req,
5107 char *link_target = NULL;
5108 const char *newname = fname;
5109 NTSTATUS status = NT_STATUS_OK;
5110 TALLOC_CTX *ctx = talloc_tos();
5112 /* Set a symbolic link. */
5113 /* Don't allow this if follow links is false. */
5115 if (total_data == 0) {
5116 return NT_STATUS_INVALID_PARAMETER;
5119 if (!lp_symlinks(SNUM(conn))) {
5120 return NT_STATUS_ACCESS_DENIED;
5123 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5124 total_data, STR_TERMINATE);
5127 return NT_STATUS_INVALID_PARAMETER;
5130 /* !widelinks forces the target path to be within the share. */
5131 /* This means we can interpret the target as a pathname. */
5132 if (!lp_widelinks(SNUM(conn))) {
5133 char *rel_name = NULL;
5134 char *last_dirp = NULL;
5136 if (*link_target == '/') {
5137 /* No absolute paths allowed. */
5138 return NT_STATUS_ACCESS_DENIED;
5140 rel_name = talloc_strdup(ctx,newname);
5142 return NT_STATUS_NO_MEMORY;
5144 last_dirp = strrchr_m(rel_name, '/');
5146 last_dirp[1] = '\0';
5148 rel_name = talloc_strdup(ctx,"./");
5150 return NT_STATUS_NO_MEMORY;
5153 rel_name = talloc_asprintf_append(rel_name,
5157 return NT_STATUS_NO_MEMORY;
5160 status = check_name(conn, rel_name);
5161 if (!NT_STATUS_IS_OK(status)) {
5166 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5167 newname, link_target ));
5169 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5170 return map_nt_error_from_unix(errno);
5173 return NT_STATUS_OK;
5176 /****************************************************************************
5177 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5178 ****************************************************************************/
5180 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5181 struct smb_request *req,
5182 const char *pdata, int total_data,
5185 char *oldname = NULL;
5186 TALLOC_CTX *ctx = talloc_tos();
5187 NTSTATUS status = NT_STATUS_OK;
5189 /* Set a hard link. */
5190 if (total_data == 0) {
5191 return NT_STATUS_INVALID_PARAMETER;
5194 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5195 total_data, STR_TERMINATE, &status);
5196 if (!NT_STATUS_IS_OK(status)) {
5200 status = resolve_dfspath(ctx, conn,
5201 req->flags2 & FLAGS2_DFS_PATHNAMES,
5204 if (!NT_STATUS_IS_OK(status)) {
5208 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5211 return hardlink_internals(ctx, conn, oldname, fname);
5214 /****************************************************************************
5215 Deal with SMB_FILE_RENAME_INFORMATION.
5216 ****************************************************************************/
5218 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5219 struct smb_request *req,
5228 char *newname = NULL;
5229 char *base_name = NULL;
5230 bool dest_has_wcard = False;
5231 NTSTATUS status = NT_STATUS_OK;
5233 TALLOC_CTX *ctx = talloc_tos();
5235 if (total_data < 13) {
5236 return NT_STATUS_INVALID_PARAMETER;
5239 overwrite = (CVAL(pdata,0) ? True : False);
5240 root_fid = IVAL(pdata,4);
5241 len = IVAL(pdata,8);
5243 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5244 return NT_STATUS_INVALID_PARAMETER;
5247 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5250 if (!NT_STATUS_IS_OK(status)) {
5254 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5257 status = resolve_dfspath_wcard(ctx, conn,
5258 req->flags2 & FLAGS2_DFS_PATHNAMES,
5262 if (!NT_STATUS_IS_OK(status)) {
5266 /* Check the new name has no '/' characters. */
5267 if (strchr_m(newname, '/')) {
5268 return NT_STATUS_NOT_SUPPORTED;
5271 /* Create the base directory. */
5272 base_name = talloc_strdup(ctx, fname);
5274 return NT_STATUS_NO_MEMORY;
5276 p = strrchr_m(base_name, '/');
5280 base_name = talloc_strdup(ctx, "./");
5282 return NT_STATUS_NO_MEMORY;
5285 /* Append the new name. */
5286 base_name = talloc_asprintf_append(base_name,
5290 return NT_STATUS_NO_MEMORY;
5294 SMB_STRUCT_STAT sbuf;
5295 char *newname_last_component = NULL;
5299 status = unix_convert(ctx, conn, newname, False,
5301 &newname_last_component,
5304 /* If an error we expect this to be
5305 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5307 if (!NT_STATUS_IS_OK(status)
5308 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5313 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5314 fsp->fnum, fsp->fsp_name, base_name ));
5315 status = rename_internals_fsp(conn, fsp, base_name,
5316 newname_last_component, 0,
5319 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5320 fname, base_name ));
5321 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5322 overwrite, False, dest_has_wcard);
5328 /****************************************************************************
5329 Deal with SMB_SET_POSIX_ACL.
5330 ****************************************************************************/
5332 #if defined(HAVE_POSIX_ACLS)
5333 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5338 SMB_STRUCT_STAT *psbuf)
5340 uint16 posix_acl_version;
5341 uint16 num_file_acls;
5342 uint16 num_def_acls;
5343 bool valid_file_acls = True;
5344 bool valid_def_acls = True;
5346 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5347 return NT_STATUS_INVALID_PARAMETER;
5349 posix_acl_version = SVAL(pdata,0);
5350 num_file_acls = SVAL(pdata,2);
5351 num_def_acls = SVAL(pdata,4);
5353 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5354 valid_file_acls = False;
5358 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5359 valid_def_acls = False;
5363 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5364 return NT_STATUS_INVALID_PARAMETER;
5367 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5368 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5369 return NT_STATUS_INVALID_PARAMETER;
5372 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5373 fname ? fname : fsp->fsp_name,
5374 (unsigned int)num_file_acls,
5375 (unsigned int)num_def_acls));
5377 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5378 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5379 return map_nt_error_from_unix(errno);
5382 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5383 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5384 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5385 return map_nt_error_from_unix(errno);
5387 return NT_STATUS_OK;
5391 /****************************************************************************
5392 Deal with SMB_SET_POSIX_LOCK.
5393 ****************************************************************************/
5395 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5396 const struct smb_request *req,
5402 SMB_BIG_UINT offset;
5404 bool blocking_lock = False;
5405 enum brl_type lock_type;
5407 NTSTATUS status = NT_STATUS_OK;
5409 if (fsp == NULL || fsp->fh->fd == -1) {
5410 return NT_STATUS_INVALID_HANDLE;
5413 if (total_data != POSIX_LOCK_DATA_SIZE) {
5414 return NT_STATUS_INVALID_PARAMETER;
5417 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5418 case POSIX_LOCK_TYPE_READ:
5419 lock_type = READ_LOCK;
5421 case POSIX_LOCK_TYPE_WRITE:
5422 /* Return the right POSIX-mappable error code for files opened read-only. */
5423 if (!fsp->can_write) {
5424 return NT_STATUS_INVALID_HANDLE;
5426 lock_type = WRITE_LOCK;
5428 case POSIX_LOCK_TYPE_UNLOCK:
5429 lock_type = UNLOCK_LOCK;
5432 return NT_STATUS_INVALID_PARAMETER;
5435 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5436 blocking_lock = False;
5437 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5438 blocking_lock = True;
5440 return NT_STATUS_INVALID_PARAMETER;
5443 if (!lp_blocking_locks(SNUM(conn))) {
5444 blocking_lock = False;
5447 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5448 #if defined(HAVE_LONGLONG)
5449 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5450 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5451 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5452 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5453 #else /* HAVE_LONGLONG */
5454 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5455 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5456 #endif /* HAVE_LONGLONG */
5458 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5459 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5461 (unsigned int)lock_type,
5462 (unsigned int)lock_pid,
5466 if (lock_type == UNLOCK_LOCK) {
5467 status = do_unlock(smbd_messaging_context(),
5474 uint32 block_smbpid;
5476 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5487 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5489 * A blocking lock was requested. Package up
5490 * this smb into a queued request and push it
5491 * onto the blocking lock queue.
5493 if(push_blocking_lock_request(br_lck,
5496 -1, /* infinite timeout. */
5504 TALLOC_FREE(br_lck);
5508 TALLOC_FREE(br_lck);
5514 /****************************************************************************
5515 Deal with SMB_INFO_STANDARD.
5516 ****************************************************************************/
5518 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5523 const SMB_STRUCT_STAT *psbuf)
5525 struct timespec ts[2];
5527 if (total_data < 12) {
5528 return NT_STATUS_INVALID_PARAMETER;
5532 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5534 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5536 DEBUG(10,("smb_set_info_standard: file %s\n",
5537 fname ? fname : fsp->fsp_name ));
5539 return smb_set_file_time(conn,
5547 /****************************************************************************
5548 Deal with SMB_SET_FILE_BASIC_INFO.
5549 ****************************************************************************/
5551 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5556 SMB_STRUCT_STAT *psbuf)
5558 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5559 struct timespec write_time;
5560 struct timespec changed_time;
5562 struct timespec ts[2];
5563 NTSTATUS status = NT_STATUS_OK;
5564 bool setting_write_time = true;
5566 if (total_data < 36) {
5567 return NT_STATUS_INVALID_PARAMETER;
5570 /* Set the attributes */
5571 dosmode = IVAL(pdata,32);
5572 status = smb_set_file_dosmode(conn,
5576 if (!NT_STATUS_IS_OK(status)) {
5580 /* Ignore create time at offset pdata. */
5583 ts[0] = interpret_long_date(pdata+8);
5585 write_time = interpret_long_date(pdata+16);
5586 changed_time = interpret_long_date(pdata+24);
5589 ts[1] = timespec_min(&write_time, &changed_time);
5591 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5595 /* Prefer a defined time to an undefined one. */
5596 if (null_timespec(ts[1])) {
5597 if (null_timespec(write_time)) {
5598 ts[1] = changed_time;
5599 setting_write_time = false;
5605 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5606 fname ? fname : fsp->fsp_name ));
5608 return smb_set_file_time(conn,
5613 setting_write_time);
5616 /****************************************************************************
5617 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5618 ****************************************************************************/
5620 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5621 struct smb_request *req,
5626 SMB_STRUCT_STAT *psbuf)
5628 SMB_BIG_UINT allocation_size = 0;
5629 NTSTATUS status = NT_STATUS_OK;
5630 files_struct *new_fsp = NULL;
5632 if (!VALID_STAT(*psbuf)) {
5633 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5636 if (total_data < 8) {
5637 return NT_STATUS_INVALID_PARAMETER;
5640 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5641 #ifdef LARGE_SMB_OFF_T
5642 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5643 #else /* LARGE_SMB_OFF_T */
5644 if (IVAL(pdata,4) != 0) {
5645 /* more than 32 bits? */
5646 return NT_STATUS_INVALID_PARAMETER;
5648 #endif /* LARGE_SMB_OFF_T */
5650 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5651 fname, (double)allocation_size ));
5653 if (allocation_size) {
5654 allocation_size = smb_roundup(conn, allocation_size);
5657 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5658 fname, (double)allocation_size ));
5660 if (fsp && fsp->fh->fd != -1) {
5661 /* Open file handle. */
5662 /* Only change if needed. */
5663 if (allocation_size != get_file_size(*psbuf)) {
5664 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5665 return map_nt_error_from_unix(errno);
5668 /* But always update the time. */
5669 if (null_timespec(fsp->pending_modtime)) {
5671 * This is equivalent to a write. Ensure it's seen immediately
5672 * if there are no pending writes.
5674 set_filetime(fsp->conn, fsp->fsp_name,
5675 timespec_current());
5677 return NT_STATUS_OK;
5680 /* Pathname or stat or directory file. */
5682 status = open_file_ntcreate(conn, req, fname, psbuf,
5684 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5687 FILE_ATTRIBUTE_NORMAL,
5688 FORCE_OPLOCK_BREAK_TO_NONE,
5691 if (!NT_STATUS_IS_OK(status)) {
5692 /* NB. We check for open_was_deferred in the caller. */
5696 /* Only change if needed. */
5697 if (allocation_size != get_file_size(*psbuf)) {
5698 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5699 status = map_nt_error_from_unix(errno);
5700 close_file(new_fsp,NORMAL_CLOSE);
5705 /* Changing the allocation size should set the last mod time. */
5706 /* Don't need to call set_filetime as this will be flushed on
5709 fsp_set_pending_modtime(new_fsp, timespec_current());
5711 close_file(new_fsp,NORMAL_CLOSE);
5712 return NT_STATUS_OK;
5715 /****************************************************************************
5716 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5717 ****************************************************************************/
5719 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5720 struct smb_request *req,
5725 SMB_STRUCT_STAT *psbuf)
5729 if (total_data < 8) {
5730 return NT_STATUS_INVALID_PARAMETER;
5733 size = IVAL(pdata,0);
5734 #ifdef LARGE_SMB_OFF_T
5735 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5736 #else /* LARGE_SMB_OFF_T */
5737 if (IVAL(pdata,4) != 0) {
5738 /* more than 32 bits? */
5739 return NT_STATUS_INVALID_PARAMETER;
5741 #endif /* LARGE_SMB_OFF_T */
5742 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5743 "file %s to %.0f\n", fname, (double)size ));
5745 return smb_set_file_size(conn, req,
5752 /****************************************************************************
5753 Allow a UNIX info mknod.
5754 ****************************************************************************/
5756 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5760 SMB_STRUCT_STAT *psbuf)
5762 uint32 file_type = IVAL(pdata,56);
5763 #if defined(HAVE_MAKEDEV)
5764 uint32 dev_major = IVAL(pdata,60);
5765 uint32 dev_minor = IVAL(pdata,68);
5767 SMB_DEV_T dev = (SMB_DEV_T)0;
5768 uint32 raw_unixmode = IVAL(pdata,84);
5772 if (total_data < 100) {
5773 return NT_STATUS_INVALID_PARAMETER;
5776 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5777 if (!NT_STATUS_IS_OK(status)) {
5781 #if defined(HAVE_MAKEDEV)
5782 dev = makedev(dev_major, dev_minor);
5785 switch (file_type) {
5786 #if defined(S_IFIFO)
5787 case UNIX_TYPE_FIFO:
5788 unixmode |= S_IFIFO;
5791 #if defined(S_IFSOCK)
5792 case UNIX_TYPE_SOCKET:
5793 unixmode |= S_IFSOCK;
5796 #if defined(S_IFCHR)
5797 case UNIX_TYPE_CHARDEV:
5798 unixmode |= S_IFCHR;
5801 #if defined(S_IFBLK)
5802 case UNIX_TYPE_BLKDEV:
5803 unixmode |= S_IFBLK;
5807 return NT_STATUS_INVALID_PARAMETER;
5810 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5811 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5813 /* Ok - do the mknod. */
5814 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5815 return map_nt_error_from_unix(errno);
5818 /* If any of the other "set" calls fail we
5819 * don't want to end up with a half-constructed mknod.
5822 if (lp_inherit_perms(SNUM(conn))) {
5824 conn, parent_dirname(fname),
5828 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5829 status = map_nt_error_from_unix(errno);
5830 SMB_VFS_UNLINK(conn,fname);
5833 return NT_STATUS_OK;
5836 /****************************************************************************
5837 Deal with SMB_SET_FILE_UNIX_BASIC.
5838 ****************************************************************************/
5840 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5841 struct smb_request *req,
5846 SMB_STRUCT_STAT *psbuf)
5848 struct timespec ts[2];
5849 uint32 raw_unixmode;
5852 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5853 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5854 NTSTATUS status = NT_STATUS_OK;
5855 bool delete_on_fail = False;
5856 enum perm_type ptype;
5858 if (total_data < 100) {
5859 return NT_STATUS_INVALID_PARAMETER;
5862 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5863 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5864 size=IVAL(pdata,0); /* first 8 Bytes are size */
5865 #ifdef LARGE_SMB_OFF_T
5866 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5867 #else /* LARGE_SMB_OFF_T */
5868 if (IVAL(pdata,4) != 0) {
5869 /* more than 32 bits? */
5870 return NT_STATUS_INVALID_PARAMETER;
5872 #endif /* LARGE_SMB_OFF_T */
5875 ts[0] = interpret_long_date(pdata+24); /* access_time */
5876 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5877 set_owner = (uid_t)IVAL(pdata,40);
5878 set_grp = (gid_t)IVAL(pdata,48);
5879 raw_unixmode = IVAL(pdata,84);
5881 if (VALID_STAT(*psbuf)) {
5882 if (S_ISDIR(psbuf->st_mode)) {
5883 ptype = PERM_EXISTING_DIR;
5885 ptype = PERM_EXISTING_FILE;
5888 ptype = PERM_NEW_FILE;
5891 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5892 if (!NT_STATUS_IS_OK(status)) {
5896 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5897 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5898 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5900 if (!VALID_STAT(*psbuf)) {
5902 * The only valid use of this is to create character and block
5903 * devices, and named pipes. This is deprecated (IMHO) and
5904 * a new info level should be used for mknod. JRA.
5907 status = smb_unix_mknod(conn,
5912 if (!NT_STATUS_IS_OK(status)) {
5916 /* Ensure we don't try and change anything else. */
5917 raw_unixmode = SMB_MODE_NO_CHANGE;
5918 size = get_file_size(*psbuf);
5919 ts[0] = get_atimespec(psbuf);
5920 ts[1] = get_mtimespec(psbuf);
5922 * We continue here as we might want to change the
5925 delete_on_fail = True;
5929 /* Horrible backwards compatibility hack as an old server bug
5930 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5934 size = get_file_size(*psbuf);
5939 * Deal with the UNIX specific mode set.
5942 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5943 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5944 (unsigned int)unixmode, fname ));
5945 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5946 return map_nt_error_from_unix(errno);
5951 * Deal with the UNIX specific uid set.
5954 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5957 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
5958 (unsigned int)set_owner, fname ));
5960 if (S_ISLNK(psbuf->st_mode)) {
5961 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
5963 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
5967 status = map_nt_error_from_unix(errno);
5968 if (delete_on_fail) {
5969 SMB_VFS_UNLINK(conn,fname);
5976 * Deal with the UNIX specific gid set.
5979 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5980 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5981 (unsigned int)set_owner, fname ));
5982 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5983 status = map_nt_error_from_unix(errno);
5984 if (delete_on_fail) {
5985 SMB_VFS_UNLINK(conn,fname);
5991 /* Deal with any size changes. */
5993 status = smb_set_file_size(conn, req,
5998 if (!NT_STATUS_IS_OK(status)) {
6002 /* Deal with any time changes. */
6004 return smb_set_file_time(conn,
6012 /****************************************************************************
6013 Deal with SMB_SET_FILE_UNIX_INFO2.
6014 ****************************************************************************/
6016 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6017 struct smb_request *req,
6022 SMB_STRUCT_STAT *psbuf)
6028 if (total_data < 116) {
6029 return NT_STATUS_INVALID_PARAMETER;
6032 /* Start by setting all the fields that are common between UNIX_BASIC
6035 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6037 if (!NT_STATUS_IS_OK(status)) {
6041 smb_fflags = IVAL(pdata, 108);
6042 smb_fmask = IVAL(pdata, 112);
6044 /* NB: We should only attempt to alter the file flags if the client
6045 * sends a non-zero mask.
6047 if (smb_fmask != 0) {
6048 int stat_fflags = 0;
6050 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6052 /* Client asked to alter a flag we don't understand. */
6053 return NT_STATUS_INVALID_PARAMETER;
6056 if (fsp && fsp->fh->fd != -1) {
6057 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6058 return NT_STATUS_NOT_SUPPORTED;
6060 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6061 return map_nt_error_from_unix(errno);
6066 /* XXX: need to add support for changing the create_time here. You
6067 * can do this for paths on Darwin with setattrlist(2). The right way
6068 * to hook this up is probably by extending the VFS utimes interface.
6071 return NT_STATUS_OK;
6074 /****************************************************************************
6075 Create a directory with POSIX semantics.
6076 ****************************************************************************/
6078 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6079 struct smb_request *req,
6083 SMB_STRUCT_STAT *psbuf,
6084 int *pdata_return_size)
6086 NTSTATUS status = NT_STATUS_OK;
6087 uint32 raw_unixmode = 0;
6088 uint32 mod_unixmode = 0;
6089 mode_t unixmode = (mode_t)0;
6090 files_struct *fsp = NULL;
6091 uint16 info_level_return = 0;
6093 char *pdata = *ppdata;
6095 if (total_data < 18) {
6096 return NT_STATUS_INVALID_PARAMETER;
6099 raw_unixmode = IVAL(pdata,8);
6100 /* Next 4 bytes are not yet defined. */
6102 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6103 if (!NT_STATUS_IS_OK(status)) {
6107 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6109 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6110 fname, (unsigned int)unixmode ));
6112 status = open_directory(conn, req,
6115 FILE_READ_ATTRIBUTES, /* Just a stat open */
6116 FILE_SHARE_NONE, /* Ignored for stat opens */
6123 if (NT_STATUS_IS_OK(status)) {
6124 close_file(fsp, NORMAL_CLOSE);
6127 info_level_return = SVAL(pdata,16);
6129 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6130 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6131 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6132 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6134 *pdata_return_size = 12;
6137 /* Realloc the data size */
6138 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6139 if (*ppdata == NULL) {
6140 *pdata_return_size = 0;
6141 return NT_STATUS_NO_MEMORY;
6145 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6146 SSVAL(pdata,2,0); /* No fnum. */
6147 SIVAL(pdata,4,info); /* Was directory created. */
6149 switch (info_level_return) {
6150 case SMB_QUERY_FILE_UNIX_BASIC:
6151 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6152 SSVAL(pdata,10,0); /* Padding. */
6153 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6155 case SMB_QUERY_FILE_UNIX_INFO2:
6156 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6157 SSVAL(pdata,10,0); /* Padding. */
6158 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6161 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6162 SSVAL(pdata,10,0); /* Padding. */
6169 /****************************************************************************
6170 Open/Create a file with POSIX semantics.
6171 ****************************************************************************/
6173 static NTSTATUS smb_posix_open(connection_struct *conn,
6174 struct smb_request *req,
6178 SMB_STRUCT_STAT *psbuf,
6179 int *pdata_return_size)
6181 bool extended_oplock_granted = False;
6182 char *pdata = *ppdata;
6184 uint32 wire_open_mode = 0;
6185 uint32 raw_unixmode = 0;
6186 uint32 mod_unixmode = 0;
6187 uint32 create_disp = 0;
6188 uint32 access_mask = 0;
6189 uint32 create_options = 0;
6190 NTSTATUS status = NT_STATUS_OK;
6191 mode_t unixmode = (mode_t)0;
6192 files_struct *fsp = NULL;
6193 int oplock_request = 0;
6195 uint16 info_level_return = 0;
6197 if (total_data < 18) {
6198 return NT_STATUS_INVALID_PARAMETER;
6201 flags = IVAL(pdata,0);
6202 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6203 if (oplock_request) {
6204 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6207 wire_open_mode = IVAL(pdata,4);
6209 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6210 return smb_posix_mkdir(conn, req,
6218 switch (wire_open_mode & SMB_ACCMODE) {
6220 access_mask = FILE_READ_DATA;
6223 access_mask = FILE_WRITE_DATA;
6226 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6229 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6230 (unsigned int)wire_open_mode ));
6231 return NT_STATUS_INVALID_PARAMETER;
6234 wire_open_mode &= ~SMB_ACCMODE;
6236 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6237 create_disp = FILE_CREATE;
6238 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6239 create_disp = FILE_OVERWRITE_IF;
6240 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6241 create_disp = FILE_OPEN_IF;
6243 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6244 (unsigned int)wire_open_mode ));
6245 return NT_STATUS_INVALID_PARAMETER;
6248 raw_unixmode = IVAL(pdata,8);
6249 /* Next 4 bytes are not yet defined. */
6251 status = unix_perms_from_wire(conn,
6254 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6257 if (!NT_STATUS_IS_OK(status)) {
6261 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6263 if (wire_open_mode & SMB_O_SYNC) {
6264 create_options |= FILE_WRITE_THROUGH;
6266 if (wire_open_mode & SMB_O_APPEND) {
6267 access_mask |= FILE_APPEND_DATA;
6269 if (wire_open_mode & SMB_O_DIRECT) {
6270 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6273 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6275 (unsigned int)wire_open_mode,
6276 (unsigned int)unixmode ));
6278 status = open_file_ntcreate(conn, req,
6282 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6284 0, /* no create options yet. */
6290 if (!NT_STATUS_IS_OK(status)) {
6294 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6295 extended_oplock_granted = True;
6298 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6299 extended_oplock_granted = True;
6302 info_level_return = SVAL(pdata,16);
6304 /* Allocate the correct return size. */
6306 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6307 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6308 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6309 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6311 *pdata_return_size = 12;
6314 /* Realloc the data size */
6315 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6316 if (*ppdata == NULL) {
6317 close_file(fsp,ERROR_CLOSE);
6318 *pdata_return_size = 0;
6319 return NT_STATUS_NO_MEMORY;
6323 if (extended_oplock_granted) {
6324 if (flags & REQUEST_BATCH_OPLOCK) {
6325 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6327 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6329 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6330 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6332 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6335 SSVAL(pdata,2,fsp->fnum);
6336 SIVAL(pdata,4,info); /* Was file created etc. */
6338 switch (info_level_return) {
6339 case SMB_QUERY_FILE_UNIX_BASIC:
6340 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6341 SSVAL(pdata,10,0); /* padding. */
6342 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6344 case SMB_QUERY_FILE_UNIX_INFO2:
6345 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6346 SSVAL(pdata,10,0); /* padding. */
6347 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6350 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6351 SSVAL(pdata,10,0); /* padding. */
6354 return NT_STATUS_OK;
6357 /****************************************************************************
6358 Delete a file with POSIX semantics.
6359 ****************************************************************************/
6361 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6362 struct smb_request *req,
6366 SMB_STRUCT_STAT *psbuf)
6368 NTSTATUS status = NT_STATUS_OK;
6369 files_struct *fsp = NULL;
6374 struct share_mode_lock *lck = NULL;
6376 if (total_data < 2) {
6377 return NT_STATUS_INVALID_PARAMETER;
6380 flags = SVAL(pdata,0);
6382 if (!VALID_STAT(*psbuf)) {
6383 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6386 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6387 !VALID_STAT_OF_DIR(*psbuf)) {
6388 return NT_STATUS_NOT_A_DIRECTORY;
6391 DEBUG(10,("smb_posix_unlink: %s %s\n",
6392 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6395 if (VALID_STAT_OF_DIR(*psbuf)) {
6396 status = open_directory(conn, req,
6400 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6403 FILE_FLAG_POSIX_SEMANTICS|0777,
6408 status = open_file_ntcreate(conn, req,
6412 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6415 FILE_FLAG_POSIX_SEMANTICS|0777,
6416 0, /* No oplock, but break existing ones. */
6421 if (!NT_STATUS_IS_OK(status)) {
6426 * Don't lie to client. If we can't really delete due to
6427 * non-POSIX opens return SHARING_VIOLATION.
6430 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL);
6432 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6433 "lock for file %s\n", fsp->fsp_name));
6434 close_file(fsp, NORMAL_CLOSE);
6435 return NT_STATUS_INVALID_PARAMETER;
6439 * See if others still have the file open. If this is the case, then
6440 * don't delete. If all opens are POSIX delete we can set the delete
6441 * on close disposition.
6443 for (i=0; i<lck->num_share_modes; i++) {
6444 struct share_mode_entry *e = &lck->share_modes[i];
6445 if (is_valid_share_mode_entry(e)) {
6446 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6449 /* Fail with sharing violation. */
6450 close_file(fsp, NORMAL_CLOSE);
6452 return NT_STATUS_SHARING_VIOLATION;
6457 * Set the delete on close.
6459 status = smb_set_file_disposition_info(conn,
6466 if (!NT_STATUS_IS_OK(status)) {
6467 close_file(fsp, NORMAL_CLOSE);
6472 return close_file(fsp, NORMAL_CLOSE);
6475 /****************************************************************************
6476 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6477 ****************************************************************************/
6479 static void call_trans2setfilepathinfo(connection_struct *conn,
6480 struct smb_request *req,
6481 unsigned int tran_call,
6482 char **pparams, int total_params,
6483 char **ppdata, int total_data,
6484 unsigned int max_data_bytes)
6486 char *params = *pparams;
6487 char *pdata = *ppdata;
6489 SMB_STRUCT_STAT sbuf;
6491 files_struct *fsp = NULL;
6492 NTSTATUS status = NT_STATUS_OK;
6493 int data_return_size = 0;
6494 TALLOC_CTX *ctx = talloc_tos();
6497 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6503 if (tran_call == TRANSACT2_SETFILEINFO) {
6504 if (total_params < 4) {
6505 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6509 fsp = file_fsp(SVAL(params,0));
6510 /* Basic check for non-null fsp. */
6511 if (!check_fsp_open(conn, req, fsp, ¤t_user)) {
6514 info_level = SVAL(params,2);
6516 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6518 reply_nterror(req, NT_STATUS_NO_MEMORY);
6522 if(fsp->is_directory || fsp->fh->fd == -1) {
6524 * This is actually a SETFILEINFO on a directory
6525 * handle (returned from an NT SMB). NT5.0 seems
6526 * to do this call. JRA.
6528 if (INFO_LEVEL_IS_UNIX(info_level)) {
6529 /* Always do lstat for UNIX calls. */
6530 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6531 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6532 reply_unixerror(req,ERRDOS,ERRbadpath);
6536 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6537 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6538 reply_unixerror(req,ERRDOS,ERRbadpath);
6542 } else if (fsp->print_file) {
6544 * Doing a DELETE_ON_CLOSE should cancel a print job.
6546 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6547 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6549 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6552 send_trans2_replies(conn, req, params, 2,
6557 reply_unixerror(req, ERRDOS, ERRbadpath);
6562 * Original code - this is an open file.
6564 if (!check_fsp(conn, req, fsp, ¤t_user)) {
6568 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6569 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6570 reply_unixerror(req, ERRDOS, ERRbadfid);
6576 if (total_params < 7) {
6577 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6581 info_level = SVAL(params,0);
6582 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
6583 total_params - 6, STR_TERMINATE,
6585 if (!NT_STATUS_IS_OK(status)) {
6586 reply_nterror(req, status);
6590 status = resolve_dfspath(ctx, conn,
6591 req->flags2 & FLAGS2_DFS_PATHNAMES,
6594 if (!NT_STATUS_IS_OK(status)) {
6595 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6596 reply_botherror(req,
6597 NT_STATUS_PATH_NOT_COVERED,
6598 ERRSRV, ERRbadpath);
6601 reply_nterror(req, status);
6605 status = unix_convert(ctx, conn, fname, False,
6606 &fname, NULL, &sbuf);
6607 if (!NT_STATUS_IS_OK(status)) {
6608 reply_nterror(req, status);
6612 status = check_name(conn, fname);
6613 if (!NT_STATUS_IS_OK(status)) {
6614 reply_nterror(req, status);
6618 if (INFO_LEVEL_IS_UNIX(info_level)) {
6620 * For CIFS UNIX extensions the target name may not exist.
6623 /* Always do lstat for UNIX calls. */
6624 SMB_VFS_LSTAT(conn,fname,&sbuf);
6626 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6627 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6628 reply_unixerror(req, ERRDOS, ERRbadpath);
6633 if (!CAN_WRITE(conn)) {
6634 reply_doserror(req, ERRSRV, ERRaccess);
6638 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6639 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6643 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6644 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6646 /* Realloc the parameter size */
6647 *pparams = (char *)SMB_REALLOC(*pparams,2);
6648 if (*pparams == NULL) {
6649 reply_nterror(req, NT_STATUS_NO_MEMORY);
6656 if (fsp && !null_timespec(fsp->pending_modtime)) {
6657 /* the pending modtime overrides the current modtime */
6658 set_mtimespec(&sbuf, fsp->pending_modtime);
6661 switch (info_level) {
6663 case SMB_INFO_STANDARD:
6665 status = smb_set_info_standard(conn,
6674 case SMB_INFO_SET_EA:
6676 status = smb_info_set_ea(conn,
6684 case SMB_SET_FILE_BASIC_INFO:
6685 case SMB_FILE_BASIC_INFORMATION:
6687 status = smb_set_file_basic_info(conn,
6696 case SMB_FILE_ALLOCATION_INFORMATION:
6697 case SMB_SET_FILE_ALLOCATION_INFO:
6699 status = smb_set_file_allocation_info(conn, req,
6708 case SMB_FILE_END_OF_FILE_INFORMATION:
6709 case SMB_SET_FILE_END_OF_FILE_INFO:
6711 status = smb_set_file_end_of_file_info(conn, req,
6720 case SMB_FILE_DISPOSITION_INFORMATION:
6721 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6724 /* JRA - We used to just ignore this on a path ?
6725 * Shouldn't this be invalid level on a pathname
6728 if (tran_call != TRANSACT2_SETFILEINFO) {
6729 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6732 status = smb_set_file_disposition_info(conn,
6741 case SMB_FILE_POSITION_INFORMATION:
6743 status = smb_file_position_information(conn,
6750 /* From tridge Samba4 :
6751 * MODE_INFORMATION in setfileinfo (I have no
6752 * idea what "mode information" on a file is - it takes a value of 0,
6753 * 2, 4 or 6. What could it be?).
6756 case SMB_FILE_MODE_INFORMATION:
6758 status = smb_file_mode_information(conn,
6765 * CIFS UNIX extensions.
6768 case SMB_SET_FILE_UNIX_BASIC:
6770 status = smb_set_file_unix_basic(conn, req,
6779 case SMB_SET_FILE_UNIX_INFO2:
6781 status = smb_set_file_unix_info2(conn, req,
6790 case SMB_SET_FILE_UNIX_LINK:
6792 if (tran_call != TRANSACT2_SETPATHINFO) {
6793 /* We must have a pathname for this. */
6794 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6797 status = smb_set_file_unix_link(conn, req, pdata,
6802 case SMB_SET_FILE_UNIX_HLINK:
6804 if (tran_call != TRANSACT2_SETPATHINFO) {
6805 /* We must have a pathname for this. */
6806 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6809 status = smb_set_file_unix_hlink(conn, req,
6815 case SMB_FILE_RENAME_INFORMATION:
6817 status = smb_file_rename_information(conn, req,
6823 #if defined(HAVE_POSIX_ACLS)
6824 case SMB_SET_POSIX_ACL:
6826 status = smb_set_posix_acl(conn,
6836 case SMB_SET_POSIX_LOCK:
6838 if (tran_call != TRANSACT2_SETFILEINFO) {
6839 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6842 status = smb_set_posix_lock(conn, req,
6843 pdata, total_data, fsp);
6847 case SMB_POSIX_PATH_OPEN:
6849 if (tran_call != TRANSACT2_SETPATHINFO) {
6850 /* We must have a pathname for this. */
6851 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6855 status = smb_posix_open(conn, req,
6864 case SMB_POSIX_PATH_UNLINK:
6866 if (tran_call != TRANSACT2_SETPATHINFO) {
6867 /* We must have a pathname for this. */
6868 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6872 status = smb_posix_unlink(conn, req,
6881 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6886 if (!NT_STATUS_IS_OK(status)) {
6887 if (open_was_deferred(req->mid)) {
6888 /* We have re-scheduled this call. */
6891 if (blocking_lock_was_deferred(req->mid)) {
6892 /* We have re-scheduled this call. */
6895 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6896 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6897 ERRSRV, ERRbadpath);
6900 if (info_level == SMB_POSIX_PATH_OPEN) {
6901 reply_openerror(req, status);
6905 reply_nterror(req, status);
6910 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
6916 /****************************************************************************
6917 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6918 ****************************************************************************/
6920 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
6921 char **pparams, int total_params,
6922 char **ppdata, int total_data,
6923 unsigned int max_data_bytes)
6925 char *params = *pparams;
6926 char *pdata = *ppdata;
6927 char *directory = NULL;
6928 SMB_STRUCT_STAT sbuf;
6929 NTSTATUS status = NT_STATUS_OK;
6930 struct ea_list *ea_list = NULL;
6931 TALLOC_CTX *ctx = talloc_tos();
6933 if (!CAN_WRITE(conn)) {
6934 reply_doserror(req, ERRSRV, ERRaccess);
6938 if (total_params < 5) {
6939 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6943 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
6944 total_params - 4, STR_TERMINATE,
6946 if (!NT_STATUS_IS_OK(status)) {
6947 reply_nterror(req, status);
6951 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6953 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
6954 if (!NT_STATUS_IS_OK(status)) {
6955 reply_nterror(req, status);
6959 status = check_name(conn, directory);
6960 if (!NT_STATUS_IS_OK(status)) {
6961 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6962 reply_nterror(req, status);
6966 /* Any data in this call is an EA list. */
6967 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6968 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6973 * OS/2 workplace shell seems to send SET_EA requests of "null"
6974 * length (4 bytes containing IVAL 4).
6975 * They seem to have no effect. Bug #3212. JRA.
6978 if (total_data != 4) {
6979 if (total_data < 10) {
6980 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6984 if (IVAL(pdata,0) > total_data) {
6985 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6986 IVAL(pdata,0), (unsigned int)total_data));
6987 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6991 ea_list = read_ea_list(talloc_tos(), pdata + 4,
6994 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6997 } else if (IVAL(pdata,0) != 4) {
6998 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7002 status = create_directory(conn, req, directory);
7004 if (!NT_STATUS_IS_OK(status)) {
7005 reply_nterror(req, status);
7009 /* Try and set any given EA. */
7011 status = set_ea(conn, NULL, directory, ea_list);
7012 if (!NT_STATUS_IS_OK(status)) {
7013 reply_nterror(req, status);
7018 /* Realloc the parameter and data sizes */
7019 *pparams = (char *)SMB_REALLOC(*pparams,2);
7020 if(*pparams == NULL) {
7021 reply_nterror(req, NT_STATUS_NO_MEMORY);
7028 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7033 /****************************************************************************
7034 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7035 We don't actually do this - we just send a null response.
7036 ****************************************************************************/
7038 static void call_trans2findnotifyfirst(connection_struct *conn,
7039 struct smb_request *req,
7040 char **pparams, int total_params,
7041 char **ppdata, int total_data,
7042 unsigned int max_data_bytes)
7044 static uint16 fnf_handle = 257;
7045 char *params = *pparams;
7048 if (total_params < 6) {
7049 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7053 info_level = SVAL(params,4);
7054 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7056 switch (info_level) {
7061 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7065 /* Realloc the parameter and data sizes */
7066 *pparams = (char *)SMB_REALLOC(*pparams,6);
7067 if (*pparams == NULL) {
7068 reply_nterror(req, NT_STATUS_NO_MEMORY);
7073 SSVAL(params,0,fnf_handle);
7074 SSVAL(params,2,0); /* No changes */
7075 SSVAL(params,4,0); /* No EA errors */
7082 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7087 /****************************************************************************
7088 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7089 changes). Currently this does nothing.
7090 ****************************************************************************/
7092 static void call_trans2findnotifynext(connection_struct *conn,
7093 struct smb_request *req,
7094 char **pparams, int total_params,
7095 char **ppdata, int total_data,
7096 unsigned int max_data_bytes)
7098 char *params = *pparams;
7100 DEBUG(3,("call_trans2findnotifynext\n"));
7102 /* Realloc the parameter and data sizes */
7103 *pparams = (char *)SMB_REALLOC(*pparams,4);
7104 if (*pparams == NULL) {
7105 reply_nterror(req, NT_STATUS_NO_MEMORY);
7110 SSVAL(params,0,0); /* No changes */
7111 SSVAL(params,2,0); /* No EA errors */
7113 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7118 /****************************************************************************
7119 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7120 ****************************************************************************/
7122 static void call_trans2getdfsreferral(connection_struct *conn,
7123 struct smb_request *req,
7124 char **pparams, int total_params,
7125 char **ppdata, int total_data,
7126 unsigned int max_data_bytes)
7128 char *params = *pparams;
7129 char *pathname = NULL;
7131 int max_referral_level;
7132 NTSTATUS status = NT_STATUS_OK;
7133 TALLOC_CTX *ctx = talloc_tos();
7135 DEBUG(10,("call_trans2getdfsreferral\n"));
7137 if (total_params < 3) {
7138 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7142 max_referral_level = SVAL(params,0);
7144 if(!lp_host_msdfs()) {
7145 reply_doserror(req, ERRDOS, ERRbadfunc);
7149 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7150 total_params - 2, STR_TERMINATE);
7152 reply_nterror(req, NT_STATUS_NOT_FOUND);
7155 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7156 ppdata,&status)) < 0) {
7157 reply_nterror(req, status);
7161 SSVAL(req->inbuf, smb_flg2,
7162 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7163 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7168 #define LMCAT_SPL 0x53
7169 #define LMFUNC_GETJOBID 0x60
7171 /****************************************************************************
7172 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7173 ****************************************************************************/
7175 static void call_trans2ioctl(connection_struct *conn,
7176 struct smb_request *req,
7177 char **pparams, int total_params,
7178 char **ppdata, int total_data,
7179 unsigned int max_data_bytes)
7181 char *pdata = *ppdata;
7182 files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15));
7184 /* check for an invalid fid before proceeding */
7187 reply_doserror(req, ERRDOS, ERRbadfid);
7191 if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7192 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7193 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7194 if (*ppdata == NULL) {
7195 reply_nterror(req, NT_STATUS_NO_MEMORY);
7200 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7201 CAN ACCEPT THIS IN UNICODE. JRA. */
7203 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7204 srvstr_push(pdata, req->flags2, pdata + 2,
7205 global_myname(), 15,
7206 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7207 srvstr_push(pdata, req->flags2, pdata+18,
7208 lp_servicename(SNUM(conn)), 13,
7209 STR_ASCII|STR_TERMINATE); /* Service name */
7210 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7215 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7216 reply_doserror(req, ERRSRV, ERRerror);
7219 /****************************************************************************
7220 Reply to a SMBfindclose (stop trans2 directory search).
7221 ****************************************************************************/
7223 void reply_findclose(struct smb_request *req)
7227 START_PROFILE(SMBfindclose);
7230 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7231 END_PROFILE(SMBfindclose);
7235 dptr_num = SVALS(req->inbuf,smb_vwv0);
7237 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7239 dptr_close(&dptr_num);
7241 reply_outbuf(req, 0, 0);
7243 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7245 END_PROFILE(SMBfindclose);
7249 /****************************************************************************
7250 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7251 ****************************************************************************/
7253 void reply_findnclose(struct smb_request *req)
7257 START_PROFILE(SMBfindnclose);
7260 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7261 END_PROFILE(SMBfindnclose);
7265 dptr_num = SVAL(req->inbuf,smb_vwv0);
7267 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7269 /* We never give out valid handles for a
7270 findnotifyfirst - so any dptr_num is ok here.
7273 reply_outbuf(req, 0, 0);
7275 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7277 END_PROFILE(SMBfindnclose);
7281 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7282 struct trans_state *state)
7284 if (Protocol >= PROTOCOL_NT1) {
7285 req->flags2 |= 0x40; /* IS_LONG_NAME */
7286 SSVAL(req->inbuf,smb_flg2,req->flags2);
7289 if (conn->encrypt_level == Required && !req->encrypted) {
7290 if (state->call != TRANSACT2_QFSINFO &&
7291 state->call != TRANSACT2_SETFSINFO) {
7292 DEBUG(0,("handle_trans2: encryption required "
7294 (unsigned int)state->call));
7295 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7300 /* Now we must call the relevant TRANS2 function */
7301 switch(state->call) {
7302 case TRANSACT2_OPEN:
7304 START_PROFILE(Trans2_open);
7305 call_trans2open(conn, req,
7306 &state->param, state->total_param,
7307 &state->data, state->total_data,
7308 state->max_data_return);
7309 END_PROFILE(Trans2_open);
7313 case TRANSACT2_FINDFIRST:
7315 START_PROFILE(Trans2_findfirst);
7316 call_trans2findfirst(conn, req,
7317 &state->param, state->total_param,
7318 &state->data, state->total_data,
7319 state->max_data_return);
7320 END_PROFILE(Trans2_findfirst);
7324 case TRANSACT2_FINDNEXT:
7326 START_PROFILE(Trans2_findnext);
7327 call_trans2findnext(conn, req,
7328 &state->param, state->total_param,
7329 &state->data, state->total_data,
7330 state->max_data_return);
7331 END_PROFILE(Trans2_findnext);
7335 case TRANSACT2_QFSINFO:
7337 START_PROFILE(Trans2_qfsinfo);
7338 call_trans2qfsinfo(conn, req,
7339 &state->param, state->total_param,
7340 &state->data, state->total_data,
7341 state->max_data_return);
7342 END_PROFILE(Trans2_qfsinfo);
7346 case TRANSACT2_SETFSINFO:
7348 START_PROFILE(Trans2_setfsinfo);
7349 call_trans2setfsinfo(conn, req,
7350 &state->param, state->total_param,
7351 &state->data, state->total_data,
7352 state->max_data_return);
7353 END_PROFILE(Trans2_setfsinfo);
7357 case TRANSACT2_QPATHINFO:
7358 case TRANSACT2_QFILEINFO:
7360 START_PROFILE(Trans2_qpathinfo);
7361 call_trans2qfilepathinfo(conn, req, state->call,
7362 &state->param, state->total_param,
7363 &state->data, state->total_data,
7364 state->max_data_return);
7365 END_PROFILE(Trans2_qpathinfo);
7369 case TRANSACT2_SETPATHINFO:
7370 case TRANSACT2_SETFILEINFO:
7372 START_PROFILE(Trans2_setpathinfo);
7373 call_trans2setfilepathinfo(conn, req, state->call,
7374 &state->param, state->total_param,
7375 &state->data, state->total_data,
7376 state->max_data_return);
7377 END_PROFILE(Trans2_setpathinfo);
7381 case TRANSACT2_FINDNOTIFYFIRST:
7383 START_PROFILE(Trans2_findnotifyfirst);
7384 call_trans2findnotifyfirst(conn, req,
7385 &state->param, state->total_param,
7386 &state->data, state->total_data,
7387 state->max_data_return);
7388 END_PROFILE(Trans2_findnotifyfirst);
7392 case TRANSACT2_FINDNOTIFYNEXT:
7394 START_PROFILE(Trans2_findnotifynext);
7395 call_trans2findnotifynext(conn, req,
7396 &state->param, state->total_param,
7397 &state->data, state->total_data,
7398 state->max_data_return);
7399 END_PROFILE(Trans2_findnotifynext);
7403 case TRANSACT2_MKDIR:
7405 START_PROFILE(Trans2_mkdir);
7406 call_trans2mkdir(conn, req,
7407 &state->param, state->total_param,
7408 &state->data, state->total_data,
7409 state->max_data_return);
7410 END_PROFILE(Trans2_mkdir);
7414 case TRANSACT2_GET_DFS_REFERRAL:
7416 START_PROFILE(Trans2_get_dfs_referral);
7417 call_trans2getdfsreferral(conn, req,
7418 &state->param, state->total_param,
7419 &state->data, state->total_data,
7420 state->max_data_return);
7421 END_PROFILE(Trans2_get_dfs_referral);
7425 case TRANSACT2_IOCTL:
7427 START_PROFILE(Trans2_ioctl);
7428 call_trans2ioctl(conn, req,
7429 &state->param, state->total_param,
7430 &state->data, state->total_data,
7431 state->max_data_return);
7432 END_PROFILE(Trans2_ioctl);
7437 /* Error in request */
7438 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7439 reply_doserror(req, ERRSRV,ERRerror);
7443 /****************************************************************************
7444 Reply to a SMBtrans2.
7445 ****************************************************************************/
7447 void reply_trans2(struct smb_request *req)
7449 connection_struct *conn = req->conn;
7454 unsigned int tran_call;
7456 struct trans_state *state;
7459 START_PROFILE(SMBtrans2);
7461 if (req->wct < 14) {
7462 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7463 END_PROFILE(SMBtrans2);
7467 dsoff = SVAL(req->inbuf, smb_dsoff);
7468 dscnt = SVAL(req->inbuf, smb_dscnt);
7469 psoff = SVAL(req->inbuf, smb_psoff);
7470 pscnt = SVAL(req->inbuf, smb_pscnt);
7471 tran_call = SVAL(req->inbuf, smb_setup0);
7472 size = smb_len(req->inbuf) + 4;
7474 result = allow_new_trans(conn->pending_trans, req->mid);
7475 if (!NT_STATUS_IS_OK(result)) {
7476 DEBUG(2, ("Got invalid trans2 request: %s\n",
7477 nt_errstr(result)));
7478 reply_nterror(req, result);
7479 END_PROFILE(SMBtrans2);
7484 switch (tran_call) {
7485 /* List the allowed trans2 calls on IPC$ */
7486 case TRANSACT2_OPEN:
7487 case TRANSACT2_GET_DFS_REFERRAL:
7488 case TRANSACT2_QFILEINFO:
7489 case TRANSACT2_QFSINFO:
7490 case TRANSACT2_SETFSINFO:
7493 reply_doserror(req, ERRSRV, ERRaccess);
7494 END_PROFILE(SMBtrans2);
7499 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
7500 DEBUG(0, ("talloc failed\n"));
7501 reply_nterror(req, NT_STATUS_NO_MEMORY);
7502 END_PROFILE(SMBtrans2);
7506 state->cmd = SMBtrans2;
7508 state->mid = req->mid;
7509 state->vuid = req->vuid;
7510 state->setup_count = SVAL(req->inbuf, smb_suwcnt);
7511 state->setup = NULL;
7512 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7513 state->param = NULL;
7514 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7516 state->max_param_return = SVAL(req->inbuf, smb_mprcnt);
7517 state->max_data_return = SVAL(req->inbuf, smb_mdrcnt);
7518 state->max_setup_return = SVAL(req->inbuf, smb_msrcnt);
7519 state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0);
7520 state->one_way = BITSETW(req->inbuf+smb_vwv5,1);
7522 state->call = tran_call;
7524 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7525 is so as a sanity check */
7526 if (state->setup_count != 1) {
7528 * Need to have rc=0 for ioctl to get job id for OS/2.
7529 * Network printing will fail if function is not successful.
7530 * Similar function in reply.c will be used if protocol
7531 * is LANMAN1.0 instead of LM1.2X002.
7532 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7533 * outbuf doesn't have to be set(only job id is used).
7535 if ( (state->setup_count == 4)
7536 && (tran_call == TRANSACT2_IOCTL)
7537 && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7538 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7539 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7541 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7542 DEBUG(2,("Transaction is %d\n",tran_call));
7544 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7545 END_PROFILE(SMBtrans2);
7550 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7553 if (state->total_data) {
7554 /* Can't use talloc here, the core routines do realloc on the
7555 * params and data. */
7556 state->data = (char *)SMB_MALLOC(state->total_data);
7557 if (state->data == NULL) {
7558 DEBUG(0,("reply_trans2: data malloc fail for %u "
7559 "bytes !\n", (unsigned int)state->total_data));
7561 reply_nterror(req, NT_STATUS_NO_MEMORY);
7562 END_PROFILE(SMBtrans2);
7565 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
7567 if ((smb_base(req->inbuf)+dsoff+dscnt
7568 > (char *)req->inbuf + size) ||
7569 (smb_base(req->inbuf)+dsoff+dscnt < smb_base(req->inbuf)))
7572 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7575 if (state->total_param) {
7576 /* Can't use talloc here, the core routines do realloc on the
7577 * params and data. */
7578 state->param = (char *)SMB_MALLOC(state->total_param);
7579 if (state->param == NULL) {
7580 DEBUG(0,("reply_trans: param malloc fail for %u "
7581 "bytes !\n", (unsigned int)state->total_param));
7582 SAFE_FREE(state->data);
7584 reply_nterror(req, NT_STATUS_NO_MEMORY);
7585 END_PROFILE(SMBtrans2);
7588 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
7590 if ((smb_base(req->inbuf)+psoff+pscnt
7591 > (char *)req->inbuf + size) ||
7592 (smb_base(req->inbuf)+psoff+pscnt < smb_base(req->inbuf)))
7595 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7598 state->received_data = dscnt;
7599 state->received_param = pscnt;
7601 if ((state->received_param == state->total_param) &&
7602 (state->received_data == state->total_data)) {
7604 handle_trans2(conn, req, state);
7606 SAFE_FREE(state->data);
7607 SAFE_FREE(state->param);
7609 END_PROFILE(SMBtrans2);
7613 DLIST_ADD(conn->pending_trans, state);
7615 /* We need to send an interim response then receive the rest
7616 of the parameter/data bytes */
7617 reply_outbuf(req, 0, 0);
7618 show_msg((char *)req->outbuf);
7619 END_PROFILE(SMBtrans2);
7624 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7625 SAFE_FREE(state->data);
7626 SAFE_FREE(state->param);
7628 END_PROFILE(SMBtrans2);
7629 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7633 /****************************************************************************
7634 Reply to a SMBtranss2
7635 ****************************************************************************/
7637 void reply_transs2(struct smb_request *req)
7639 connection_struct *conn = req->conn;
7640 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7641 struct trans_state *state;
7644 START_PROFILE(SMBtranss2);
7646 show_msg((char *)req->inbuf);
7649 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7650 END_PROFILE(SMBtranss2);
7654 size = smb_len(req->inbuf)+4;
7656 for (state = conn->pending_trans; state != NULL;
7657 state = state->next) {
7658 if (state->mid == req->mid) {
7663 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7664 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7665 END_PROFILE(SMBtranss2);
7669 /* Revise state->total_param and state->total_data in case they have
7670 changed downwards */
7672 if (SVAL(req->inbuf, smb_tpscnt) < state->total_param)
7673 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7674 if (SVAL(req->inbuf, smb_tdscnt) < state->total_data)
7675 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7677 pcnt = SVAL(req->inbuf, smb_spscnt);
7678 poff = SVAL(req->inbuf, smb_spsoff);
7679 pdisp = SVAL(req->inbuf, smb_spsdisp);
7681 dcnt = SVAL(req->inbuf, smb_sdscnt);
7682 doff = SVAL(req->inbuf, smb_sdsoff);
7683 ddisp = SVAL(req->inbuf, smb_sdsdisp);
7685 state->received_param += pcnt;
7686 state->received_data += dcnt;
7688 if ((state->received_data > state->total_data) ||
7689 (state->received_param > state->total_param))
7693 if (pdisp+pcnt > state->total_param)
7695 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
7697 if (pdisp > state->total_param)
7699 if ((smb_base(req->inbuf) + poff + pcnt
7700 > (char *)req->inbuf + size) ||
7701 (smb_base(req->inbuf) + poff + pcnt < smb_base(req->inbuf)))
7703 if (state->param + pdisp < state->param)
7706 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,
7711 if (ddisp+dcnt > state->total_data)
7713 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
7715 if (ddisp > state->total_data)
7717 if ((smb_base(req->inbuf) + doff + dcnt
7718 > (char *)req->inbuf + size) ||
7719 (smb_base(req->inbuf) + doff + dcnt < smb_base(req->inbuf)))
7721 if (state->data + ddisp < state->data)
7724 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
7728 if ((state->received_param < state->total_param) ||
7729 (state->received_data < state->total_data)) {
7730 END_PROFILE(SMBtranss2);
7735 * construct_reply_common will copy smb_com from inbuf to
7736 * outbuf. SMBtranss2 is wrong here.
7738 SCVAL(req->inbuf,smb_com,SMBtrans2);
7740 handle_trans2(conn, req, state);
7742 DLIST_REMOVE(conn->pending_trans, state);
7743 SAFE_FREE(state->data);
7744 SAFE_FREE(state->param);
7747 END_PROFILE(SMBtranss2);
7752 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7753 DLIST_REMOVE(conn->pending_trans, state);
7754 SAFE_FREE(state->data);
7755 SAFE_FREE(state->param);
7757 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7758 END_PROFILE(SMBtranss2);