2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
29 extern enum protocol_types Protocol;
30 extern uint32 global_client_caps;
31 extern struct current_user current_user;
33 #define get_file_size(sbuf) ((sbuf).st_size)
34 #define DIR_ENTRY_SAFETY_MARGIN 4096
36 static char *store_file_unix_basic(connection_struct *conn,
39 const SMB_STRUCT_STAT *psbuf);
41 static char *store_file_unix_basic_info2(connection_struct *conn,
44 const SMB_STRUCT_STAT *psbuf);
46 /********************************************************************
47 Roundup a value to the nearest allocation roundup size boundary.
48 Only do this for Windows clients.
49 ********************************************************************/
51 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
53 SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
55 /* Only roundup for Windows clients. */
56 enum remote_arch_types ra_type = get_remote_arch();
57 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
58 val = SMB_ROUNDUP(val,rval);
63 /********************************************************************
64 Given a stat buffer return the allocated size on disk, taking into
66 ********************************************************************/
68 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
72 if(S_ISDIR(sbuf->st_mode)) {
76 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
77 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
79 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
82 if (fsp && fsp->initial_allocation_size)
83 ret = MAX(ret,fsp->initial_allocation_size);
85 return smb_roundup(conn, ret);
88 /****************************************************************************
89 Utility functions for dealing with extended attributes.
90 ****************************************************************************/
92 /****************************************************************************
93 Refuse to allow clients to overwrite our private xattrs.
94 ****************************************************************************/
96 static bool samba_private_attr_name(const char *unix_ea_name)
98 static const char *prohibited_ea_names[] = {
99 SAMBA_POSIX_INHERITANCE_EA_NAME,
100 SAMBA_XATTR_DOS_ATTRIB,
106 for (i = 0; prohibited_ea_names[i]; i++) {
107 if (strequal( prohibited_ea_names[i], unix_ea_name))
110 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
111 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
117 /****************************************************************************
118 Get one EA value. Fill in a struct ea_struct.
119 ****************************************************************************/
121 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
122 files_struct *fsp, const char *fname,
123 const char *ea_name, struct ea_struct *pea)
125 /* Get the value of this xattr. Max size is 64k. */
126 size_t attr_size = 256;
132 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
134 return NT_STATUS_NO_MEMORY;
137 if (fsp && fsp->fh->fd != -1) {
138 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
140 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
143 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
149 return map_nt_error_from_unix(errno);
152 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
153 dump_data(10, (uint8 *)val, sizeret);
156 if (strnequal(ea_name, "user.", 5)) {
157 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
159 pea->name = talloc_strdup(mem_ctx, ea_name);
161 if (pea->name == NULL) {
163 return NT_STATUS_NO_MEMORY;
165 pea->value.data = (unsigned char *)val;
166 pea->value.length = (size_t)sizeret;
170 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
171 files_struct *fsp, const char *fname,
172 char ***pnames, size_t *pnum_names)
174 /* Get a list of all xattrs. Max namesize is 64k. */
175 size_t ea_namelist_size = 1024;
176 char *ea_namelist = NULL;
183 if (!lp_ea_support(SNUM(conn))) {
190 * TALLOC the result early to get the talloc hierarchy right.
193 names = TALLOC_ARRAY(mem_ctx, char *, 1);
195 DEBUG(0, ("talloc failed\n"));
196 return NT_STATUS_NO_MEMORY;
199 while (ea_namelist_size <= 65536) {
201 ea_namelist = TALLOC_REALLOC_ARRAY(
202 names, ea_namelist, char, ea_namelist_size);
203 if (ea_namelist == NULL) {
204 DEBUG(0, ("talloc failed\n"));
206 return NT_STATUS_NO_MEMORY;
209 if (fsp && fsp->fh->fd != -1) {
210 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
213 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
217 if ((sizeret == -1) && (errno == ERANGE)) {
218 ea_namelist_size *= 2;
227 return map_nt_error_from_unix(errno);
230 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
231 (unsigned int)sizeret));
241 * Ensure the result is 0-terminated
244 if (ea_namelist[sizeret-1] != '\0') {
246 return NT_STATUS_INTERNAL_ERROR;
254 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
258 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
260 DEBUG(0, ("talloc failed\n"));
262 return NT_STATUS_NO_MEMORY;
268 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
269 names[num_names++] = p;
273 *pnum_names = num_names;
277 /****************************************************************************
278 Return a linked list of the total EA's. Plus the total size
279 ****************************************************************************/
281 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
282 const char *fname, size_t *pea_total_len)
284 /* Get a list of all xattrs. Max namesize is 64k. */
287 struct ea_list *ea_list_head = NULL;
292 if (!lp_ea_support(SNUM(conn))) {
296 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
299 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
303 for (i=0; i<num_names; i++) {
304 struct ea_list *listp;
307 if (strnequal(names[i], "system.", 7)
308 || samba_private_attr_name(names[i]))
311 listp = TALLOC_P(mem_ctx, struct ea_list);
316 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
322 push_ascii_fstring(dos_ea_name, listp->ea.name);
325 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
327 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
328 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
329 (unsigned int)listp->ea.value.length));
331 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
335 /* Add on 4 for total length. */
336 if (*pea_total_len) {
340 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
341 (unsigned int)*pea_total_len));
346 /****************************************************************************
347 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
349 ****************************************************************************/
351 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
352 connection_struct *conn, struct ea_list *ea_list)
354 unsigned int ret_data_size = 4;
357 SMB_ASSERT(total_data_size >= 4);
359 if (!lp_ea_support(SNUM(conn))) {
364 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
367 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
368 dos_namelen = strlen(dos_ea_name);
369 if (dos_namelen > 255 || dos_namelen == 0) {
372 if (ea_list->ea.value.length > 65535) {
375 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
379 /* We know we have room. */
380 SCVAL(p,0,ea_list->ea.flags);
381 SCVAL(p,1,dos_namelen);
382 SSVAL(p,2,ea_list->ea.value.length);
383 fstrcpy(p+4, dos_ea_name);
384 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
386 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
387 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
390 ret_data_size = PTR_DIFF(p, pdata);
391 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
392 SIVAL(pdata,0,ret_data_size);
393 return ret_data_size;
396 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
398 size_t total_ea_len = 0;
399 TALLOC_CTX *mem_ctx = NULL;
401 if (!lp_ea_support(SNUM(conn))) {
404 mem_ctx = talloc_tos();
405 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
409 /****************************************************************************
410 Ensure the EA name is case insensitive by matching any existing EA name.
411 ****************************************************************************/
413 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
416 TALLOC_CTX *mem_ctx = talloc_tos();
417 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
419 for (; ea_list; ea_list = ea_list->next) {
420 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
421 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
422 &unix_ea_name[5], ea_list->ea.name));
423 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
429 /****************************************************************************
430 Set or delete an extended attribute.
431 ****************************************************************************/
433 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
435 if (!lp_ea_support(SNUM(conn))) {
436 return NT_STATUS_EAS_NOT_SUPPORTED;
439 for (;ea_list; ea_list = ea_list->next) {
441 fstring unix_ea_name;
443 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
444 fstrcat(unix_ea_name, ea_list->ea.name);
446 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
448 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
450 if (samba_private_attr_name(unix_ea_name)) {
451 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
452 return NT_STATUS_ACCESS_DENIED;
455 if (ea_list->ea.value.length == 0) {
456 /* Remove the attribute. */
457 if (fsp && (fsp->fh->fd != -1)) {
458 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
459 unix_ea_name, fsp->fsp_name));
460 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
462 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
463 unix_ea_name, fname));
464 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
467 /* Removing a non existent attribute always succeeds. */
468 if (ret == -1 && errno == ENOATTR) {
469 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
475 if (fsp && (fsp->fh->fd != -1)) {
476 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
477 unix_ea_name, fsp->fsp_name));
478 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
479 ea_list->ea.value.data, ea_list->ea.value.length, 0);
481 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
482 unix_ea_name, fname));
483 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
484 ea_list->ea.value.data, ea_list->ea.value.length, 0);
490 if (errno == ENOTSUP) {
491 return NT_STATUS_EAS_NOT_SUPPORTED;
494 return map_nt_error_from_unix(errno);
500 /****************************************************************************
501 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
502 ****************************************************************************/
504 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
506 struct ea_list *ea_list_head = NULL;
509 while (offset + 2 < data_size) {
510 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
511 unsigned int namelen = CVAL(pdata,offset);
513 offset++; /* Go past the namelen byte. */
515 /* integer wrap paranioa. */
516 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
517 (offset > data_size) || (namelen > data_size) ||
518 (offset + namelen >= data_size)) {
521 /* Ensure the name is null terminated. */
522 if (pdata[offset + namelen] != '\0') {
525 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
530 offset += (namelen + 1); /* Go past the name + terminating zero. */
531 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
532 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
538 /****************************************************************************
539 Read one EA list entry from the buffer.
540 ****************************************************************************/
542 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
544 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
546 unsigned int namelen;
556 eal->ea.flags = CVAL(pdata,0);
557 namelen = CVAL(pdata,1);
558 val_len = SVAL(pdata,2);
560 if (4 + namelen + 1 + val_len > data_size) {
564 /* Ensure the name is null terminated. */
565 if (pdata[namelen + 4] != '\0') {
568 pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
573 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
574 if (!eal->ea.value.data) {
578 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
580 /* Ensure we're null terminated just in case we print the value. */
581 eal->ea.value.data[val_len] = '\0';
582 /* But don't count the null. */
583 eal->ea.value.length--;
586 *pbytes_used = 4 + namelen + 1 + val_len;
589 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
590 dump_data(10, eal->ea.value.data, eal->ea.value.length);
595 /****************************************************************************
596 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
597 ****************************************************************************/
599 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
601 struct ea_list *ea_list_head = NULL;
603 size_t bytes_used = 0;
605 while (offset < data_size) {
606 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
612 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
613 offset += bytes_used;
619 /****************************************************************************
620 Count the total EA size needed.
621 ****************************************************************************/
623 static size_t ea_list_size(struct ea_list *ealist)
626 struct ea_list *listp;
629 for (listp = ealist; listp; listp = listp->next) {
630 push_ascii_fstring(dos_ea_name, listp->ea.name);
631 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
633 /* Add on 4 for total length. */
641 /****************************************************************************
642 Return a union of EA's from a file list and a list of names.
643 The TALLOC context for the two lists *MUST* be identical as we steal
644 memory from one list to add to another. JRA.
645 ****************************************************************************/
647 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
649 struct ea_list *nlistp, *flistp;
651 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
652 for (flistp = file_list; flistp; flistp = flistp->next) {
653 if (strequal(nlistp->ea.name, flistp->ea.name)) {
659 /* Copy the data from this entry. */
660 nlistp->ea.flags = flistp->ea.flags;
661 nlistp->ea.value = flistp->ea.value;
664 nlistp->ea.flags = 0;
665 ZERO_STRUCT(nlistp->ea.value);
669 *total_ea_len = ea_list_size(name_list);
673 /****************************************************************************
674 Send the required number of replies back.
675 We assume all fields other than the data fields are
676 set correctly for the type of call.
677 HACK ! Always assumes smb_setup field is zero.
678 ****************************************************************************/
680 void send_trans2_replies(connection_struct *conn,
681 struct smb_request *req,
688 /* As we are using a protocol > LANMAN1 then the max_send
689 variable must have been set in the sessetupX call.
690 This takes precedence over the max_xmit field in the
691 global struct. These different max_xmit variables should
692 be merged as this is now too confusing */
694 int data_to_send = datasize;
695 int params_to_send = paramsize;
697 const char *pp = params;
698 const char *pd = pdata;
699 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
700 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
701 int data_alignment_offset = 0;
702 bool overflow = False;
704 /* Modify the data_to_send and datasize and set the error if
705 we're trying to send more than max_data_bytes. We still send
706 the part of the packet(s) that fit. Strange, but needed
709 if (max_data_bytes > 0 && datasize > max_data_bytes) {
710 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
711 max_data_bytes, datasize ));
712 datasize = data_to_send = max_data_bytes;
716 /* If there genuinely are no parameters or data to send just send the empty packet */
718 if(params_to_send == 0 && data_to_send == 0) {
719 reply_outbuf(req, 10, 0);
720 show_msg((char *)req->outbuf);
724 /* When sending params and data ensure that both are nicely aligned */
725 /* Only do this alignment when there is also data to send - else
726 can cause NT redirector problems. */
728 if (((params_to_send % 4) != 0) && (data_to_send != 0))
729 data_alignment_offset = 4 - (params_to_send % 4);
731 /* Space is bufsize minus Netbios over TCP header minus SMB header */
732 /* The alignment_offset is to align the param bytes on an even byte
733 boundary. NT 4.0 Beta needs this to work correctly. */
735 useable_space = max_send - (smb_size
738 + data_alignment_offset);
740 /* useable_space can never be more than max_send minus the alignment offset. */
742 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
744 while (params_to_send || data_to_send) {
745 /* Calculate whether we will totally or partially fill this packet */
747 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
749 /* We can never send more than useable_space */
751 * Note that 'useable_space' does not include the alignment offsets,
752 * but we must include the alignment offsets in the calculation of
753 * the length of the data we send over the wire, as the alignment offsets
754 * are sent here. Fix from Marc_Jacobsen@hp.com.
757 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
759 reply_outbuf(req, 10, total_sent_thistime);
761 /* Set total params and data to be sent */
762 SSVAL(req->outbuf,smb_tprcnt,paramsize);
763 SSVAL(req->outbuf,smb_tdrcnt,datasize);
765 /* Calculate how many parameters and data we can fit into
766 * this packet. Parameters get precedence
769 params_sent_thistime = MIN(params_to_send,useable_space);
770 data_sent_thistime = useable_space - params_sent_thistime;
771 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
773 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
775 /* smb_proff is the offset from the start of the SMB header to the
776 parameter bytes, however the first 4 bytes of outbuf are
777 the Netbios over TCP header. Thus use smb_base() to subtract
778 them from the calculation */
780 SSVAL(req->outbuf,smb_proff,
781 ((smb_buf(req->outbuf)+alignment_offset)
782 - smb_base(req->outbuf)));
784 if(params_sent_thistime == 0)
785 SSVAL(req->outbuf,smb_prdisp,0);
787 /* Absolute displacement of param bytes sent in this packet */
788 SSVAL(req->outbuf,smb_prdisp,pp - params);
790 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
791 if(data_sent_thistime == 0) {
792 SSVAL(req->outbuf,smb_droff,0);
793 SSVAL(req->outbuf,smb_drdisp, 0);
795 /* The offset of the data bytes is the offset of the
796 parameter bytes plus the number of parameters being sent this time */
797 SSVAL(req->outbuf, smb_droff,
798 ((smb_buf(req->outbuf)+alignment_offset)
799 - smb_base(req->outbuf))
800 + params_sent_thistime + data_alignment_offset);
801 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
804 /* Initialize the padding for alignment */
806 if (alignment_offset != 0) {
807 memset(smb_buf(req->outbuf), 0, alignment_offset);
810 /* Copy the param bytes into the packet */
812 if(params_sent_thistime) {
813 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
814 params_sent_thistime);
817 /* Copy in the data bytes */
818 if(data_sent_thistime) {
819 if (data_alignment_offset != 0) {
820 memset((smb_buf(req->outbuf)+alignment_offset+
821 params_sent_thistime), 0,
822 data_alignment_offset);
824 memcpy(smb_buf(req->outbuf)+alignment_offset
825 +params_sent_thistime+data_alignment_offset,
826 pd,data_sent_thistime);
829 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
830 params_sent_thistime, data_sent_thistime, useable_space));
831 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
832 params_to_send, data_to_send, paramsize, datasize));
835 error_packet_set((char *)req->outbuf,
836 ERRDOS,ERRbufferoverflow,
837 STATUS_BUFFER_OVERFLOW,
841 /* Send the packet */
842 show_msg((char *)req->outbuf);
843 if (!srv_send_smb(smbd_server_fd(),
845 IS_CONN_ENCRYPTED(conn)))
846 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
848 TALLOC_FREE(req->outbuf);
850 pp += params_sent_thistime;
851 pd += data_sent_thistime;
853 params_to_send -= params_sent_thistime;
854 data_to_send -= data_sent_thistime;
857 if(params_to_send < 0 || data_to_send < 0) {
858 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
859 params_to_send, data_to_send));
867 /****************************************************************************
868 Reply to a TRANSACT2_OPEN.
869 ****************************************************************************/
871 static void call_trans2open(connection_struct *conn,
872 struct smb_request *req,
873 char **pparams, int total_params,
874 char **ppdata, int total_data,
875 unsigned int max_data_bytes)
877 char *params = *pparams;
878 char *pdata = *ppdata;
883 bool return_additional_info;
894 SMB_STRUCT_STAT sbuf;
897 struct ea_list *ea_list = NULL;
902 uint32 create_disposition;
903 uint32 create_options = 0;
904 TALLOC_CTX *ctx = talloc_tos();
907 * Ensure we have enough parameters to perform the operation.
910 if (total_params < 29) {
911 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
915 flags = SVAL(params, 0);
916 deny_mode = SVAL(params, 2);
917 open_attr = SVAL(params,6);
918 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
919 if (oplock_request) {
920 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
924 return_additional_info = BITSETW(params,0);
925 open_sattr = SVAL(params, 4);
926 open_time = make_unix_date3(params+8);
928 open_ofun = SVAL(params,12);
929 open_size = IVAL(params,14);
933 reply_doserror(req, ERRSRV, ERRaccess);
937 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
938 total_params - 28, STR_TERMINATE,
940 if (!NT_STATUS_IS_OK(status)) {
941 reply_nterror(req, status);
945 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
946 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
947 (unsigned int)open_ofun, open_size));
949 if (open_ofun == 0) {
950 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
954 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
959 reply_doserror(req, ERRDOS, ERRbadaccess);
963 /* Any data in this call is an EA list. */
964 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
965 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
969 if (total_data != 4) {
970 if (total_data < 10) {
971 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
975 if (IVAL(pdata,0) > total_data) {
976 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
977 IVAL(pdata,0), (unsigned int)total_data));
978 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
982 ea_list = read_ea_list(talloc_tos(), pdata + 4,
985 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
988 } else if (IVAL(pdata,0) != 4) {
989 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
993 status = create_file(conn, /* conn */
995 0, /* root_dir_fid */
997 access_mask, /* access_mask */
998 share_mode, /* share_access */
999 create_disposition, /* create_disposition*/
1000 create_options, /* create_options */
1001 open_attr, /* file_attributes */
1002 oplock_request, /* oplock_request */
1003 open_size, /* allocation_size */
1005 ea_list, /* ea_list */
1007 &smb_action, /* pinfo */
1010 if (!NT_STATUS_IS_OK(status)) {
1011 if (open_was_deferred(req->mid)) {
1012 /* We have re-scheduled this call. */
1015 reply_openerror(req, status);
1019 size = get_file_size(sbuf);
1020 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1021 mtime = sbuf.st_mtime;
1022 inode = sbuf.st_ino;
1024 close_file(fsp,ERROR_CLOSE);
1025 reply_doserror(req, ERRDOS,ERRnoaccess);
1029 /* Realloc the size of parameters and data we will return */
1030 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1031 if(*pparams == NULL ) {
1032 reply_nterror(req, NT_STATUS_NO_MEMORY);
1037 SSVAL(params,0,fsp->fnum);
1038 SSVAL(params,2,fattr);
1039 srv_put_dos_date2(params,4, mtime);
1040 SIVAL(params,8, (uint32)size);
1041 SSVAL(params,12,deny_mode);
1042 SSVAL(params,14,0); /* open_type - file or directory. */
1043 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1045 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1046 smb_action |= EXTENDED_OPLOCK_GRANTED;
1049 SSVAL(params,18,smb_action);
1052 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1054 SIVAL(params,20,inode);
1055 SSVAL(params,24,0); /* Padding. */
1057 uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
1058 SIVAL(params, 26, ea_size);
1060 SIVAL(params, 26, 0);
1063 /* Send the required number of replies */
1064 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1067 /*********************************************************
1068 Routine to check if a given string matches exactly.
1069 as a special case a mask of "." does NOT match. That
1070 is required for correct wildcard semantics
1071 Case can be significant or not.
1072 **********************************************************/
1074 static bool exact_match(connection_struct *conn,
1078 if (mask[0] == '.' && mask[1] == 0)
1080 if (conn->case_sensitive)
1081 return strcmp(str,mask)==0;
1082 if (StrCaseCmp(str,mask) != 0) {
1085 if (dptr_has_wild(conn->dirptr)) {
1091 /****************************************************************************
1092 Return the filetype for UNIX extensions.
1093 ****************************************************************************/
1095 static uint32 unix_filetype(mode_t mode)
1098 return UNIX_TYPE_FILE;
1099 else if(S_ISDIR(mode))
1100 return UNIX_TYPE_DIR;
1102 else if(S_ISLNK(mode))
1103 return UNIX_TYPE_SYMLINK;
1106 else if(S_ISCHR(mode))
1107 return UNIX_TYPE_CHARDEV;
1110 else if(S_ISBLK(mode))
1111 return UNIX_TYPE_BLKDEV;
1114 else if(S_ISFIFO(mode))
1115 return UNIX_TYPE_FIFO;
1118 else if(S_ISSOCK(mode))
1119 return UNIX_TYPE_SOCKET;
1122 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1123 return UNIX_TYPE_UNKNOWN;
1126 /****************************************************************************
1127 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1128 ****************************************************************************/
1130 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1132 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1133 SMB_STRUCT_STAT *psbuf,
1135 enum perm_type ptype,
1140 if (perms == SMB_MODE_NO_CHANGE) {
1141 if (!VALID_STAT(*psbuf)) {
1142 return NT_STATUS_INVALID_PARAMETER;
1144 *ret_perms = psbuf->st_mode;
1145 return NT_STATUS_OK;
1149 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1150 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1151 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1152 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1153 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1154 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1155 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1156 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1157 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1159 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1162 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1165 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1170 /* Apply mode mask */
1171 ret &= lp_create_mask(SNUM(conn));
1172 /* Add in force bits */
1173 ret |= lp_force_create_mode(SNUM(conn));
1176 ret &= lp_dir_mask(SNUM(conn));
1177 /* Add in force bits */
1178 ret |= lp_force_dir_mode(SNUM(conn));
1180 case PERM_EXISTING_FILE:
1181 /* Apply mode mask */
1182 ret &= lp_security_mask(SNUM(conn));
1183 /* Add in force bits */
1184 ret |= lp_force_security_mode(SNUM(conn));
1186 case PERM_EXISTING_DIR:
1187 /* Apply mode mask */
1188 ret &= lp_dir_security_mask(SNUM(conn));
1189 /* Add in force bits */
1190 ret |= lp_force_dir_security_mode(SNUM(conn));
1195 return NT_STATUS_OK;
1198 /****************************************************************************
1199 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. */
1241 struct timespec write_time_ts;
1243 *out_of_space = False;
1244 *got_exact_match = False;
1246 ZERO_STRUCT(mdate_ts);
1247 ZERO_STRUCT(adate_ts);
1248 ZERO_STRUCT(create_date_ts);
1250 if (!conn->dirptr) {
1254 p = strrchr_m(path_mask,'/');
1257 mask = talloc_strdup(ctx,"*.*");
1267 bool ms_dfs_link = False;
1269 /* Needed if we run out of space */
1270 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1271 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1274 * Due to bugs in NT client redirectors we are not using
1275 * resume keys any more - set them to zero.
1276 * Check out the related comments in findfirst/findnext.
1282 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1283 (long)conn->dirptr,curr_dirpos));
1290 * fname may get mangled, dname is never mangled.
1291 * Whenever we're accessing the filesystem we use
1292 * pathreal which is composed from dname.
1298 /* Mangle fname if it's an illegal name. */
1299 if (mangle_must_mangle(dname,conn->params)) {
1300 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1301 continue; /* Error - couldn't mangle. */
1303 fname = mangled_name;
1306 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1307 got_match = mask_match(fname, mask, conn->case_sensitive);
1310 if(!got_match && check_mangled_names &&
1311 !mangle_is_8_3(fname, False, conn->params)) {
1313 * It turns out that NT matches wildcards against
1314 * both long *and* short names. This may explain some
1315 * of the wildcard wierdness from old DOS clients
1316 * that some people have been seeing.... JRA.
1318 /* Force the mangling into 8.3. */
1319 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1320 continue; /* Error - couldn't mangle. */
1323 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1324 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1329 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1331 if (dont_descend && !isdots) {
1337 pathreal = talloc_asprintf(ctx,
1342 pathreal = talloc_asprintf(ctx,
1352 if (INFO_LEVEL_IS_UNIX(info_level)) {
1353 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1354 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1355 pathreal,strerror(errno)));
1356 TALLOC_FREE(pathreal);
1359 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1360 /* Needed to show the msdfs symlinks as
1363 if(lp_host_msdfs() &&
1364 lp_msdfs_root(SNUM(conn)) &&
1365 ((ms_dfs_link = is_msdfs_link(conn, pathreal, &sbuf)) == True)) {
1366 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
1369 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1373 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1374 pathreal,strerror(errno)));
1375 TALLOC_FREE(pathreal);
1381 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1383 mode = dos_mode(conn,pathreal,&sbuf);
1386 if (!dir_check_ftype(conn,mode,dirtype)) {
1387 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1388 TALLOC_FREE(pathreal);
1392 if (!(mode & aDIR)) {
1393 file_size = get_file_size(sbuf);
1395 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1397 mdate_ts = get_mtimespec(&sbuf);
1398 adate_ts = get_atimespec(&sbuf);
1399 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1401 write_time_ts = get_write_time(
1402 vfs_file_id_from_sbuf(conn, &sbuf));
1403 if (!null_timespec(write_time_ts)) {
1404 mdate_ts = write_time_ts;
1407 if (lp_dos_filetime_resolution(SNUM(conn))) {
1408 dos_filetime_timespec(&create_date_ts);
1409 dos_filetime_timespec(&mdate_ts);
1410 dos_filetime_timespec(&adate_ts);
1413 create_date = convert_timespec_to_time_t(create_date_ts);
1414 mdate = convert_timespec_to_time_t(mdate_ts);
1415 adate = convert_timespec_to_time_t(adate_ts);
1417 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1421 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1428 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1430 switch (info_level) {
1431 case SMB_FIND_INFO_STANDARD:
1432 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1433 if(requires_resume_key) {
1437 srv_put_dos_date2(p,0,create_date);
1438 srv_put_dos_date2(p,4,adate);
1439 srv_put_dos_date2(p,8,mdate);
1440 SIVAL(p,12,(uint32)file_size);
1441 SIVAL(p,16,(uint32)allocation_size);
1445 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1446 p += ucs2_align(base_data, p, 0);
1448 len = srvstr_push(base_data, flags2, p,
1449 fname, PTR_DIFF(end_data, p),
1451 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1453 SCVAL(nameptr, -1, len - 2);
1455 SCVAL(nameptr, -1, 0);
1459 SCVAL(nameptr, -1, len - 1);
1461 SCVAL(nameptr, -1, 0);
1467 case SMB_FIND_EA_SIZE:
1468 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1469 if(requires_resume_key) {
1473 srv_put_dos_date2(p,0,create_date);
1474 srv_put_dos_date2(p,4,adate);
1475 srv_put_dos_date2(p,8,mdate);
1476 SIVAL(p,12,(uint32)file_size);
1477 SIVAL(p,16,(uint32)allocation_size);
1480 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1481 SIVAL(p,22,ea_size); /* Extended attributes */
1485 len = srvstr_push(base_data, flags2,
1486 p, fname, PTR_DIFF(end_data, p),
1487 STR_TERMINATE | STR_NOALIGN);
1488 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1501 SCVAL(nameptr,0,len);
1503 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1506 case SMB_FIND_EA_LIST:
1508 struct ea_list *file_list = NULL;
1511 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1515 if(requires_resume_key) {
1519 srv_put_dos_date2(p,0,create_date);
1520 srv_put_dos_date2(p,4,adate);
1521 srv_put_dos_date2(p,8,mdate);
1522 SIVAL(p,12,(uint32)file_size);
1523 SIVAL(p,16,(uint32)allocation_size);
1525 p += 22; /* p now points to the EA area. */
1527 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1528 name_list = ea_list_union(name_list, file_list, &ea_len);
1530 /* We need to determine if this entry will fit in the space available. */
1531 /* Max string size is 255 bytes. */
1532 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1533 /* Move the dirptr back to prev_dirpos */
1534 dptr_SeekDir(conn->dirptr, prev_dirpos);
1535 *out_of_space = True;
1536 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1537 return False; /* Not finished - just out of space */
1540 /* Push the ea_data followed by the name. */
1541 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1543 len = srvstr_push(base_data, flags2,
1544 p + 1, fname, PTR_DIFF(end_data, p+1),
1545 STR_TERMINATE | STR_NOALIGN);
1546 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1559 SCVAL(nameptr,0,len);
1561 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1565 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1566 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1567 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1569 SIVAL(p,0,reskey); p += 4;
1570 put_long_date_timespec(p,create_date_ts); p += 8;
1571 put_long_date_timespec(p,adate_ts); p += 8;
1572 put_long_date_timespec(p,mdate_ts); p += 8;
1573 put_long_date_timespec(p,mdate_ts); p += 8;
1574 SOFF_T(p,0,file_size); p += 8;
1575 SOFF_T(p,0,allocation_size); p += 8;
1576 SIVAL(p,0,nt_extmode); p += 4;
1577 q = p; p += 4; /* q is placeholder for name length. */
1579 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1580 SIVAL(p,0,ea_size); /* Extended attributes */
1583 /* Clear the short name buffer. This is
1584 * IMPORTANT as not doing so will trigger
1585 * a Win2k client bug. JRA.
1587 if (!was_8_3 && check_mangled_names) {
1588 if (!name_to_8_3(fname,mangled_name,True,
1590 /* Error - mangle failed ! */
1591 memset(mangled_name,'\0',12);
1593 mangled_name[12] = 0;
1594 len = srvstr_push(base_data, flags2,
1595 p+2, mangled_name, 24,
1596 STR_UPPER|STR_UNICODE);
1598 memset(p + 2 + len,'\0',24 - len);
1605 len = srvstr_push(base_data, flags2, p,
1606 fname, PTR_DIFF(end_data, p),
1607 STR_TERMINATE_ASCII);
1610 SIVAL(p,0,0); /* Ensure any padding is null. */
1611 len = PTR_DIFF(p, pdata);
1612 len = (len + 3) & ~3;
1617 case SMB_FIND_FILE_DIRECTORY_INFO:
1618 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1620 SIVAL(p,0,reskey); p += 4;
1621 put_long_date_timespec(p,create_date_ts); p += 8;
1622 put_long_date_timespec(p,adate_ts); p += 8;
1623 put_long_date_timespec(p,mdate_ts); p += 8;
1624 put_long_date_timespec(p,mdate_ts); p += 8;
1625 SOFF_T(p,0,file_size); p += 8;
1626 SOFF_T(p,0,allocation_size); p += 8;
1627 SIVAL(p,0,nt_extmode); p += 4;
1628 len = srvstr_push(base_data, flags2,
1629 p + 4, fname, PTR_DIFF(end_data, p+4),
1630 STR_TERMINATE_ASCII);
1633 SIVAL(p,0,0); /* Ensure any padding is null. */
1634 len = PTR_DIFF(p, pdata);
1635 len = (len + 3) & ~3;
1640 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1641 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1643 SIVAL(p,0,reskey); p += 4;
1644 put_long_date_timespec(p,create_date_ts); p += 8;
1645 put_long_date_timespec(p,adate_ts); p += 8;
1646 put_long_date_timespec(p,mdate_ts); p += 8;
1647 put_long_date_timespec(p,mdate_ts); p += 8;
1648 SOFF_T(p,0,file_size); p += 8;
1649 SOFF_T(p,0,allocation_size); p += 8;
1650 SIVAL(p,0,nt_extmode); p += 4;
1651 q = p; p += 4; /* q is placeholder for name length. */
1653 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1654 SIVAL(p,0,ea_size); /* Extended attributes */
1657 len = srvstr_push(base_data, flags2, p,
1658 fname, PTR_DIFF(end_data, p),
1659 STR_TERMINATE_ASCII);
1663 SIVAL(p,0,0); /* Ensure any padding is null. */
1664 len = PTR_DIFF(p, pdata);
1665 len = (len + 3) & ~3;
1670 case SMB_FIND_FILE_NAMES_INFO:
1671 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1673 SIVAL(p,0,reskey); p += 4;
1675 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1676 acl on a dir (tridge) */
1677 len = srvstr_push(base_data, flags2, p,
1678 fname, PTR_DIFF(end_data, p),
1679 STR_TERMINATE_ASCII);
1682 SIVAL(p,0,0); /* Ensure any padding is null. */
1683 len = PTR_DIFF(p, pdata);
1684 len = (len + 3) & ~3;
1689 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1690 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1692 SIVAL(p,0,reskey); p += 4;
1693 put_long_date_timespec(p,create_date_ts); p += 8;
1694 put_long_date_timespec(p,adate_ts); p += 8;
1695 put_long_date_timespec(p,mdate_ts); p += 8;
1696 put_long_date_timespec(p,mdate_ts); p += 8;
1697 SOFF_T(p,0,file_size); p += 8;
1698 SOFF_T(p,0,allocation_size); p += 8;
1699 SIVAL(p,0,nt_extmode); p += 4;
1700 q = p; p += 4; /* q is placeholder for name length. */
1702 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1703 SIVAL(p,0,ea_size); /* Extended attributes */
1706 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1707 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1708 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1709 len = srvstr_push(base_data, flags2, p,
1710 fname, PTR_DIFF(end_data, p),
1711 STR_TERMINATE_ASCII);
1714 SIVAL(p,0,0); /* Ensure any padding is null. */
1715 len = PTR_DIFF(p, pdata);
1716 len = (len + 3) & ~3;
1721 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1722 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1723 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1725 SIVAL(p,0,reskey); p += 4;
1726 put_long_date_timespec(p,create_date_ts); p += 8;
1727 put_long_date_timespec(p,adate_ts); p += 8;
1728 put_long_date_timespec(p,mdate_ts); p += 8;
1729 put_long_date_timespec(p,mdate_ts); p += 8;
1730 SOFF_T(p,0,file_size); p += 8;
1731 SOFF_T(p,0,allocation_size); p += 8;
1732 SIVAL(p,0,nt_extmode); p += 4;
1733 q = p; p += 4; /* q is placeholder for name length */
1735 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1736 SIVAL(p,0,ea_size); /* Extended attributes */
1739 /* Clear the short name buffer. This is
1740 * IMPORTANT as not doing so will trigger
1741 * a Win2k client bug. JRA.
1743 if (!was_8_3 && check_mangled_names) {
1744 if (!name_to_8_3(fname,mangled_name,True,
1746 /* Error - mangle failed ! */
1747 memset(mangled_name,'\0',12);
1749 mangled_name[12] = 0;
1750 len = srvstr_push(base_data, flags2,
1751 p+2, mangled_name, 24,
1752 STR_UPPER|STR_UNICODE);
1755 memset(p + 2 + len,'\0',24 - len);
1762 SSVAL(p,0,0); p += 2; /* Reserved ? */
1763 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1764 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1765 len = srvstr_push(base_data, flags2, p,
1766 fname, PTR_DIFF(end_data, p),
1767 STR_TERMINATE_ASCII);
1770 SIVAL(p,0,0); /* Ensure any padding is null. */
1771 len = PTR_DIFF(p, pdata);
1772 len = (len + 3) & ~3;
1777 /* CIFS UNIX Extension. */
1779 case SMB_FIND_FILE_UNIX:
1780 case SMB_FIND_FILE_UNIX_INFO2:
1782 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1784 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1786 if (info_level == SMB_FIND_FILE_UNIX) {
1787 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1788 p = store_file_unix_basic(conn, p,
1790 len = srvstr_push(base_data, flags2, p,
1791 fname, PTR_DIFF(end_data, p),
1794 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1795 p = store_file_unix_basic_info2(conn, p,
1799 len = srvstr_push(base_data, flags2, p, fname,
1800 PTR_DIFF(end_data, p), 0);
1801 SIVAL(nameptr, 0, len);
1805 SIVAL(p,0,0); /* Ensure any padding is null. */
1807 len = PTR_DIFF(p, pdata);
1808 len = (len + 3) & ~3;
1809 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1811 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1820 if (PTR_DIFF(p,pdata) > space_remaining) {
1821 /* Move the dirptr back to prev_dirpos */
1822 dptr_SeekDir(conn->dirptr, prev_dirpos);
1823 *out_of_space = True;
1824 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1825 return False; /* Not finished - just out of space */
1828 /* Setup the last entry pointer, as an offset from base_data */
1829 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1830 /* Advance the data pointer to the next slot */
1836 /****************************************************************************
1837 Reply to a TRANS2_FINDFIRST.
1838 ****************************************************************************/
1840 static void call_trans2findfirst(connection_struct *conn,
1841 struct smb_request *req,
1842 char **pparams, int total_params,
1843 char **ppdata, int total_data,
1844 unsigned int max_data_bytes)
1846 /* We must be careful here that we don't return more than the
1847 allowed number of data bytes. If this means returning fewer than
1848 maxentries then so be it. We assume that the redirector has
1849 enough room for the fixed number of parameter bytes it has
1851 char *params = *pparams;
1852 char *pdata = *ppdata;
1856 uint16 findfirst_flags;
1857 bool close_after_first;
1859 bool requires_resume_key;
1861 char *directory = NULL;
1862 const char *mask = NULL;
1864 int last_entry_off=0;
1868 bool finished = False;
1869 bool dont_descend = False;
1870 bool out_of_space = False;
1871 int space_remaining;
1872 bool mask_contains_wcard = False;
1873 SMB_STRUCT_STAT sbuf;
1874 struct ea_list *ea_list = NULL;
1875 NTSTATUS ntstatus = NT_STATUS_OK;
1876 TALLOC_CTX *ctx = talloc_tos();
1878 if (total_params < 13) {
1879 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1883 dirtype = SVAL(params,0);
1884 maxentries = SVAL(params,2);
1885 findfirst_flags = SVAL(params,4);
1886 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1887 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1888 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1889 info_level = SVAL(params,6);
1891 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1892 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1893 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1894 info_level, max_data_bytes));
1897 /* W2K3 seems to treat zero as 1. */
1901 switch (info_level) {
1902 case SMB_FIND_INFO_STANDARD:
1903 case SMB_FIND_EA_SIZE:
1904 case SMB_FIND_EA_LIST:
1905 case SMB_FIND_FILE_DIRECTORY_INFO:
1906 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1907 case SMB_FIND_FILE_NAMES_INFO:
1908 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1909 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1910 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1912 case SMB_FIND_FILE_UNIX:
1913 case SMB_FIND_FILE_UNIX_INFO2:
1914 if (!lp_unix_extensions()) {
1915 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1920 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1924 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1925 params+12, total_params - 12,
1926 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1927 if (!NT_STATUS_IS_OK(ntstatus)) {
1928 reply_nterror(req, ntstatus);
1932 ntstatus = resolve_dfspath_wcard(ctx, conn,
1933 req->flags2 & FLAGS2_DFS_PATHNAMES,
1936 &mask_contains_wcard);
1937 if (!NT_STATUS_IS_OK(ntstatus)) {
1938 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1939 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1940 ERRSRV, ERRbadpath);
1943 reply_nterror(req, ntstatus);
1947 ntstatus = unix_convert(ctx, conn, directory, True, &directory, NULL, &sbuf);
1948 if (!NT_STATUS_IS_OK(ntstatus)) {
1949 reply_nterror(req, ntstatus);
1953 ntstatus = check_name(conn, directory);
1954 if (!NT_STATUS_IS_OK(ntstatus)) {
1955 reply_nterror(req, ntstatus);
1959 p = strrchr_m(directory,'/');
1961 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1962 if((directory[0] == '.') && (directory[1] == '\0')) {
1964 mask_contains_wcard = True;
1968 directory = talloc_strdup(talloc_tos(), "./");
1970 reply_nterror(req, NT_STATUS_NO_MEMORY);
1978 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1980 if (info_level == SMB_FIND_EA_LIST) {
1983 if (total_data < 4) {
1984 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1988 ea_size = IVAL(pdata,0);
1989 if (ea_size != total_data) {
1990 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1991 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1992 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1996 if (!lp_ea_support(SNUM(conn))) {
1997 reply_doserror(req, ERRDOS, ERReasnotsupported);
2001 /* Pull out the list of names. */
2002 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2004 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2009 *ppdata = (char *)SMB_REALLOC(
2010 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2011 if(*ppdata == NULL ) {
2012 reply_nterror(req, NT_STATUS_NO_MEMORY);
2016 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2018 /* Realloc the params space */
2019 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2020 if (*pparams == NULL) {
2021 reply_nterror(req, NT_STATUS_NO_MEMORY);
2026 /* Save the wildcard match and attribs we are using on this directory -
2027 needed as lanman2 assumes these are being saved between calls */
2029 ntstatus = dptr_create(conn,
2035 mask_contains_wcard,
2039 if (!NT_STATUS_IS_OK(ntstatus)) {
2040 reply_nterror(req, ntstatus);
2044 dptr_num = dptr_dnum(conn->dirptr);
2045 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2047 /* We don't need to check for VOL here as this is returned by
2048 a different TRANS2 call. */
2050 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2051 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2052 dont_descend = True;
2055 space_remaining = max_data_bytes;
2056 out_of_space = False;
2058 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2059 bool got_exact_match = False;
2061 /* this is a heuristic to avoid seeking the dirptr except when
2062 absolutely necessary. It allows for a filename of about 40 chars */
2063 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2064 out_of_space = True;
2067 finished = !get_lanman2_dir_entry(ctx,
2070 mask,dirtype,info_level,
2071 requires_resume_key,dont_descend,
2073 space_remaining, &out_of_space,
2075 &last_entry_off, ea_list);
2078 if (finished && out_of_space)
2081 if (!finished && !out_of_space)
2085 * As an optimisation if we know we aren't looking
2086 * for a wildcard name (ie. the name matches the wildcard exactly)
2087 * then we can finish on any (first) match.
2088 * This speeds up large directory searches. JRA.
2094 /* Ensure space_remaining never goes -ve. */
2095 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2096 space_remaining = 0;
2097 out_of_space = true;
2099 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2103 /* Check if we can close the dirptr */
2104 if(close_after_first || (finished && close_if_end)) {
2105 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2106 dptr_close(&dptr_num);
2110 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2111 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2112 * the protocol level is less than NT1. Tested with smbclient. JRA.
2113 * This should fix the OS/2 client bug #2335.
2116 if(numentries == 0) {
2117 dptr_close(&dptr_num);
2118 if (Protocol < PROTOCOL_NT1) {
2119 reply_doserror(req, ERRDOS, ERRnofiles);
2122 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2123 ERRDOS, ERRbadfile);
2128 /* At this point pdata points to numentries directory entries. */
2130 /* Set up the return parameter block */
2131 SSVAL(params,0,dptr_num);
2132 SSVAL(params,2,numentries);
2133 SSVAL(params,4,finished);
2134 SSVAL(params,6,0); /* Never an EA error */
2135 SSVAL(params,8,last_entry_off);
2137 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2140 if ((! *directory) && dptr_path(dptr_num)) {
2141 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2143 reply_nterror(req, NT_STATUS_NO_MEMORY);
2147 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2148 smb_fn_name(CVAL(req->inbuf,smb_com)),
2149 mask, directory, dirtype, numentries ) );
2152 * Force a name mangle here to ensure that the
2153 * mask as an 8.3 name is top of the mangled cache.
2154 * The reasons for this are subtle. Don't remove
2155 * this code unless you know what you are doing
2156 * (see PR#13758). JRA.
2159 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2160 char mangled_name[13];
2161 name_to_8_3(mask, mangled_name, True, conn->params);
2167 /****************************************************************************
2168 Reply to a TRANS2_FINDNEXT.
2169 ****************************************************************************/
2171 static void call_trans2findnext(connection_struct *conn,
2172 struct smb_request *req,
2173 char **pparams, int total_params,
2174 char **ppdata, int total_data,
2175 unsigned int max_data_bytes)
2177 /* We must be careful here that we don't return more than the
2178 allowed number of data bytes. If this means returning fewer than
2179 maxentries then so be it. We assume that the redirector has
2180 enough room for the fixed number of parameter bytes it has
2182 char *params = *pparams;
2183 char *pdata = *ppdata;
2189 uint16 findnext_flags;
2190 bool close_after_request;
2192 bool requires_resume_key;
2194 bool mask_contains_wcard = False;
2195 char *resume_name = NULL;
2196 const char *mask = NULL;
2197 const char *directory = NULL;
2201 int i, last_entry_off=0;
2202 bool finished = False;
2203 bool dont_descend = False;
2204 bool out_of_space = False;
2205 int space_remaining;
2206 struct ea_list *ea_list = NULL;
2207 NTSTATUS ntstatus = NT_STATUS_OK;
2208 TALLOC_CTX *ctx = talloc_tos();
2210 if (total_params < 13) {
2211 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2215 dptr_num = SVAL(params,0);
2216 maxentries = SVAL(params,2);
2217 info_level = SVAL(params,4);
2218 resume_key = IVAL(params,6);
2219 findnext_flags = SVAL(params,10);
2220 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2221 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2222 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2223 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2225 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2227 total_params - 12, STR_TERMINATE, &ntstatus,
2228 &mask_contains_wcard);
2229 if (!NT_STATUS_IS_OK(ntstatus)) {
2230 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2231 complain (it thinks we're asking for the directory above the shared
2232 path or an invalid name). Catch this as the resume name is only compared, never used in
2233 a file access. JRA. */
2234 srvstr_pull_talloc(ctx, params, req->flags2,
2235 &resume_name, params+12,
2239 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2240 reply_nterror(req, ntstatus);
2245 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2246 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2247 resume_key = %d resume name = %s continue=%d level = %d\n",
2248 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2249 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2252 /* W2K3 seems to treat zero as 1. */
2256 switch (info_level) {
2257 case SMB_FIND_INFO_STANDARD:
2258 case SMB_FIND_EA_SIZE:
2259 case SMB_FIND_EA_LIST:
2260 case SMB_FIND_FILE_DIRECTORY_INFO:
2261 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2262 case SMB_FIND_FILE_NAMES_INFO:
2263 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2264 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2265 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2267 case SMB_FIND_FILE_UNIX:
2268 case SMB_FIND_FILE_UNIX_INFO2:
2269 if (!lp_unix_extensions()) {
2270 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2275 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2279 if (info_level == SMB_FIND_EA_LIST) {
2282 if (total_data < 4) {
2283 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2287 ea_size = IVAL(pdata,0);
2288 if (ea_size != total_data) {
2289 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2290 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2291 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2295 if (!lp_ea_support(SNUM(conn))) {
2296 reply_doserror(req, ERRDOS, ERReasnotsupported);
2300 /* Pull out the list of names. */
2301 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2303 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2308 *ppdata = (char *)SMB_REALLOC(
2309 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2310 if(*ppdata == NULL) {
2311 reply_nterror(req, NT_STATUS_NO_MEMORY);
2316 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2318 /* Realloc the params space */
2319 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2320 if(*pparams == NULL ) {
2321 reply_nterror(req, NT_STATUS_NO_MEMORY);
2327 /* Check that the dptr is valid */
2328 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2329 reply_doserror(req, ERRDOS, ERRnofiles);
2333 string_set(&conn->dirpath,dptr_path(dptr_num));
2335 /* Get the wildcard mask from the dptr */
2336 if((p = dptr_wcard(dptr_num))== NULL) {
2337 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2338 reply_doserror(req, ERRDOS, ERRnofiles);
2343 directory = conn->dirpath;
2345 /* Get the attr mask from the dptr */
2346 dirtype = dptr_attr(dptr_num);
2348 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2349 dptr_num, mask, dirtype,
2351 dptr_TellDir(conn->dirptr)));
2353 /* We don't need to check for VOL here as this is returned by
2354 a different TRANS2 call. */
2356 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2357 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2358 dont_descend = True;
2361 space_remaining = max_data_bytes;
2362 out_of_space = False;
2365 * Seek to the correct position. We no longer use the resume key but
2366 * depend on the last file name instead.
2369 if(*resume_name && !continue_bit) {
2372 long current_pos = 0;
2374 * Remember, name_to_8_3 is called by
2375 * get_lanman2_dir_entry(), so the resume name
2376 * could be mangled. Ensure we check the unmangled name.
2379 if (mangle_is_mangled(resume_name, conn->params)) {
2380 char *new_resume_name = NULL;
2381 mangle_lookup_name_from_8_3(ctx,
2385 if (new_resume_name) {
2386 resume_name = new_resume_name;
2391 * Fix for NT redirector problem triggered by resume key indexes
2392 * changing between directory scans. We now return a resume key of 0
2393 * and instead look for the filename to continue from (also given
2394 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2395 * findfirst/findnext (as is usual) then the directory pointer
2396 * should already be at the correct place.
2399 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2400 } /* end if resume_name && !continue_bit */
2402 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2403 bool got_exact_match = False;
2405 /* this is a heuristic to avoid seeking the dirptr except when
2406 absolutely necessary. It allows for a filename of about 40 chars */
2407 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2408 out_of_space = True;
2411 finished = !get_lanman2_dir_entry(ctx,
2414 mask,dirtype,info_level,
2415 requires_resume_key,dont_descend,
2417 space_remaining, &out_of_space,
2419 &last_entry_off, ea_list);
2422 if (finished && out_of_space)
2425 if (!finished && !out_of_space)
2429 * As an optimisation if we know we aren't looking
2430 * for a wildcard name (ie. the name matches the wildcard exactly)
2431 * then we can finish on any (first) match.
2432 * This speeds up large directory searches. JRA.
2438 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2441 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2442 smb_fn_name(CVAL(req->inbuf,smb_com)),
2443 mask, directory, dirtype, numentries ) );
2445 /* Check if we can close the dirptr */
2446 if(close_after_request || (finished && close_if_end)) {
2447 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2448 dptr_close(&dptr_num); /* This frees up the saved mask */
2451 /* Set up the return parameter block */
2452 SSVAL(params,0,numentries);
2453 SSVAL(params,2,finished);
2454 SSVAL(params,4,0); /* Never an EA error */
2455 SSVAL(params,6,last_entry_off);
2457 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2463 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2465 E_md4hash(lp_servicename(SNUM(conn)),objid);
2469 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2471 SMB_ASSERT(extended_info != NULL);
2473 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2474 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2475 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2476 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2477 #ifdef SAMBA_VERSION_REVISION
2478 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2480 extended_info->samba_subversion = 0;
2481 #ifdef SAMBA_VERSION_RC_RELEASE
2482 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2484 #ifdef SAMBA_VERSION_PRE_RELEASE
2485 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2488 #ifdef SAMBA_VERSION_VENDOR_PATCH
2489 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2491 extended_info->samba_gitcommitdate = 0;
2492 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2493 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2496 memset(extended_info->samba_version_string, 0,
2497 sizeof(extended_info->samba_version_string));
2499 snprintf (extended_info->samba_version_string,
2500 sizeof(extended_info->samba_version_string),
2501 "%s", samba_version_string());
2504 /****************************************************************************
2505 Reply to a TRANS2_QFSINFO (query filesystem info).
2506 ****************************************************************************/
2508 static void call_trans2qfsinfo(connection_struct *conn,
2509 struct smb_request *req,
2510 char **pparams, int total_params,
2511 char **ppdata, int total_data,
2512 unsigned int max_data_bytes)
2514 char *pdata, *end_data;
2515 char *params = *pparams;
2519 const char *vname = volume_label(SNUM(conn));
2520 int snum = SNUM(conn);
2521 char *fstype = lp_fstype(SNUM(conn));
2522 uint32 additional_flags = 0;
2524 if (total_params < 2) {
2525 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2529 info_level = SVAL(params,0);
2532 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2533 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2534 "info level (0x%x) on IPC$.\n",
2535 (unsigned int)info_level));
2536 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2541 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2542 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2543 DEBUG(0,("call_trans2qfsinfo: encryption required "
2544 "and info level 0x%x sent.\n",
2545 (unsigned int)info_level));
2546 exit_server_cleanly("encryption required "
2552 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2554 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2555 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2556 reply_doserror(req, ERRSRV, ERRinvdevice);
2560 *ppdata = (char *)SMB_REALLOC(
2561 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2562 if (*ppdata == NULL ) {
2563 reply_nterror(req, NT_STATUS_NO_MEMORY);
2568 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2569 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2571 switch (info_level) {
2572 case SMB_INFO_ALLOCATION:
2574 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2576 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2577 reply_unixerror(req, ERRHRD, ERRgeneral);
2581 block_size = lp_block_size(snum);
2582 if (bsize < block_size) {
2583 SMB_BIG_UINT factor = block_size/bsize;
2588 if (bsize > block_size) {
2589 SMB_BIG_UINT factor = bsize/block_size;
2594 bytes_per_sector = 512;
2595 sectors_per_unit = bsize/bytes_per_sector;
2597 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2598 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2599 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2601 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2602 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2603 SIVAL(pdata,l1_cUnit,dsize);
2604 SIVAL(pdata,l1_cUnitAvail,dfree);
2605 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2609 case SMB_INFO_VOLUME:
2610 /* Return volume name */
2612 * Add volume serial number - hash of a combination of
2613 * the called hostname and the service name.
2615 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2617 * Win2k3 and previous mess this up by sending a name length
2618 * one byte short. I believe only older clients (OS/2 Win9x) use
2619 * this call so try fixing this by adding a terminating null to
2620 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2624 pdata+l2_vol_szVolLabel, vname,
2625 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2626 STR_NOALIGN|STR_TERMINATE);
2627 SCVAL(pdata,l2_vol_cch,len);
2628 data_len = l2_vol_szVolLabel + len;
2629 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2630 (unsigned)st.st_ctime, len, vname));
2633 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2634 case SMB_FS_ATTRIBUTE_INFORMATION:
2636 additional_flags = 0;
2637 #if defined(HAVE_SYS_QUOTAS)
2638 additional_flags |= FILE_VOLUME_QUOTAS;
2641 if(lp_nt_acl_support(SNUM(conn))) {
2642 additional_flags |= FILE_PERSISTENT_ACLS;
2645 /* Capabilities are filled in at connection time through STATVFS call */
2646 additional_flags |= conn->fs_capabilities;
2648 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2649 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2650 additional_flags); /* FS ATTRIBUTES */
2652 SIVAL(pdata,4,255); /* Max filename component length */
2653 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2654 and will think we can't do long filenames */
2655 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2656 PTR_DIFF(end_data, pdata+12),
2659 data_len = 12 + len;
2662 case SMB_QUERY_FS_LABEL_INFO:
2663 case SMB_FS_LABEL_INFORMATION:
2664 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2665 PTR_DIFF(end_data, pdata+4), 0);
2670 case SMB_QUERY_FS_VOLUME_INFO:
2671 case SMB_FS_VOLUME_INFORMATION:
2674 * Add volume serial number - hash of a combination of
2675 * the called hostname and the service name.
2677 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2678 (str_checksum(get_local_machine_name())<<16));
2680 /* Max label len is 32 characters. */
2681 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2682 PTR_DIFF(end_data, pdata+18),
2684 SIVAL(pdata,12,len);
2687 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2688 (int)strlen(vname),vname, lp_servicename(snum)));
2691 case SMB_QUERY_FS_SIZE_INFO:
2692 case SMB_FS_SIZE_INFORMATION:
2694 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2696 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2697 reply_unixerror(req, ERRHRD, ERRgeneral);
2700 block_size = lp_block_size(snum);
2701 if (bsize < block_size) {
2702 SMB_BIG_UINT factor = block_size/bsize;
2707 if (bsize > block_size) {
2708 SMB_BIG_UINT factor = bsize/block_size;
2713 bytes_per_sector = 512;
2714 sectors_per_unit = bsize/bytes_per_sector;
2715 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2716 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2717 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2718 SBIG_UINT(pdata,0,dsize);
2719 SBIG_UINT(pdata,8,dfree);
2720 SIVAL(pdata,16,sectors_per_unit);
2721 SIVAL(pdata,20,bytes_per_sector);
2725 case SMB_FS_FULL_SIZE_INFORMATION:
2727 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2729 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2730 reply_unixerror(req, ERRHRD, ERRgeneral);
2733 block_size = lp_block_size(snum);
2734 if (bsize < block_size) {
2735 SMB_BIG_UINT factor = block_size/bsize;
2740 if (bsize > block_size) {
2741 SMB_BIG_UINT factor = bsize/block_size;
2746 bytes_per_sector = 512;
2747 sectors_per_unit = bsize/bytes_per_sector;
2748 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2749 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2750 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2751 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2752 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2753 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2754 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2755 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2759 case SMB_QUERY_FS_DEVICE_INFO:
2760 case SMB_FS_DEVICE_INFORMATION:
2762 SIVAL(pdata,0,0); /* dev type */
2763 SIVAL(pdata,4,0); /* characteristics */
2766 #ifdef HAVE_SYS_QUOTAS
2767 case SMB_FS_QUOTA_INFORMATION:
2769 * what we have to send --metze:
2771 * Unknown1: 24 NULL bytes
2772 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2773 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2774 * Quota Flags: 2 byte :
2775 * Unknown3: 6 NULL bytes
2779 * details for Quota Flags:
2781 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2782 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2783 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2784 * 0x0001 Enable Quotas: enable quota for this fs
2788 /* we need to fake up a fsp here,
2789 * because its not send in this call
2792 SMB_NTQUOTA_STRUCT quotas;
2795 ZERO_STRUCT(quotas);
2801 if (current_user.ut.uid != 0) {
2802 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2803 lp_servicename(SNUM(conn)),conn->user));
2804 reply_doserror(req, ERRDOS, ERRnoaccess);
2808 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2809 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2810 reply_doserror(req, ERRSRV, ERRerror);
2816 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2818 /* Unknown1 24 NULL bytes*/
2819 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2820 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2821 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2823 /* Default Soft Quota 8 bytes */
2824 SBIG_UINT(pdata,24,quotas.softlim);
2826 /* Default Hard Quota 8 bytes */
2827 SBIG_UINT(pdata,32,quotas.hardlim);
2829 /* Quota flag 2 bytes */
2830 SSVAL(pdata,40,quotas.qflags);
2832 /* Unknown3 6 NULL bytes */
2838 #endif /* HAVE_SYS_QUOTAS */
2839 case SMB_FS_OBJECTID_INFORMATION:
2841 unsigned char objid[16];
2842 struct smb_extended_info extended_info;
2843 memcpy(pdata,create_volume_objectid(conn, objid),16);
2844 samba_extended_info_version (&extended_info);
2845 SIVAL(pdata,16,extended_info.samba_magic);
2846 SIVAL(pdata,20,extended_info.samba_version);
2847 SIVAL(pdata,24,extended_info.samba_subversion);
2848 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2849 memcpy(pdata+36,extended_info.samba_version_string,28);
2855 * Query the version and capabilities of the CIFS UNIX extensions
2859 case SMB_QUERY_CIFS_UNIX_INFO:
2861 bool large_write = lp_min_receive_file_size() &&
2862 !srv_is_signing_active();
2863 bool large_read = !srv_is_signing_active();
2864 int encrypt_caps = 0;
2866 if (!lp_unix_extensions()) {
2867 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2871 switch (conn->encrypt_level) {
2877 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2880 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2881 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2882 large_write = false;
2888 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2889 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2891 /* We have POSIX ACLs, pathname, encryption,
2892 * large read/write, and locking capability. */
2894 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2895 CIFS_UNIX_POSIX_ACLS_CAP|
2896 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2897 CIFS_UNIX_FCNTL_LOCKS_CAP|
2898 CIFS_UNIX_EXTATTR_CAP|
2899 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2901 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2903 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2907 case SMB_QUERY_POSIX_FS_INFO:
2910 vfs_statvfs_struct svfs;
2912 if (!lp_unix_extensions()) {
2913 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2917 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2921 SIVAL(pdata,0,svfs.OptimalTransferSize);
2922 SIVAL(pdata,4,svfs.BlockSize);
2923 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2924 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2925 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2926 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2927 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2928 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2929 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2931 } else if (rc == EOPNOTSUPP) {
2932 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2934 #endif /* EOPNOTSUPP */
2936 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2937 reply_doserror(req, ERRSRV, ERRerror);
2943 case SMB_QUERY_POSIX_WHOAMI:
2949 if (!lp_unix_extensions()) {
2950 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2954 if (max_data_bytes < 40) {
2955 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2959 /* We ARE guest if global_sid_Builtin_Guests is
2960 * in our list of SIDs.
2962 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2963 current_user.nt_user_token)) {
2964 flags |= SMB_WHOAMI_GUEST;
2967 /* We are NOT guest if global_sid_Authenticated_Users
2968 * is in our list of SIDs.
2970 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2971 current_user.nt_user_token)) {
2972 flags &= ~SMB_WHOAMI_GUEST;
2975 /* NOTE: 8 bytes for UID/GID, irrespective of native
2976 * platform size. This matches
2977 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2979 data_len = 4 /* flags */
2986 + 4 /* pad/reserved */
2987 + (current_user.ut.ngroups * 8)
2989 + (current_user.nt_user_token->num_sids *
2993 SIVAL(pdata, 0, flags);
2994 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2995 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2996 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2999 if (data_len >= max_data_bytes) {
3000 /* Potential overflow, skip the GIDs and SIDs. */
3002 SIVAL(pdata, 24, 0); /* num_groups */
3003 SIVAL(pdata, 28, 0); /* num_sids */
3004 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3005 SIVAL(pdata, 36, 0); /* reserved */
3011 SIVAL(pdata, 24, current_user.ut.ngroups);
3013 current_user.nt_user_token->num_sids);
3015 /* We walk the SID list twice, but this call is fairly
3016 * infrequent, and I don't expect that it's performance
3017 * sensitive -- jpeach
3019 for (i = 0, sid_bytes = 0;
3020 i < current_user.nt_user_token->num_sids; ++i) {
3021 sid_bytes += ndr_size_dom_sid(
3022 ¤t_user.nt_user_token->user_sids[i], 0);
3025 /* SID list byte count */
3026 SIVAL(pdata, 32, sid_bytes);
3028 /* 4 bytes pad/reserved - must be zero */
3029 SIVAL(pdata, 36, 0);
3033 for (i = 0; i < current_user.ut.ngroups; ++i) {
3034 SBIG_UINT(pdata, data_len,
3035 (SMB_BIG_UINT)current_user.ut.groups[i]);
3041 i < current_user.nt_user_token->num_sids; ++i) {
3042 int sid_len = ndr_size_dom_sid(
3043 ¤t_user.nt_user_token->user_sids[i], 0);
3045 sid_linearize(pdata + data_len, sid_len,
3046 ¤t_user.nt_user_token->user_sids[i]);
3047 data_len += sid_len;
3053 case SMB_MAC_QUERY_FS_INFO:
3055 * Thursby MAC extension... ONLY on NTFS filesystems
3056 * once we do streams then we don't need this
3058 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3060 SIVAL(pdata,84,0x100); /* Don't support mac... */
3065 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3070 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3073 DEBUG( 4, ( "%s info_level = %d\n",
3074 smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) );
3079 /****************************************************************************
3080 Reply to a TRANS2_SETFSINFO (set filesystem info).
3081 ****************************************************************************/
3083 static void call_trans2setfsinfo(connection_struct *conn,
3084 struct smb_request *req,
3085 char **pparams, int total_params,
3086 char **ppdata, int total_data,
3087 unsigned int max_data_bytes)
3089 char *pdata = *ppdata;
3090 char *params = *pparams;
3093 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3096 if (total_params < 4) {
3097 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3099 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3103 info_level = SVAL(params,2);
3106 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3107 info_level != SMB_SET_CIFS_UNIX_INFO) {
3108 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3109 "info level (0x%x) on IPC$.\n",
3110 (unsigned int)info_level));
3111 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3116 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3117 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3118 DEBUG(0,("call_trans2setfsinfo: encryption required "
3119 "and info level 0x%x sent.\n",
3120 (unsigned int)info_level));
3121 exit_server_cleanly("encryption required "
3127 switch(info_level) {
3128 case SMB_SET_CIFS_UNIX_INFO:
3130 uint16 client_unix_major;
3131 uint16 client_unix_minor;
3132 uint32 client_unix_cap_low;
3133 uint32 client_unix_cap_high;
3135 if (!lp_unix_extensions()) {
3137 NT_STATUS_INVALID_LEVEL);
3141 /* There should be 12 bytes of capabilities set. */
3142 if (total_data < 8) {
3145 NT_STATUS_INVALID_PARAMETER);
3148 client_unix_major = SVAL(pdata,0);
3149 client_unix_minor = SVAL(pdata,2);
3150 client_unix_cap_low = IVAL(pdata,4);
3151 client_unix_cap_high = IVAL(pdata,8);
3152 /* Just print these values for now. */
3153 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3154 cap_low = 0x%x, cap_high = 0x%x\n",
3155 (unsigned int)client_unix_major,
3156 (unsigned int)client_unix_minor,
3157 (unsigned int)client_unix_cap_low,
3158 (unsigned int)client_unix_cap_high ));
3160 /* Here is where we must switch to posix pathname processing... */
3161 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3162 lp_set_posix_pathnames();
3163 mangle_change_to_posix();
3166 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3167 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3168 /* Client that knows how to do posix locks,
3169 * but not posix open/mkdir operations. Set a
3170 * default type for read/write checks. */
3172 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3178 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3181 size_t param_len = 0;
3182 size_t data_len = total_data;
3184 if (!lp_unix_extensions()) {
3187 NT_STATUS_INVALID_LEVEL);
3191 if (lp_smb_encrypt(SNUM(conn)) == false) {
3194 NT_STATUS_NOT_SUPPORTED);
3198 DEBUG( 4,("call_trans2setfsinfo: "
3199 "request transport encryption.\n"));
3201 status = srv_request_encryption_setup(conn,
3202 (unsigned char **)ppdata,
3204 (unsigned char **)pparams,
3207 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3208 !NT_STATUS_IS_OK(status)) {
3209 reply_nterror(req, status);
3213 send_trans2_replies(conn, req,
3220 if (NT_STATUS_IS_OK(status)) {
3221 /* Server-side transport
3222 * encryption is now *on*. */
3223 status = srv_encryption_start(conn);
3224 if (!NT_STATUS_IS_OK(status)) {
3225 exit_server_cleanly(
3226 "Failure in setting "
3227 "up encrypted transport");
3233 case SMB_FS_QUOTA_INFORMATION:
3235 files_struct *fsp = NULL;
3236 SMB_NTQUOTA_STRUCT quotas;
3238 ZERO_STRUCT(quotas);
3241 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
3242 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3243 lp_servicename(SNUM(conn)),conn->user));
3244 reply_doserror(req, ERRSRV, ERRaccess);
3248 /* note: normaly there're 48 bytes,
3249 * but we didn't use the last 6 bytes for now
3252 fsp = file_fsp(SVAL(params,0));
3253 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
3254 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3256 req, NT_STATUS_INVALID_HANDLE);
3260 if (total_data < 42) {
3261 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3265 NT_STATUS_INVALID_PARAMETER);
3269 /* unknown_1 24 NULL bytes in pdata*/
3271 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3272 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
3273 #ifdef LARGE_SMB_OFF_T
3274 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
3275 #else /* LARGE_SMB_OFF_T */
3276 if ((IVAL(pdata,28) != 0)&&
3277 ((quotas.softlim != 0xFFFFFFFF)||
3278 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3279 /* more than 32 bits? */
3282 NT_STATUS_INVALID_PARAMETER);
3285 #endif /* LARGE_SMB_OFF_T */
3287 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3288 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
3289 #ifdef LARGE_SMB_OFF_T
3290 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
3291 #else /* LARGE_SMB_OFF_T */
3292 if ((IVAL(pdata,36) != 0)&&
3293 ((quotas.hardlim != 0xFFFFFFFF)||
3294 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3295 /* more than 32 bits? */
3298 NT_STATUS_INVALID_PARAMETER);
3301 #endif /* LARGE_SMB_OFF_T */
3303 /* quota_flags 2 bytes **/
3304 quotas.qflags = SVAL(pdata,40);
3306 /* unknown_2 6 NULL bytes follow*/
3308 /* now set the quotas */
3309 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3310 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3311 reply_doserror(req, ERRSRV, ERRerror);
3318 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3320 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3326 * sending this reply works fine,
3327 * but I'm not sure it's the same
3328 * like windows do...
3331 reply_outbuf(req, 10, 0);
3334 #if defined(HAVE_POSIX_ACLS)
3335 /****************************************************************************
3336 Utility function to count the number of entries in a POSIX acl.
3337 ****************************************************************************/
3339 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3341 unsigned int ace_count = 0;
3342 int entry_id = SMB_ACL_FIRST_ENTRY;
3343 SMB_ACL_ENTRY_T entry;
3345 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3347 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3348 entry_id = SMB_ACL_NEXT_ENTRY;
3355 /****************************************************************************
3356 Utility function to marshall a POSIX acl into wire format.
3357 ****************************************************************************/
3359 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3361 int entry_id = SMB_ACL_FIRST_ENTRY;
3362 SMB_ACL_ENTRY_T entry;
3364 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3365 SMB_ACL_TAG_T tagtype;
3366 SMB_ACL_PERMSET_T permset;
3367 unsigned char perms = 0;
3368 unsigned int own_grp;
3371 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3372 entry_id = SMB_ACL_NEXT_ENTRY;
3375 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3376 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3380 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3381 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3385 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3386 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3387 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3389 SCVAL(pdata,1,perms);
3392 case SMB_ACL_USER_OBJ:
3393 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3394 own_grp = (unsigned int)pst->st_uid;
3395 SIVAL(pdata,2,own_grp);
3400 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3402 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3405 own_grp = (unsigned int)*puid;
3406 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3407 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3408 SIVAL(pdata,2,own_grp);
3412 case SMB_ACL_GROUP_OBJ:
3413 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3414 own_grp = (unsigned int)pst->st_gid;
3415 SIVAL(pdata,2,own_grp);
3420 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3422 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3425 own_grp = (unsigned int)*pgid;
3426 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3427 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3428 SIVAL(pdata,2,own_grp);
3433 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3434 SIVAL(pdata,2,0xFFFFFFFF);
3435 SIVAL(pdata,6,0xFFFFFFFF);
3438 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3439 SIVAL(pdata,2,0xFFFFFFFF);
3440 SIVAL(pdata,6,0xFFFFFFFF);
3443 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3446 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3453 /****************************************************************************
3454 Store the FILE_UNIX_BASIC info.
3455 ****************************************************************************/
3457 static char *store_file_unix_basic(connection_struct *conn,
3460 const SMB_STRUCT_STAT *psbuf)
3462 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3463 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3465 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3468 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3471 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3472 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3473 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3476 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3480 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3484 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3487 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3491 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3495 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3498 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3502 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3509 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3510 * the chflags(2) (or equivalent) flags.
3512 * XXX: this really should be behind the VFS interface. To do this, we would
3513 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3514 * Each VFS module could then implement its own mapping as appropriate for the
3515 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3517 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3521 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3525 { UF_IMMUTABLE, EXT_IMMUTABLE },
3529 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3533 { UF_HIDDEN, EXT_HIDDEN },
3536 /* Do not remove. We need to guarantee that this array has at least one
3537 * entry to build on HP-UX.
3543 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3544 uint32 *smb_fflags, uint32 *smb_fmask)
3546 #ifdef HAVE_STAT_ST_FLAGS
3549 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3550 *smb_fmask |= info2_flags_map[i].smb_fflag;
3551 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3552 *smb_fflags |= info2_flags_map[i].smb_fflag;
3555 #endif /* HAVE_STAT_ST_FLAGS */
3558 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3559 const uint32 smb_fflags,
3560 const uint32 smb_fmask,
3563 #ifdef HAVE_STAT_ST_FLAGS
3564 uint32 max_fmask = 0;
3567 *stat_fflags = psbuf->st_flags;
3569 /* For each flags requested in smb_fmask, check the state of the
3570 * corresponding flag in smb_fflags and set or clear the matching
3574 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3575 max_fmask |= info2_flags_map[i].smb_fflag;
3576 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3577 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3578 *stat_fflags |= info2_flags_map[i].stat_fflag;
3580 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3585 /* If smb_fmask is asking to set any bits that are not supported by
3586 * our flag mappings, we should fail.
3588 if ((smb_fmask & max_fmask) != smb_fmask) {
3595 #endif /* HAVE_STAT_ST_FLAGS */
3599 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3600 * of file flags and birth (create) time.
3602 static char *store_file_unix_basic_info2(connection_struct *conn,
3605 const SMB_STRUCT_STAT *psbuf)
3607 uint32 file_flags = 0;
3608 uint32 flags_mask = 0;
3610 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3612 /* Create (birth) time 64 bit */
3613 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3616 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3617 SIVAL(pdata, 0, file_flags); /* flags */
3618 SIVAL(pdata, 4, flags_mask); /* mask */
3624 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3625 const struct stream_struct *streams,
3627 unsigned int max_data_bytes,
3628 unsigned int *data_size)
3631 unsigned int ofs = 0;
3633 for (i=0; i<num_streams; i++) {
3634 unsigned int next_offset;
3636 smb_ucs2_t *namebuf;
3638 namelen = push_ucs2_talloc(talloc_tos(), &namebuf,
3641 if ((namelen == (size_t)-1) || (namelen <= 2)) {
3642 return NT_STATUS_INVALID_PARAMETER;
3646 * name_buf is now null-terminated, we need to marshall as not
3652 if (ofs + 24 + namelen > max_data_bytes) {
3653 TALLOC_FREE(namebuf);
3654 return NT_STATUS_BUFFER_TOO_SMALL;
3657 SIVAL(data, ofs+4, namelen);
3658 SOFF_T(data, ofs+8, streams[i].size);
3659 SOFF_T(data, ofs+16, streams[i].alloc_size);
3660 memcpy(data+ofs+24, namebuf, namelen);
3661 TALLOC_FREE(namebuf);
3663 next_offset = ofs + 24 + namelen;
3665 if (i == num_streams-1) {
3666 SIVAL(data, ofs, 0);
3669 unsigned int align = ndr_align_size(next_offset, 8);
3671 if (next_offset + align > max_data_bytes) {
3672 return NT_STATUS_BUFFER_TOO_SMALL;
3675 memset(data+next_offset, 0, align);
3676 next_offset += align;
3678 SIVAL(data, ofs, next_offset - ofs);
3687 return NT_STATUS_OK;
3690 /****************************************************************************
3691 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3692 ****************************************************************************/
3694 static void call_trans2qpipeinfo(connection_struct *conn,
3695 struct smb_request *req,
3696 unsigned int tran_call,
3697 char **pparams, int total_params,
3698 char **ppdata, int total_data,
3699 unsigned int max_data_bytes)
3701 char *params = *pparams;
3702 char *pdata = *ppdata;
3703 unsigned int data_size = 0;
3704 unsigned int param_size = 2;
3706 smb_np_struct *p_pipe = NULL;
3709 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3713 if (total_params < 4) {
3714 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3718 p_pipe = get_rpc_pipe_p(SVAL(params,0));
3719 if (p_pipe == NULL) {
3720 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3724 info_level = SVAL(params,2);
3726 *pparams = (char *)SMB_REALLOC(*pparams,2);
3727 if (*pparams == NULL) {
3728 reply_nterror(req, NT_STATUS_NO_MEMORY);
3733 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3734 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3735 if (*ppdata == NULL ) {
3736 reply_nterror(req, NT_STATUS_NO_MEMORY);
3741 switch (info_level) {
3742 case SMB_FILE_STANDARD_INFORMATION:
3744 SOFF_T(pdata,0,4096LL);
3751 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3755 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3761 /****************************************************************************
3762 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3763 file name or file id).
3764 ****************************************************************************/
3766 static void call_trans2qfilepathinfo(connection_struct *conn,
3767 struct smb_request *req,
3768 unsigned int tran_call,
3769 char **pparams, int total_params,
3770 char **ppdata, int total_data,
3771 unsigned int max_data_bytes)
3773 char *params = *pparams;
3774 char *pdata = *ppdata;
3775 char *dstart, *dend;
3779 SMB_OFF_T file_size=0;
3780 SMB_BIG_UINT allocation_size=0;
3781 unsigned int data_size = 0;
3782 unsigned int param_size = 2;
3783 SMB_STRUCT_STAT sbuf;
3784 char *dos_fname = NULL;
3790 bool delete_pending = False;
3792 time_t create_time, mtime, atime;
3793 struct timespec create_time_ts, mtime_ts, atime_ts;
3794 struct timespec write_time_ts;
3795 files_struct *fsp = NULL;
3796 struct file_id fileid;
3797 struct ea_list *ea_list = NULL;
3798 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3799 char *lock_data = NULL;
3800 TALLOC_CTX *ctx = talloc_tos();
3803 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3808 ZERO_STRUCT(write_time_ts);
3810 if (tran_call == TRANSACT2_QFILEINFO) {
3811 if (total_params < 4) {
3812 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3817 call_trans2qpipeinfo(conn, req, tran_call,
3818 pparams, total_params,
3824 fsp = file_fsp(SVAL(params,0));
3825 info_level = SVAL(params,2);
3827 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3829 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3830 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3834 /* Initial check for valid fsp ptr. */
3835 if (!check_fsp_open(conn, req, fsp, ¤t_user)) {
3839 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3841 reply_nterror(req, NT_STATUS_NO_MEMORY);
3845 if(fsp->fake_file_handle) {
3847 * This is actually for the QUOTA_FAKE_FILE --metze
3850 /* We know this name is ok, it's already passed the checks. */
3852 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3854 * This is actually a QFILEINFO on a directory
3855 * handle (returned from an NT SMB). NT5.0 seems
3856 * to do this call. JRA.
3859 if (INFO_LEVEL_IS_UNIX(info_level)) {
3860 /* Always do lstat for UNIX calls. */
3861 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3862 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3863 reply_unixerror(req,ERRDOS,ERRbadpath);
3866 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3867 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3868 reply_unixerror(req, ERRDOS, ERRbadpath);
3872 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3873 delete_pending = get_delete_on_close_flag(fileid);
3874 write_time_ts = get_write_time(fileid);
3877 * Original code - this is an open file.
3879 if (!check_fsp(conn, req, fsp, ¤t_user)) {
3883 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3884 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3885 reply_unixerror(req, ERRDOS, ERRbadfid);
3888 pos = fsp->fh->position_information;
3889 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3890 delete_pending = get_delete_on_close_flag(fileid);
3891 write_time_ts = get_write_time(fileid);
3892 access_mask = fsp->access_mask;
3896 NTSTATUS status = NT_STATUS_OK;
3899 if (total_params < 7) {
3900 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3904 info_level = SVAL(params,0);
3906 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3908 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3909 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3913 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
3915 STR_TERMINATE, &status);
3916 if (!NT_STATUS_IS_OK(status)) {
3917 reply_nterror(req, status);
3921 status = resolve_dfspath(ctx,
3923 req->flags2 & FLAGS2_DFS_PATHNAMES,
3926 if (!NT_STATUS_IS_OK(status)) {
3927 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3928 reply_botherror(req,
3929 NT_STATUS_PATH_NOT_COVERED,
3930 ERRSRV, ERRbadpath);
3932 reply_nterror(req, status);
3936 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3937 if (!NT_STATUS_IS_OK(status)) {
3938 reply_nterror(req, status);
3941 status = check_name(conn, fname);
3942 if (!NT_STATUS_IS_OK(status)) {
3943 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3944 reply_nterror(req, status);
3948 if (INFO_LEVEL_IS_UNIX(info_level)) {
3949 /* Always do lstat for UNIX calls. */
3950 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3951 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3952 reply_unixerror(req, ERRDOS, ERRbadpath);
3955 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3956 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3957 reply_unixerror(req, ERRDOS, ERRbadpath);
3961 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3962 delete_pending = get_delete_on_close_flag(fileid);
3963 if (delete_pending) {
3964 reply_nterror(req, NT_STATUS_DELETE_PENDING);
3967 write_time_ts = get_write_time(fileid);
3970 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3971 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3975 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3976 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3978 p = strrchr_m(fname,'/');
3984 mode = dos_mode(conn,fname,&sbuf);
3986 mode = FILE_ATTRIBUTE_NORMAL;
3988 nlink = sbuf.st_nlink;
3990 if (nlink && (mode&aDIR)) {
3994 if ((nlink > 0) && delete_pending) {
3998 fullpathname = fname;
4000 file_size = get_file_size(sbuf);
4002 /* Pull out any data sent here before we realloc. */
4003 switch (info_level) {
4004 case SMB_INFO_QUERY_EAS_FROM_LIST:
4006 /* Pull any EA list from the data portion. */
4009 if (total_data < 4) {
4011 req, NT_STATUS_INVALID_PARAMETER);
4014 ea_size = IVAL(pdata,0);
4016 if (total_data > 0 && ea_size != total_data) {
4017 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4018 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4020 req, NT_STATUS_INVALID_PARAMETER);
4024 if (!lp_ea_support(SNUM(conn))) {
4025 reply_doserror(req, ERRDOS,
4026 ERReasnotsupported);
4030 /* Pull out the list of names. */
4031 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4034 req, NT_STATUS_INVALID_PARAMETER);
4040 case SMB_QUERY_POSIX_LOCK:
4042 if (fsp == NULL || fsp->fh->fd == -1) {
4043 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4047 if (total_data != POSIX_LOCK_DATA_SIZE) {
4049 req, NT_STATUS_INVALID_PARAMETER);
4053 /* Copy the lock range data. */
4054 lock_data = (char *)TALLOC_MEMDUP(
4055 ctx, pdata, total_data);
4057 reply_nterror(req, NT_STATUS_NO_MEMORY);
4065 *pparams = (char *)SMB_REALLOC(*pparams,2);
4066 if (*pparams == NULL) {
4067 reply_nterror(req, NT_STATUS_NO_MEMORY);
4072 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4073 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4074 if (*ppdata == NULL ) {
4075 reply_nterror(req, NT_STATUS_NO_MEMORY);
4080 dend = dstart + data_size - 1;
4082 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
4083 mtime_ts = get_mtimespec(&sbuf);
4084 atime_ts = get_atimespec(&sbuf);
4086 allocation_size = get_allocation_size(conn,fsp,&sbuf);
4089 /* Do we have this path open ? */
4091 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4092 fsp1 = file_find_di_first(fileid);
4093 if (fsp1 && fsp1->initial_allocation_size) {
4094 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
4098 if (!null_timespec(write_time_ts)) {
4099 mtime_ts = write_time_ts;
4102 if (lp_dos_filetime_resolution(SNUM(conn))) {
4103 dos_filetime_timespec(&create_time_ts);
4104 dos_filetime_timespec(&mtime_ts);
4105 dos_filetime_timespec(&atime_ts);
4108 create_time = convert_timespec_to_time_t(create_time_ts);
4109 mtime = convert_timespec_to_time_t(mtime_ts);
4110 atime = convert_timespec_to_time_t(atime_ts);
4112 /* NT expects the name to be in an exact form of the *full*
4113 filename. See the trans2 torture test */
4114 if (ISDOT(base_name)) {
4115 dos_fname = talloc_strdup(ctx, "\\");
4117 reply_nterror(req, NT_STATUS_NO_MEMORY);
4121 dos_fname = talloc_asprintf(ctx,
4125 reply_nterror(req, NT_STATUS_NO_MEMORY);
4128 string_replace(dos_fname, '/', '\\');
4131 switch (info_level) {
4132 case SMB_INFO_STANDARD:
4133 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4135 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4136 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4137 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4138 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4139 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4140 SSVAL(pdata,l1_attrFile,mode);
4143 case SMB_INFO_QUERY_EA_SIZE:
4145 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4146 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4148 srv_put_dos_date2(pdata,0,create_time);
4149 srv_put_dos_date2(pdata,4,atime);
4150 srv_put_dos_date2(pdata,8,mtime); /* write time */
4151 SIVAL(pdata,12,(uint32)file_size);
4152 SIVAL(pdata,16,(uint32)allocation_size);
4153 SSVAL(pdata,20,mode);
4154 SIVAL(pdata,22,ea_size);
4158 case SMB_INFO_IS_NAME_VALID:
4159 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4160 if (tran_call == TRANSACT2_QFILEINFO) {
4161 /* os/2 needs this ? really ?*/
4162 reply_doserror(req, ERRDOS, ERRbadfunc);
4169 case SMB_INFO_QUERY_EAS_FROM_LIST:
4171 size_t total_ea_len = 0;
4172 struct ea_list *ea_file_list = NULL;
4174 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4176 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4177 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4179 if (!ea_list || (total_ea_len > data_size)) {
4181 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4185 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4189 case SMB_INFO_QUERY_ALL_EAS:
4191 /* We have data_size bytes to put EA's into. */
4192 size_t total_ea_len = 0;
4194 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4196 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4197 if (!ea_list || (total_ea_len > data_size)) {
4199 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4203 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4207 case SMB_FILE_BASIC_INFORMATION:
4208 case SMB_QUERY_FILE_BASIC_INFO:
4210 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4211 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4212 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4214 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4218 put_long_date_timespec(pdata,create_time_ts);
4219 put_long_date_timespec(pdata+8,atime_ts);
4220 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4221 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4222 SIVAL(pdata,32,mode);
4224 DEBUG(5,("SMB_QFBI - "));
4225 DEBUG(5,("create: %s ", ctime(&create_time)));
4226 DEBUG(5,("access: %s ", ctime(&atime)));
4227 DEBUG(5,("write: %s ", ctime(&mtime)));
4228 DEBUG(5,("change: %s ", ctime(&mtime)));
4229 DEBUG(5,("mode: %x\n", mode));
4232 case SMB_FILE_STANDARD_INFORMATION:
4233 case SMB_QUERY_FILE_STANDARD_INFO:
4235 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4237 SOFF_T(pdata,0,allocation_size);
4238 SOFF_T(pdata,8,file_size);
4239 SIVAL(pdata,16,nlink);
4240 SCVAL(pdata,20,delete_pending?1:0);
4241 SCVAL(pdata,21,(mode&aDIR)?1:0);
4242 SSVAL(pdata,22,0); /* Padding. */
4245 case SMB_FILE_EA_INFORMATION:
4246 case SMB_QUERY_FILE_EA_INFO:
4248 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4249 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4251 SIVAL(pdata,0,ea_size);
4255 /* Get the 8.3 name - used if NT SMB was negotiated. */
4256 case SMB_QUERY_FILE_ALT_NAME_INFO:
4257 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4259 char mangled_name[13];
4260 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4261 if (!name_to_8_3(base_name,mangled_name,
4262 True,conn->params)) {
4265 NT_STATUS_NO_MEMORY);
4267 len = srvstr_push(dstart, req->flags2,
4268 pdata+4, mangled_name,
4269 PTR_DIFF(dend, pdata+4),
4271 data_size = 4 + len;
4276 case SMB_QUERY_FILE_NAME_INFO:
4278 this must be *exactly* right for ACLs on mapped drives to work
4280 len = srvstr_push(dstart, req->flags2,
4282 PTR_DIFF(dend, pdata+4),
4284 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4285 data_size = 4 + len;
4289 case SMB_FILE_ALLOCATION_INFORMATION:
4290 case SMB_QUERY_FILE_ALLOCATION_INFO:
4291 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4293 SOFF_T(pdata,0,allocation_size);
4296 case SMB_FILE_END_OF_FILE_INFORMATION:
4297 case SMB_QUERY_FILE_END_OF_FILEINFO:
4298 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4300 SOFF_T(pdata,0,file_size);
4303 case SMB_QUERY_FILE_ALL_INFO:
4304 case SMB_FILE_ALL_INFORMATION:
4306 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4307 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4308 put_long_date_timespec(pdata,create_time_ts);
4309 put_long_date_timespec(pdata+8,atime_ts);
4310 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4311 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4312 SIVAL(pdata,32,mode);
4313 SIVAL(pdata,36,0); /* padding. */
4315 SOFF_T(pdata,0,allocation_size);
4316 SOFF_T(pdata,8,file_size);
4317 SIVAL(pdata,16,nlink);
4318 SCVAL(pdata,20,delete_pending);
4319 SCVAL(pdata,21,(mode&aDIR)?1:0);
4322 SIVAL(pdata,0,ea_size);
4323 pdata += 4; /* EA info */
4324 len = srvstr_push(dstart, req->flags2,
4326 PTR_DIFF(dend, pdata+4),
4330 data_size = PTR_DIFF(pdata,(*ppdata));
4333 case SMB_FILE_INTERNAL_INFORMATION:
4334 /* This should be an index number - looks like
4337 I think this causes us to fail the IFSKIT
4338 BasicFileInformationTest. -tpot */
4340 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4341 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4342 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4346 case SMB_FILE_ACCESS_INFORMATION:
4347 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4348 SIVAL(pdata,0,access_mask);
4352 case SMB_FILE_NAME_INFORMATION:
4353 /* Pathname with leading '\'. */
4356 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4357 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4358 SIVAL(pdata,0,byte_len);
4359 data_size = 4 + byte_len;
4363 case SMB_FILE_DISPOSITION_INFORMATION:
4364 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4366 SCVAL(pdata,0,delete_pending);
4369 case SMB_FILE_POSITION_INFORMATION:
4370 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4372 SOFF_T(pdata,0,pos);
4375 case SMB_FILE_MODE_INFORMATION:
4376 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4377 SIVAL(pdata,0,mode);
4381 case SMB_FILE_ALIGNMENT_INFORMATION:
4382 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4383 SIVAL(pdata,0,0); /* No alignment needed. */
4388 * NT4 server just returns "invalid query" to this - if we try
4389 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4392 /* The first statement above is false - verified using Thursby
4393 * client against NT4 -- gcolley.
4395 case SMB_QUERY_FILE_STREAM_INFO:
4396 case SMB_FILE_STREAM_INFORMATION: {
4397 unsigned int num_streams;
4398 struct stream_struct *streams;
4401 DEBUG(10,("call_trans2qfilepathinfo: "
4402 "SMB_FILE_STREAM_INFORMATION\n"));
4404 status = SMB_VFS_STREAMINFO(
4405 conn, fsp, fname, talloc_tos(),
4406 &num_streams, &streams);
4408 if (!NT_STATUS_IS_OK(status)) {
4409 DEBUG(10, ("could not get stream info: %s\n",
4410 nt_errstr(status)));
4411 reply_nterror(req, status);
4415 status = marshall_stream_info(num_streams, streams,
4416 pdata, max_data_bytes,
4419 if (!NT_STATUS_IS_OK(status)) {
4420 DEBUG(10, ("marshall_stream_info failed: %s\n",
4421 nt_errstr(status)));
4422 reply_nterror(req, status);
4426 TALLOC_FREE(streams);
4430 case SMB_QUERY_COMPRESSION_INFO:
4431 case SMB_FILE_COMPRESSION_INFORMATION:
4432 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4433 SOFF_T(pdata,0,file_size);
4434 SIVAL(pdata,8,0); /* ??? */
4435 SIVAL(pdata,12,0); /* ??? */
4439 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4440 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4441 put_long_date_timespec(pdata,create_time_ts);
4442 put_long_date_timespec(pdata+8,atime_ts);
4443 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4444 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4445 SOFF_T(pdata,32,allocation_size);
4446 SOFF_T(pdata,40,file_size);
4447 SIVAL(pdata,48,mode);
4448 SIVAL(pdata,52,0); /* ??? */
4452 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4453 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4454 SIVAL(pdata,0,mode);
4460 * CIFS UNIX Extensions.
4463 case SMB_QUERY_FILE_UNIX_BASIC:
4465 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4466 data_size = PTR_DIFF(pdata,(*ppdata));
4470 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4472 for (i=0; i<100; i++)
4473 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4479 case SMB_QUERY_FILE_UNIX_INFO2:
4481 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4482 data_size = PTR_DIFF(pdata,(*ppdata));
4486 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4488 for (i=0; i<100; i++)
4489 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4495 case SMB_QUERY_FILE_UNIX_LINK:
4497 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4500 reply_nterror(req, NT_STATUS_NO_MEMORY);
4504 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4506 if(!S_ISLNK(sbuf.st_mode)) {
4507 reply_unixerror(req, ERRSRV,
4512 reply_unixerror(req, ERRDOS, ERRbadlink);
4515 len = SMB_VFS_READLINK(conn,fullpathname,
4518 reply_unixerror(req, ERRDOS,
4523 len = srvstr_push(dstart, req->flags2,
4525 PTR_DIFF(dend, pdata),
4528 data_size = PTR_DIFF(pdata,(*ppdata));
4533 #if defined(HAVE_POSIX_ACLS)
4534 case SMB_QUERY_POSIX_ACL:
4536 SMB_ACL_T file_acl = NULL;
4537 SMB_ACL_T def_acl = NULL;
4538 uint16 num_file_acls = 0;
4539 uint16 num_def_acls = 0;
4541 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4542 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4544 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4547 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4548 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4552 NT_STATUS_NOT_IMPLEMENTED);
4556 if (S_ISDIR(sbuf.st_mode)) {
4557 if (fsp && fsp->is_directory) {
4558 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4560 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4562 def_acl = free_empty_sys_acl(conn, def_acl);
4565 num_file_acls = count_acl_entries(conn, file_acl);
4566 num_def_acls = count_acl_entries(conn, def_acl);
4568 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4569 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4571 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4572 SMB_POSIX_ACL_HEADER_SIZE) ));
4574 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4577 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4581 NT_STATUS_BUFFER_TOO_SMALL);
4585 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4586 SSVAL(pdata,2,num_file_acls);
4587 SSVAL(pdata,4,num_def_acls);
4588 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4590 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4593 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4596 req, NT_STATUS_INTERNAL_ERROR);
4599 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4601 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4604 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4608 NT_STATUS_INTERNAL_ERROR);
4613 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4616 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4618 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4624 case SMB_QUERY_POSIX_LOCK:
4626 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4628 SMB_BIG_UINT offset;
4630 enum brl_type lock_type;
4632 if (total_data != POSIX_LOCK_DATA_SIZE) {
4634 req, NT_STATUS_INVALID_PARAMETER);
4638 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4639 case POSIX_LOCK_TYPE_READ:
4640 lock_type = READ_LOCK;
4642 case POSIX_LOCK_TYPE_WRITE:
4643 lock_type = WRITE_LOCK;
4645 case POSIX_LOCK_TYPE_UNLOCK:
4647 /* There's no point in asking for an unlock... */
4650 NT_STATUS_INVALID_PARAMETER);
4654 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4655 #if defined(HAVE_LONGLONG)
4656 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4657 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4658 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4659 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4660 #else /* HAVE_LONGLONG */
4661 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4662 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4663 #endif /* HAVE_LONGLONG */
4665 status = query_lock(fsp,
4672 if (ERROR_WAS_LOCK_DENIED(status)) {
4673 /* Here we need to report who has it locked... */
4674 data_size = POSIX_LOCK_DATA_SIZE;
4676 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4677 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4678 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4679 #if defined(HAVE_LONGLONG)
4680 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4681 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4682 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4683 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4684 #else /* HAVE_LONGLONG */
4685 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4686 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4687 #endif /* HAVE_LONGLONG */
4689 } else if (NT_STATUS_IS_OK(status)) {
4690 /* For success we just return a copy of what we sent
4691 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4692 data_size = POSIX_LOCK_DATA_SIZE;
4693 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4694 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4696 reply_nterror(req, status);
4703 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4707 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4713 /****************************************************************************
4714 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4716 ****************************************************************************/
4718 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4719 connection_struct *conn,
4720 const char *oldname_in,
4721 const char *newname_in)
4723 SMB_STRUCT_STAT sbuf1, sbuf2;
4724 char *last_component_oldname = NULL;
4725 char *last_component_newname = NULL;
4726 char *oldname = NULL;
4727 char *newname = NULL;
4728 NTSTATUS status = NT_STATUS_OK;
4733 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4734 &last_component_oldname, &sbuf1);
4735 if (!NT_STATUS_IS_OK(status)) {
4739 status = check_name(conn, oldname);
4740 if (!NT_STATUS_IS_OK(status)) {
4744 /* source must already exist. */
4745 if (!VALID_STAT(sbuf1)) {
4746 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4749 status = unix_convert(ctx, conn, newname_in, False, &newname,
4750 &last_component_newname, &sbuf2);
4751 if (!NT_STATUS_IS_OK(status)) {
4755 status = check_name(conn, newname);
4756 if (!NT_STATUS_IS_OK(status)) {
4760 /* Disallow if newname already exists. */
4761 if (VALID_STAT(sbuf2)) {
4762 return NT_STATUS_OBJECT_NAME_COLLISION;
4765 /* No links from a directory. */
4766 if (S_ISDIR(sbuf1.st_mode)) {
4767 return NT_STATUS_FILE_IS_A_DIRECTORY;
4770 /* Ensure this is within the share. */
4771 status = check_reduced_name(conn, oldname);
4772 if (!NT_STATUS_IS_OK(status)) {
4776 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4778 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4779 status = map_nt_error_from_unix(errno);
4780 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4781 nt_errstr(status), newname, oldname));
4787 /****************************************************************************
4788 Deal with setting the time from any of the setfilepathinfo functions.
4789 ****************************************************************************/
4791 NTSTATUS smb_set_file_time(connection_struct *conn,
4794 const SMB_STRUCT_STAT *psbuf,
4795 struct timespec ts[2],
4796 bool setting_write_time)
4799 FILE_NOTIFY_CHANGE_LAST_ACCESS
4800 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4802 if (!VALID_STAT(*psbuf)) {
4803 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4806 /* get some defaults (no modifications) if any info is zero or -1. */
4807 if (null_timespec(ts[0])) {
4808 ts[0] = get_atimespec(psbuf);
4809 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4812 if (null_timespec(ts[1])) {
4813 ts[1] = get_mtimespec(psbuf);
4814 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4817 if (!setting_write_time) {
4818 /* ts[1] comes from change time, not write time. */
4819 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4822 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4823 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4826 * Try and set the times of this file if
4827 * they are different from the current values.
4831 struct timespec mts = get_mtimespec(psbuf);
4832 struct timespec ats = get_atimespec(psbuf);
4833 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4834 return NT_STATUS_OK;
4838 if (setting_write_time) {
4840 * This was a setfileinfo on an open file.
4841 * NT does this a lot. We also need to
4842 * set the time here, as it can be read by
4843 * FindFirst/FindNext and with the patch for bug #2045
4844 * in smbd/fileio.c it ensures that this timestamp is
4845 * kept sticky even after a write. We save the request
4846 * away and will set it on file close and after a write. JRA.
4849 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4850 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4853 set_write_time_fsp(fsp, ts[1], true);
4855 set_write_time_path(conn, fname,
4856 vfs_file_id_from_sbuf(conn, psbuf),
4861 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4863 if(file_ntimes(conn, fname, ts)!=0) {
4864 return map_nt_error_from_unix(errno);
4866 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4868 return NT_STATUS_OK;
4871 /****************************************************************************
4872 Deal with setting the dosmode from any of the setfilepathinfo functions.
4873 ****************************************************************************/
4875 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4877 SMB_STRUCT_STAT *psbuf,
4880 if (!VALID_STAT(*psbuf)) {
4881 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4885 if (S_ISDIR(psbuf->st_mode)) {
4892 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4894 /* check the mode isn't different, before changing it */
4895 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4897 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4898 fname, (unsigned int)dosmode ));
4900 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
4901 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4902 fname, strerror(errno)));
4903 return map_nt_error_from_unix(errno);
4906 return NT_STATUS_OK;
4909 /****************************************************************************
4910 Deal with setting the size from any of the setfilepathinfo functions.
4911 ****************************************************************************/
4913 static NTSTATUS smb_set_file_size(connection_struct *conn,
4914 struct smb_request *req,
4917 SMB_STRUCT_STAT *psbuf,
4920 NTSTATUS status = NT_STATUS_OK;
4921 files_struct *new_fsp = NULL;
4923 if (!VALID_STAT(*psbuf)) {
4924 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4927 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4929 if (size == get_file_size(*psbuf)) {
4930 return NT_STATUS_OK;
4933 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4934 fname, (double)size ));
4936 if (fsp && fsp->fh->fd != -1) {
4937 /* Handle based call. */
4938 if (vfs_set_filelen(fsp, size) == -1) {
4939 return map_nt_error_from_unix(errno);
4941 return NT_STATUS_OK;
4944 status = open_file_ntcreate(conn, req, fname, psbuf,
4945 FILE_WRITE_ATTRIBUTES,
4946 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4949 FILE_ATTRIBUTE_NORMAL,
4950 FORCE_OPLOCK_BREAK_TO_NONE,
4953 if (!NT_STATUS_IS_OK(status)) {
4954 /* NB. We check for open_was_deferred in the caller. */
4958 if (vfs_set_filelen(new_fsp, size) == -1) {
4959 status = map_nt_error_from_unix(errno);
4960 close_file(new_fsp,NORMAL_CLOSE);
4964 close_file(new_fsp,NORMAL_CLOSE);
4965 return NT_STATUS_OK;
4968 /****************************************************************************
4969 Deal with SMB_INFO_SET_EA.
4970 ****************************************************************************/
4972 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4978 struct ea_list *ea_list = NULL;
4979 TALLOC_CTX *ctx = NULL;
4980 NTSTATUS status = NT_STATUS_OK;
4982 if (total_data < 10) {
4984 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4985 length. They seem to have no effect. Bug #3212. JRA */
4987 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4988 /* We're done. We only get EA info in this call. */
4989 return NT_STATUS_OK;
4992 return NT_STATUS_INVALID_PARAMETER;
4995 if (IVAL(pdata,0) > total_data) {
4996 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4997 IVAL(pdata,0), (unsigned int)total_data));
4998 return NT_STATUS_INVALID_PARAMETER;
5002 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5004 return NT_STATUS_INVALID_PARAMETER;
5006 status = set_ea(conn, fsp, fname, ea_list);
5011 /****************************************************************************
5012 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5013 ****************************************************************************/
5015 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5020 SMB_STRUCT_STAT *psbuf)
5022 NTSTATUS status = NT_STATUS_OK;
5023 bool delete_on_close;
5026 if (total_data < 1) {
5027 return NT_STATUS_INVALID_PARAMETER;
5031 return NT_STATUS_INVALID_HANDLE;
5034 delete_on_close = (CVAL(pdata,0) ? True : False);
5035 dosmode = dos_mode(conn, fname, psbuf);
5037 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5038 "delete_on_close = %u\n",
5040 (unsigned int)dosmode,
5041 (unsigned int)delete_on_close ));
5043 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5045 if (!NT_STATUS_IS_OK(status)) {
5049 /* The set is across all open files on this dev/inode pair. */
5050 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
5051 return NT_STATUS_ACCESS_DENIED;
5053 return NT_STATUS_OK;
5056 /****************************************************************************
5057 Deal with SMB_FILE_POSITION_INFORMATION.
5058 ****************************************************************************/
5060 static NTSTATUS smb_file_position_information(connection_struct *conn,
5065 SMB_BIG_UINT position_information;
5067 if (total_data < 8) {
5068 return NT_STATUS_INVALID_PARAMETER;
5072 /* Ignore on pathname based set. */
5073 return NT_STATUS_OK;
5076 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
5077 #ifdef LARGE_SMB_OFF_T
5078 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5079 #else /* LARGE_SMB_OFF_T */
5080 if (IVAL(pdata,4) != 0) {
5081 /* more than 32 bits? */
5082 return NT_STATUS_INVALID_PARAMETER;
5084 #endif /* LARGE_SMB_OFF_T */
5086 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5087 fsp->fsp_name, (double)position_information ));
5088 fsp->fh->position_information = position_information;
5089 return NT_STATUS_OK;
5092 /****************************************************************************
5093 Deal with SMB_FILE_MODE_INFORMATION.
5094 ****************************************************************************/
5096 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5102 if (total_data < 4) {
5103 return NT_STATUS_INVALID_PARAMETER;
5105 mode = IVAL(pdata,0);
5106 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5107 return NT_STATUS_INVALID_PARAMETER;
5109 return NT_STATUS_OK;
5112 /****************************************************************************
5113 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5114 ****************************************************************************/
5116 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5117 struct smb_request *req,
5122 char *link_target = NULL;
5123 const char *newname = fname;
5124 NTSTATUS status = NT_STATUS_OK;
5125 TALLOC_CTX *ctx = talloc_tos();
5127 /* Set a symbolic link. */
5128 /* Don't allow this if follow links is false. */
5130 if (total_data == 0) {
5131 return NT_STATUS_INVALID_PARAMETER;
5134 if (!lp_symlinks(SNUM(conn))) {
5135 return NT_STATUS_ACCESS_DENIED;
5138 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5139 total_data, STR_TERMINATE);
5142 return NT_STATUS_INVALID_PARAMETER;
5145 /* !widelinks forces the target path to be within the share. */
5146 /* This means we can interpret the target as a pathname. */
5147 if (!lp_widelinks(SNUM(conn))) {
5148 char *rel_name = NULL;
5149 char *last_dirp = NULL;
5151 if (*link_target == '/') {
5152 /* No absolute paths allowed. */
5153 return NT_STATUS_ACCESS_DENIED;
5155 rel_name = talloc_strdup(ctx,newname);
5157 return NT_STATUS_NO_MEMORY;
5159 last_dirp = strrchr_m(rel_name, '/');
5161 last_dirp[1] = '\0';
5163 rel_name = talloc_strdup(ctx,"./");
5165 return NT_STATUS_NO_MEMORY;
5168 rel_name = talloc_asprintf_append(rel_name,
5172 return NT_STATUS_NO_MEMORY;
5175 status = check_name(conn, rel_name);
5176 if (!NT_STATUS_IS_OK(status)) {
5181 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5182 newname, link_target ));
5184 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5185 return map_nt_error_from_unix(errno);
5188 return NT_STATUS_OK;
5191 /****************************************************************************
5192 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5193 ****************************************************************************/
5195 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5196 struct smb_request *req,
5197 const char *pdata, int total_data,
5200 char *oldname = NULL;
5201 TALLOC_CTX *ctx = talloc_tos();
5202 NTSTATUS status = NT_STATUS_OK;
5204 /* Set a hard link. */
5205 if (total_data == 0) {
5206 return NT_STATUS_INVALID_PARAMETER;
5209 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5210 total_data, STR_TERMINATE, &status);
5211 if (!NT_STATUS_IS_OK(status)) {
5215 status = resolve_dfspath(ctx, conn,
5216 req->flags2 & FLAGS2_DFS_PATHNAMES,
5219 if (!NT_STATUS_IS_OK(status)) {
5223 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5226 return hardlink_internals(ctx, conn, oldname, fname);
5229 /****************************************************************************
5230 Deal with SMB_FILE_RENAME_INFORMATION.
5231 ****************************************************************************/
5233 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5234 struct smb_request *req,
5243 char *newname = NULL;
5244 char *base_name = NULL;
5245 bool dest_has_wcard = False;
5246 NTSTATUS status = NT_STATUS_OK;
5248 TALLOC_CTX *ctx = talloc_tos();
5250 if (total_data < 13) {
5251 return NT_STATUS_INVALID_PARAMETER;
5254 overwrite = (CVAL(pdata,0) ? True : False);
5255 root_fid = IVAL(pdata,4);
5256 len = IVAL(pdata,8);
5258 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5259 return NT_STATUS_INVALID_PARAMETER;
5262 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5265 if (!NT_STATUS_IS_OK(status)) {
5269 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5272 status = resolve_dfspath_wcard(ctx, conn,
5273 req->flags2 & FLAGS2_DFS_PATHNAMES,
5277 if (!NT_STATUS_IS_OK(status)) {
5281 /* Check the new name has no '/' characters. */
5282 if (strchr_m(newname, '/')) {
5283 return NT_STATUS_NOT_SUPPORTED;
5286 /* Create the base directory. */
5287 base_name = talloc_strdup(ctx, fname);
5289 return NT_STATUS_NO_MEMORY;
5291 p = strrchr_m(base_name, '/');
5295 base_name = talloc_strdup(ctx, "./");
5297 return NT_STATUS_NO_MEMORY;
5300 /* Append the new name. */
5301 base_name = talloc_asprintf_append(base_name,
5305 return NT_STATUS_NO_MEMORY;
5309 SMB_STRUCT_STAT sbuf;
5310 char *newname_last_component = NULL;
5314 status = unix_convert(ctx, conn, newname, False,
5316 &newname_last_component,
5319 /* If an error we expect this to be
5320 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5322 if (!NT_STATUS_IS_OK(status)
5323 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5328 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5329 fsp->fnum, fsp->fsp_name, base_name ));
5330 status = rename_internals_fsp(conn, fsp, base_name,
5331 newname_last_component, 0,
5334 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5335 fname, base_name ));
5336 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5337 overwrite, False, dest_has_wcard,
5338 FILE_WRITE_ATTRIBUTES);
5344 /****************************************************************************
5345 Deal with SMB_SET_POSIX_ACL.
5346 ****************************************************************************/
5348 #if defined(HAVE_POSIX_ACLS)
5349 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5354 SMB_STRUCT_STAT *psbuf)
5356 uint16 posix_acl_version;
5357 uint16 num_file_acls;
5358 uint16 num_def_acls;
5359 bool valid_file_acls = True;
5360 bool valid_def_acls = True;
5362 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5363 return NT_STATUS_INVALID_PARAMETER;
5365 posix_acl_version = SVAL(pdata,0);
5366 num_file_acls = SVAL(pdata,2);
5367 num_def_acls = SVAL(pdata,4);
5369 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5370 valid_file_acls = False;
5374 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5375 valid_def_acls = False;
5379 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5380 return NT_STATUS_INVALID_PARAMETER;
5383 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5384 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5385 return NT_STATUS_INVALID_PARAMETER;
5388 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5389 fname ? fname : fsp->fsp_name,
5390 (unsigned int)num_file_acls,
5391 (unsigned int)num_def_acls));
5393 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5394 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5395 return map_nt_error_from_unix(errno);
5398 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5399 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5400 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5401 return map_nt_error_from_unix(errno);
5403 return NT_STATUS_OK;
5407 /****************************************************************************
5408 Deal with SMB_SET_POSIX_LOCK.
5409 ****************************************************************************/
5411 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5412 const struct smb_request *req,
5418 SMB_BIG_UINT offset;
5420 bool blocking_lock = False;
5421 enum brl_type lock_type;
5423 NTSTATUS status = NT_STATUS_OK;
5425 if (fsp == NULL || fsp->fh->fd == -1) {
5426 return NT_STATUS_INVALID_HANDLE;
5429 if (total_data != POSIX_LOCK_DATA_SIZE) {
5430 return NT_STATUS_INVALID_PARAMETER;
5433 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5434 case POSIX_LOCK_TYPE_READ:
5435 lock_type = READ_LOCK;
5437 case POSIX_LOCK_TYPE_WRITE:
5438 /* Return the right POSIX-mappable error code for files opened read-only. */
5439 if (!fsp->can_write) {
5440 return NT_STATUS_INVALID_HANDLE;
5442 lock_type = WRITE_LOCK;
5444 case POSIX_LOCK_TYPE_UNLOCK:
5445 lock_type = UNLOCK_LOCK;
5448 return NT_STATUS_INVALID_PARAMETER;
5451 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5452 blocking_lock = False;
5453 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5454 blocking_lock = True;
5456 return NT_STATUS_INVALID_PARAMETER;
5459 if (!lp_blocking_locks(SNUM(conn))) {
5460 blocking_lock = False;
5463 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5464 #if defined(HAVE_LONGLONG)
5465 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5466 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5467 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5468 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5469 #else /* HAVE_LONGLONG */
5470 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5471 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5472 #endif /* HAVE_LONGLONG */
5474 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5475 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5477 (unsigned int)lock_type,
5478 (unsigned int)lock_pid,
5482 if (lock_type == UNLOCK_LOCK) {
5483 status = do_unlock(smbd_messaging_context(),
5490 uint32 block_smbpid;
5492 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5503 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5505 * A blocking lock was requested. Package up
5506 * this smb into a queued request and push it
5507 * onto the blocking lock queue.
5509 if(push_blocking_lock_request(br_lck,
5512 -1, /* infinite timeout. */
5520 TALLOC_FREE(br_lck);
5524 TALLOC_FREE(br_lck);
5530 /****************************************************************************
5531 Deal with SMB_INFO_STANDARD.
5532 ****************************************************************************/
5534 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5539 const SMB_STRUCT_STAT *psbuf)
5541 struct timespec ts[2];
5543 if (total_data < 12) {
5544 return NT_STATUS_INVALID_PARAMETER;
5548 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5550 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5552 DEBUG(10,("smb_set_info_standard: file %s\n",
5553 fname ? fname : fsp->fsp_name ));
5555 return smb_set_file_time(conn,
5563 /****************************************************************************
5564 Deal with SMB_SET_FILE_BASIC_INFO.
5565 ****************************************************************************/
5567 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5572 SMB_STRUCT_STAT *psbuf)
5574 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5575 struct timespec write_time;
5576 struct timespec changed_time;
5578 struct timespec ts[2];
5579 NTSTATUS status = NT_STATUS_OK;
5580 bool setting_write_time = true;
5582 if (total_data < 36) {
5583 return NT_STATUS_INVALID_PARAMETER;
5586 /* Set the attributes */
5587 dosmode = IVAL(pdata,32);
5588 status = smb_set_file_dosmode(conn,
5592 if (!NT_STATUS_IS_OK(status)) {
5596 /* Ignore create time at offset pdata. */
5599 ts[0] = interpret_long_date(pdata+8);
5601 write_time = interpret_long_date(pdata+16);
5602 changed_time = interpret_long_date(pdata+24);
5605 ts[1] = timespec_min(&write_time, &changed_time);
5607 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5611 /* Prefer a defined time to an undefined one. */
5612 if (null_timespec(ts[1])) {
5613 if (null_timespec(write_time)) {
5614 ts[1] = changed_time;
5615 setting_write_time = false;
5621 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5622 fname ? fname : fsp->fsp_name ));
5624 return smb_set_file_time(conn,
5629 setting_write_time);
5632 /****************************************************************************
5633 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5634 ****************************************************************************/
5636 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5637 struct smb_request *req,
5642 SMB_STRUCT_STAT *psbuf)
5644 SMB_BIG_UINT allocation_size = 0;
5645 NTSTATUS status = NT_STATUS_OK;
5646 files_struct *new_fsp = NULL;
5648 if (!VALID_STAT(*psbuf)) {
5649 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5652 if (total_data < 8) {
5653 return NT_STATUS_INVALID_PARAMETER;
5656 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5657 #ifdef LARGE_SMB_OFF_T
5658 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5659 #else /* LARGE_SMB_OFF_T */
5660 if (IVAL(pdata,4) != 0) {
5661 /* more than 32 bits? */
5662 return NT_STATUS_INVALID_PARAMETER;
5664 #endif /* LARGE_SMB_OFF_T */
5666 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5667 fname, (double)allocation_size ));
5669 if (allocation_size) {
5670 allocation_size = smb_roundup(conn, allocation_size);
5673 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5674 fname, (double)allocation_size ));
5676 if (fsp && fsp->fh->fd != -1) {
5677 /* Open file handle. */
5678 /* Only change if needed. */
5679 if (allocation_size != get_file_size(*psbuf)) {
5680 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5681 return map_nt_error_from_unix(errno);
5684 /* But always update the time. */
5686 * This is equivalent to a write. Ensure it's seen immediately
5687 * if there are no pending writes.
5689 trigger_write_time_update(fsp);
5690 return NT_STATUS_OK;
5693 /* Pathname or stat or directory file. */
5695 status = open_file_ntcreate(conn, req, fname, psbuf,
5697 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5700 FILE_ATTRIBUTE_NORMAL,
5701 FORCE_OPLOCK_BREAK_TO_NONE,
5704 if (!NT_STATUS_IS_OK(status)) {
5705 /* NB. We check for open_was_deferred in the caller. */
5709 /* Only change if needed. */
5710 if (allocation_size != get_file_size(*psbuf)) {
5711 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5712 status = map_nt_error_from_unix(errno);
5713 close_file(new_fsp,NORMAL_CLOSE);
5718 /* Changing the allocation size should set the last mod time. */
5720 * This is equivalent to a write. Ensure it's seen immediately
5721 * if there are no pending writes.
5723 trigger_write_time_update(new_fsp);
5725 close_file(new_fsp,NORMAL_CLOSE);
5726 return NT_STATUS_OK;
5729 /****************************************************************************
5730 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5731 ****************************************************************************/
5733 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5734 struct smb_request *req,
5739 SMB_STRUCT_STAT *psbuf)
5743 if (total_data < 8) {
5744 return NT_STATUS_INVALID_PARAMETER;
5747 size = IVAL(pdata,0);
5748 #ifdef LARGE_SMB_OFF_T
5749 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5750 #else /* LARGE_SMB_OFF_T */
5751 if (IVAL(pdata,4) != 0) {
5752 /* more than 32 bits? */
5753 return NT_STATUS_INVALID_PARAMETER;
5755 #endif /* LARGE_SMB_OFF_T */
5756 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5757 "file %s to %.0f\n", fname, (double)size ));
5759 return smb_set_file_size(conn, req,
5766 /****************************************************************************
5767 Allow a UNIX info mknod.
5768 ****************************************************************************/
5770 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5774 SMB_STRUCT_STAT *psbuf)
5776 uint32 file_type = IVAL(pdata,56);
5777 #if defined(HAVE_MAKEDEV)
5778 uint32 dev_major = IVAL(pdata,60);
5779 uint32 dev_minor = IVAL(pdata,68);
5781 SMB_DEV_T dev = (SMB_DEV_T)0;
5782 uint32 raw_unixmode = IVAL(pdata,84);
5786 if (total_data < 100) {
5787 return NT_STATUS_INVALID_PARAMETER;
5790 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5791 if (!NT_STATUS_IS_OK(status)) {
5795 #if defined(HAVE_MAKEDEV)
5796 dev = makedev(dev_major, dev_minor);
5799 switch (file_type) {
5800 #if defined(S_IFIFO)
5801 case UNIX_TYPE_FIFO:
5802 unixmode |= S_IFIFO;
5805 #if defined(S_IFSOCK)
5806 case UNIX_TYPE_SOCKET:
5807 unixmode |= S_IFSOCK;
5810 #if defined(S_IFCHR)
5811 case UNIX_TYPE_CHARDEV:
5812 unixmode |= S_IFCHR;
5815 #if defined(S_IFBLK)
5816 case UNIX_TYPE_BLKDEV:
5817 unixmode |= S_IFBLK;
5821 return NT_STATUS_INVALID_PARAMETER;
5824 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5825 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5827 /* Ok - do the mknod. */
5828 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5829 return map_nt_error_from_unix(errno);
5832 /* If any of the other "set" calls fail we
5833 * don't want to end up with a half-constructed mknod.
5836 if (lp_inherit_perms(SNUM(conn))) {
5838 conn, parent_dirname(fname),
5842 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5843 status = map_nt_error_from_unix(errno);
5844 SMB_VFS_UNLINK(conn,fname);
5847 return NT_STATUS_OK;
5850 /****************************************************************************
5851 Deal with SMB_SET_FILE_UNIX_BASIC.
5852 ****************************************************************************/
5854 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5855 struct smb_request *req,
5860 SMB_STRUCT_STAT *psbuf)
5862 struct timespec ts[2];
5863 uint32 raw_unixmode;
5866 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5867 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5868 NTSTATUS status = NT_STATUS_OK;
5869 bool delete_on_fail = False;
5870 enum perm_type ptype;
5872 if (total_data < 100) {
5873 return NT_STATUS_INVALID_PARAMETER;
5876 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5877 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5878 size=IVAL(pdata,0); /* first 8 Bytes are size */
5879 #ifdef LARGE_SMB_OFF_T
5880 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5881 #else /* LARGE_SMB_OFF_T */
5882 if (IVAL(pdata,4) != 0) {
5883 /* more than 32 bits? */
5884 return NT_STATUS_INVALID_PARAMETER;
5886 #endif /* LARGE_SMB_OFF_T */
5889 ts[0] = interpret_long_date(pdata+24); /* access_time */
5890 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5891 set_owner = (uid_t)IVAL(pdata,40);
5892 set_grp = (gid_t)IVAL(pdata,48);
5893 raw_unixmode = IVAL(pdata,84);
5895 if (VALID_STAT(*psbuf)) {
5896 if (S_ISDIR(psbuf->st_mode)) {
5897 ptype = PERM_EXISTING_DIR;
5899 ptype = PERM_EXISTING_FILE;
5902 ptype = PERM_NEW_FILE;
5905 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5906 if (!NT_STATUS_IS_OK(status)) {
5910 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5911 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5912 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5914 if (!VALID_STAT(*psbuf)) {
5916 * The only valid use of this is to create character and block
5917 * devices, and named pipes. This is deprecated (IMHO) and
5918 * a new info level should be used for mknod. JRA.
5921 status = smb_unix_mknod(conn,
5926 if (!NT_STATUS_IS_OK(status)) {
5930 /* Ensure we don't try and change anything else. */
5931 raw_unixmode = SMB_MODE_NO_CHANGE;
5932 size = get_file_size(*psbuf);
5933 ts[0] = get_atimespec(psbuf);
5934 ts[1] = get_mtimespec(psbuf);
5936 * We continue here as we might want to change the
5939 delete_on_fail = True;
5943 /* Horrible backwards compatibility hack as an old server bug
5944 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5948 size = get_file_size(*psbuf);
5953 * Deal with the UNIX specific mode set.
5956 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5957 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5958 (unsigned int)unixmode, fname ));
5959 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5960 return map_nt_error_from_unix(errno);
5965 * Deal with the UNIX specific uid set.
5968 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5971 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
5972 (unsigned int)set_owner, fname ));
5974 if (S_ISLNK(psbuf->st_mode)) {
5975 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
5977 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
5981 status = map_nt_error_from_unix(errno);
5982 if (delete_on_fail) {
5983 SMB_VFS_UNLINK(conn,fname);
5990 * Deal with the UNIX specific gid set.
5993 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5994 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5995 (unsigned int)set_owner, fname ));
5996 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5997 status = map_nt_error_from_unix(errno);
5998 if (delete_on_fail) {
5999 SMB_VFS_UNLINK(conn,fname);
6005 /* Deal with any size changes. */
6007 status = smb_set_file_size(conn, req,
6012 if (!NT_STATUS_IS_OK(status)) {
6016 /* Deal with any time changes. */
6018 return smb_set_file_time(conn,
6026 /****************************************************************************
6027 Deal with SMB_SET_FILE_UNIX_INFO2.
6028 ****************************************************************************/
6030 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6031 struct smb_request *req,
6036 SMB_STRUCT_STAT *psbuf)
6042 if (total_data < 116) {
6043 return NT_STATUS_INVALID_PARAMETER;
6046 /* Start by setting all the fields that are common between UNIX_BASIC
6049 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6051 if (!NT_STATUS_IS_OK(status)) {
6055 smb_fflags = IVAL(pdata, 108);
6056 smb_fmask = IVAL(pdata, 112);
6058 /* NB: We should only attempt to alter the file flags if the client
6059 * sends a non-zero mask.
6061 if (smb_fmask != 0) {
6062 int stat_fflags = 0;
6064 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6066 /* Client asked to alter a flag we don't understand. */
6067 return NT_STATUS_INVALID_PARAMETER;
6070 if (fsp && fsp->fh->fd != -1) {
6071 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6072 return NT_STATUS_NOT_SUPPORTED;
6074 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6075 return map_nt_error_from_unix(errno);
6080 /* XXX: need to add support for changing the create_time here. You
6081 * can do this for paths on Darwin with setattrlist(2). The right way
6082 * to hook this up is probably by extending the VFS utimes interface.
6085 return NT_STATUS_OK;
6088 /****************************************************************************
6089 Create a directory with POSIX semantics.
6090 ****************************************************************************/
6092 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6093 struct smb_request *req,
6097 SMB_STRUCT_STAT *psbuf,
6098 int *pdata_return_size)
6100 NTSTATUS status = NT_STATUS_OK;
6101 uint32 raw_unixmode = 0;
6102 uint32 mod_unixmode = 0;
6103 mode_t unixmode = (mode_t)0;
6104 files_struct *fsp = NULL;
6105 uint16 info_level_return = 0;
6107 char *pdata = *ppdata;
6109 if (total_data < 18) {
6110 return NT_STATUS_INVALID_PARAMETER;
6113 raw_unixmode = IVAL(pdata,8);
6114 /* Next 4 bytes are not yet defined. */
6116 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6117 if (!NT_STATUS_IS_OK(status)) {
6121 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6123 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6124 fname, (unsigned int)unixmode ));
6126 status = open_directory(conn, req,
6129 FILE_READ_ATTRIBUTES, /* Just a stat open */
6130 FILE_SHARE_NONE, /* Ignored for stat opens */
6137 if (NT_STATUS_IS_OK(status)) {
6138 close_file(fsp, NORMAL_CLOSE);
6141 info_level_return = SVAL(pdata,16);
6143 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6144 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6145 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6146 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6148 *pdata_return_size = 12;
6151 /* Realloc the data size */
6152 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6153 if (*ppdata == NULL) {
6154 *pdata_return_size = 0;
6155 return NT_STATUS_NO_MEMORY;
6159 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6160 SSVAL(pdata,2,0); /* No fnum. */
6161 SIVAL(pdata,4,info); /* Was directory created. */
6163 switch (info_level_return) {
6164 case SMB_QUERY_FILE_UNIX_BASIC:
6165 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6166 SSVAL(pdata,10,0); /* Padding. */
6167 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6169 case SMB_QUERY_FILE_UNIX_INFO2:
6170 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6171 SSVAL(pdata,10,0); /* Padding. */
6172 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6175 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6176 SSVAL(pdata,10,0); /* Padding. */
6183 /****************************************************************************
6184 Open/Create a file with POSIX semantics.
6185 ****************************************************************************/
6187 static NTSTATUS smb_posix_open(connection_struct *conn,
6188 struct smb_request *req,
6192 SMB_STRUCT_STAT *psbuf,
6193 int *pdata_return_size)
6195 bool extended_oplock_granted = False;
6196 char *pdata = *ppdata;
6198 uint32 wire_open_mode = 0;
6199 uint32 raw_unixmode = 0;
6200 uint32 mod_unixmode = 0;
6201 uint32 create_disp = 0;
6202 uint32 access_mask = 0;
6203 uint32 create_options = 0;
6204 NTSTATUS status = NT_STATUS_OK;
6205 mode_t unixmode = (mode_t)0;
6206 files_struct *fsp = NULL;
6207 int oplock_request = 0;
6209 uint16 info_level_return = 0;
6211 if (total_data < 18) {
6212 return NT_STATUS_INVALID_PARAMETER;
6215 flags = IVAL(pdata,0);
6216 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6217 if (oplock_request) {
6218 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6221 wire_open_mode = IVAL(pdata,4);
6223 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6224 return smb_posix_mkdir(conn, req,
6232 switch (wire_open_mode & SMB_ACCMODE) {
6234 access_mask = FILE_READ_DATA;
6237 access_mask = FILE_WRITE_DATA;
6240 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6243 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6244 (unsigned int)wire_open_mode ));
6245 return NT_STATUS_INVALID_PARAMETER;
6248 wire_open_mode &= ~SMB_ACCMODE;
6250 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6251 create_disp = FILE_CREATE;
6252 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6253 create_disp = FILE_OVERWRITE_IF;
6254 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6255 create_disp = FILE_OPEN_IF;
6257 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6258 (unsigned int)wire_open_mode ));
6259 return NT_STATUS_INVALID_PARAMETER;
6262 raw_unixmode = IVAL(pdata,8);
6263 /* Next 4 bytes are not yet defined. */
6265 status = unix_perms_from_wire(conn,
6268 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6271 if (!NT_STATUS_IS_OK(status)) {
6275 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6277 if (wire_open_mode & SMB_O_SYNC) {
6278 create_options |= FILE_WRITE_THROUGH;
6280 if (wire_open_mode & SMB_O_APPEND) {
6281 access_mask |= FILE_APPEND_DATA;
6283 if (wire_open_mode & SMB_O_DIRECT) {
6284 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6287 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6289 (unsigned int)wire_open_mode,
6290 (unsigned int)unixmode ));
6292 status = open_file_ntcreate(conn, req,
6296 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6298 0, /* no create options yet. */
6304 if (!NT_STATUS_IS_OK(status)) {
6308 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6309 extended_oplock_granted = True;
6312 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6313 extended_oplock_granted = True;
6316 info_level_return = SVAL(pdata,16);
6318 /* Allocate the correct return size. */
6320 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6321 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6322 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6323 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6325 *pdata_return_size = 12;
6328 /* Realloc the data size */
6329 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6330 if (*ppdata == NULL) {
6331 close_file(fsp,ERROR_CLOSE);
6332 *pdata_return_size = 0;
6333 return NT_STATUS_NO_MEMORY;
6337 if (extended_oplock_granted) {
6338 if (flags & REQUEST_BATCH_OPLOCK) {
6339 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6341 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6343 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6344 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6346 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6349 SSVAL(pdata,2,fsp->fnum);
6350 SIVAL(pdata,4,info); /* Was file created etc. */
6352 switch (info_level_return) {
6353 case SMB_QUERY_FILE_UNIX_BASIC:
6354 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6355 SSVAL(pdata,10,0); /* padding. */
6356 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6358 case SMB_QUERY_FILE_UNIX_INFO2:
6359 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6360 SSVAL(pdata,10,0); /* padding. */
6361 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6364 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6365 SSVAL(pdata,10,0); /* padding. */
6368 return NT_STATUS_OK;
6371 /****************************************************************************
6372 Delete a file with POSIX semantics.
6373 ****************************************************************************/
6375 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6376 struct smb_request *req,
6380 SMB_STRUCT_STAT *psbuf)
6382 NTSTATUS status = NT_STATUS_OK;
6383 files_struct *fsp = NULL;
6388 struct share_mode_lock *lck = NULL;
6390 if (total_data < 2) {
6391 return NT_STATUS_INVALID_PARAMETER;
6394 flags = SVAL(pdata,0);
6396 if (!VALID_STAT(*psbuf)) {
6397 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6400 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6401 !VALID_STAT_OF_DIR(*psbuf)) {
6402 return NT_STATUS_NOT_A_DIRECTORY;
6405 DEBUG(10,("smb_posix_unlink: %s %s\n",
6406 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6409 if (VALID_STAT_OF_DIR(*psbuf)) {
6410 status = open_directory(conn, req,
6414 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6417 FILE_FLAG_POSIX_SEMANTICS|0777,
6422 status = open_file_ntcreate(conn, req,
6426 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6429 FILE_FLAG_POSIX_SEMANTICS|0777,
6430 0, /* No oplock, but break existing ones. */
6435 if (!NT_STATUS_IS_OK(status)) {
6440 * Don't lie to client. If we can't really delete due to
6441 * non-POSIX opens return SHARING_VIOLATION.
6444 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6447 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6448 "lock for file %s\n", fsp->fsp_name));
6449 close_file(fsp, NORMAL_CLOSE);
6450 return NT_STATUS_INVALID_PARAMETER;
6454 * See if others still have the file open. If this is the case, then
6455 * don't delete. If all opens are POSIX delete we can set the delete
6456 * on close disposition.
6458 for (i=0; i<lck->num_share_modes; i++) {
6459 struct share_mode_entry *e = &lck->share_modes[i];
6460 if (is_valid_share_mode_entry(e)) {
6461 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6464 /* Fail with sharing violation. */
6465 close_file(fsp, NORMAL_CLOSE);
6467 return NT_STATUS_SHARING_VIOLATION;
6472 * Set the delete on close.
6474 status = smb_set_file_disposition_info(conn,
6481 if (!NT_STATUS_IS_OK(status)) {
6482 close_file(fsp, NORMAL_CLOSE);
6487 return close_file(fsp, NORMAL_CLOSE);
6490 /****************************************************************************
6491 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6492 ****************************************************************************/
6494 static void call_trans2setfilepathinfo(connection_struct *conn,
6495 struct smb_request *req,
6496 unsigned int tran_call,
6497 char **pparams, int total_params,
6498 char **ppdata, int total_data,
6499 unsigned int max_data_bytes)
6501 char *params = *pparams;
6502 char *pdata = *ppdata;
6504 SMB_STRUCT_STAT sbuf;
6506 files_struct *fsp = NULL;
6507 NTSTATUS status = NT_STATUS_OK;
6508 int data_return_size = 0;
6509 TALLOC_CTX *ctx = talloc_tos();
6512 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6518 if (tran_call == TRANSACT2_SETFILEINFO) {
6519 if (total_params < 4) {
6520 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6524 fsp = file_fsp(SVAL(params,0));
6525 /* Basic check for non-null fsp. */
6526 if (!check_fsp_open(conn, req, fsp, ¤t_user)) {
6529 info_level = SVAL(params,2);
6531 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6533 reply_nterror(req, NT_STATUS_NO_MEMORY);
6537 if(fsp->is_directory || fsp->fh->fd == -1) {
6539 * This is actually a SETFILEINFO on a directory
6540 * handle (returned from an NT SMB). NT5.0 seems
6541 * to do this call. JRA.
6543 if (INFO_LEVEL_IS_UNIX(info_level)) {
6544 /* Always do lstat for UNIX calls. */
6545 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6546 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6547 reply_unixerror(req,ERRDOS,ERRbadpath);
6551 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6552 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6553 reply_unixerror(req,ERRDOS,ERRbadpath);
6557 } else if (fsp->print_file) {
6559 * Doing a DELETE_ON_CLOSE should cancel a print job.
6561 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6562 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6564 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6567 send_trans2_replies(conn, req, params, 2,
6572 reply_unixerror(req, ERRDOS, ERRbadpath);
6577 * Original code - this is an open file.
6579 if (!check_fsp(conn, req, fsp, ¤t_user)) {
6583 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6584 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6585 reply_unixerror(req, ERRDOS, ERRbadfid);
6591 if (total_params < 7) {
6592 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6596 info_level = SVAL(params,0);
6597 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
6598 total_params - 6, STR_TERMINATE,
6600 if (!NT_STATUS_IS_OK(status)) {
6601 reply_nterror(req, status);
6605 status = resolve_dfspath(ctx, conn,
6606 req->flags2 & FLAGS2_DFS_PATHNAMES,
6609 if (!NT_STATUS_IS_OK(status)) {
6610 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6611 reply_botherror(req,
6612 NT_STATUS_PATH_NOT_COVERED,
6613 ERRSRV, ERRbadpath);
6616 reply_nterror(req, status);
6620 status = unix_convert(ctx, conn, fname, False,
6621 &fname, NULL, &sbuf);
6622 if (!NT_STATUS_IS_OK(status)) {
6623 reply_nterror(req, status);
6627 status = check_name(conn, fname);
6628 if (!NT_STATUS_IS_OK(status)) {
6629 reply_nterror(req, status);
6633 if (INFO_LEVEL_IS_UNIX(info_level)) {
6635 * For CIFS UNIX extensions the target name may not exist.
6638 /* Always do lstat for UNIX calls. */
6639 SMB_VFS_LSTAT(conn,fname,&sbuf);
6641 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6642 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6643 reply_unixerror(req, ERRDOS, ERRbadpath);
6648 if (!CAN_WRITE(conn)) {
6649 reply_doserror(req, ERRSRV, ERRaccess);
6653 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6654 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6658 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6659 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6661 /* Realloc the parameter size */
6662 *pparams = (char *)SMB_REALLOC(*pparams,2);
6663 if (*pparams == NULL) {
6664 reply_nterror(req, NT_STATUS_NO_MEMORY);
6671 switch (info_level) {
6673 case SMB_INFO_STANDARD:
6675 status = smb_set_info_standard(conn,
6684 case SMB_INFO_SET_EA:
6686 status = smb_info_set_ea(conn,
6694 case SMB_SET_FILE_BASIC_INFO:
6695 case SMB_FILE_BASIC_INFORMATION:
6697 status = smb_set_file_basic_info(conn,
6706 case SMB_FILE_ALLOCATION_INFORMATION:
6707 case SMB_SET_FILE_ALLOCATION_INFO:
6709 status = smb_set_file_allocation_info(conn, req,
6718 case SMB_FILE_END_OF_FILE_INFORMATION:
6719 case SMB_SET_FILE_END_OF_FILE_INFO:
6721 status = smb_set_file_end_of_file_info(conn, req,
6730 case SMB_FILE_DISPOSITION_INFORMATION:
6731 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6734 /* JRA - We used to just ignore this on a path ?
6735 * Shouldn't this be invalid level on a pathname
6738 if (tran_call != TRANSACT2_SETFILEINFO) {
6739 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6742 status = smb_set_file_disposition_info(conn,
6751 case SMB_FILE_POSITION_INFORMATION:
6753 status = smb_file_position_information(conn,
6760 /* From tridge Samba4 :
6761 * MODE_INFORMATION in setfileinfo (I have no
6762 * idea what "mode information" on a file is - it takes a value of 0,
6763 * 2, 4 or 6. What could it be?).
6766 case SMB_FILE_MODE_INFORMATION:
6768 status = smb_file_mode_information(conn,
6775 * CIFS UNIX extensions.
6778 case SMB_SET_FILE_UNIX_BASIC:
6780 status = smb_set_file_unix_basic(conn, req,
6789 case SMB_SET_FILE_UNIX_INFO2:
6791 status = smb_set_file_unix_info2(conn, req,
6800 case SMB_SET_FILE_UNIX_LINK:
6802 if (tran_call != TRANSACT2_SETPATHINFO) {
6803 /* We must have a pathname for this. */
6804 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6807 status = smb_set_file_unix_link(conn, req, pdata,
6812 case SMB_SET_FILE_UNIX_HLINK:
6814 if (tran_call != TRANSACT2_SETPATHINFO) {
6815 /* We must have a pathname for this. */
6816 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6819 status = smb_set_file_unix_hlink(conn, req,
6825 case SMB_FILE_RENAME_INFORMATION:
6827 status = smb_file_rename_information(conn, req,
6833 #if defined(HAVE_POSIX_ACLS)
6834 case SMB_SET_POSIX_ACL:
6836 status = smb_set_posix_acl(conn,
6846 case SMB_SET_POSIX_LOCK:
6848 if (tran_call != TRANSACT2_SETFILEINFO) {
6849 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6852 status = smb_set_posix_lock(conn, req,
6853 pdata, total_data, fsp);
6857 case SMB_POSIX_PATH_OPEN:
6859 if (tran_call != TRANSACT2_SETPATHINFO) {
6860 /* We must have a pathname for this. */
6861 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6865 status = smb_posix_open(conn, req,
6874 case SMB_POSIX_PATH_UNLINK:
6876 if (tran_call != TRANSACT2_SETPATHINFO) {
6877 /* We must have a pathname for this. */
6878 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6882 status = smb_posix_unlink(conn, req,
6891 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6896 if (!NT_STATUS_IS_OK(status)) {
6897 if (open_was_deferred(req->mid)) {
6898 /* We have re-scheduled this call. */
6901 if (blocking_lock_was_deferred(req->mid)) {
6902 /* We have re-scheduled this call. */
6905 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6906 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6907 ERRSRV, ERRbadpath);
6910 if (info_level == SMB_POSIX_PATH_OPEN) {
6911 reply_openerror(req, status);
6915 reply_nterror(req, status);
6920 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
6926 /****************************************************************************
6927 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6928 ****************************************************************************/
6930 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
6931 char **pparams, int total_params,
6932 char **ppdata, int total_data,
6933 unsigned int max_data_bytes)
6935 char *params = *pparams;
6936 char *pdata = *ppdata;
6937 char *directory = NULL;
6938 SMB_STRUCT_STAT sbuf;
6939 NTSTATUS status = NT_STATUS_OK;
6940 struct ea_list *ea_list = NULL;
6941 TALLOC_CTX *ctx = talloc_tos();
6943 if (!CAN_WRITE(conn)) {
6944 reply_doserror(req, ERRSRV, ERRaccess);
6948 if (total_params < 5) {
6949 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6953 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
6954 total_params - 4, STR_TERMINATE,
6956 if (!NT_STATUS_IS_OK(status)) {
6957 reply_nterror(req, status);
6961 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6963 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
6964 if (!NT_STATUS_IS_OK(status)) {
6965 reply_nterror(req, status);
6969 status = check_name(conn, directory);
6970 if (!NT_STATUS_IS_OK(status)) {
6971 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6972 reply_nterror(req, status);
6976 /* Any data in this call is an EA list. */
6977 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6978 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6983 * OS/2 workplace shell seems to send SET_EA requests of "null"
6984 * length (4 bytes containing IVAL 4).
6985 * They seem to have no effect. Bug #3212. JRA.
6988 if (total_data != 4) {
6989 if (total_data < 10) {
6990 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6994 if (IVAL(pdata,0) > total_data) {
6995 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6996 IVAL(pdata,0), (unsigned int)total_data));
6997 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7001 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7004 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7007 } else if (IVAL(pdata,0) != 4) {
7008 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7012 status = create_directory(conn, req, directory);
7014 if (!NT_STATUS_IS_OK(status)) {
7015 reply_nterror(req, status);
7019 /* Try and set any given EA. */
7021 status = set_ea(conn, NULL, directory, ea_list);
7022 if (!NT_STATUS_IS_OK(status)) {
7023 reply_nterror(req, status);
7028 /* Realloc the parameter and data sizes */
7029 *pparams = (char *)SMB_REALLOC(*pparams,2);
7030 if(*pparams == NULL) {
7031 reply_nterror(req, NT_STATUS_NO_MEMORY);
7038 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7043 /****************************************************************************
7044 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7045 We don't actually do this - we just send a null response.
7046 ****************************************************************************/
7048 static void call_trans2findnotifyfirst(connection_struct *conn,
7049 struct smb_request *req,
7050 char **pparams, int total_params,
7051 char **ppdata, int total_data,
7052 unsigned int max_data_bytes)
7054 static uint16 fnf_handle = 257;
7055 char *params = *pparams;
7058 if (total_params < 6) {
7059 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7063 info_level = SVAL(params,4);
7064 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7066 switch (info_level) {
7071 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7075 /* Realloc the parameter and data sizes */
7076 *pparams = (char *)SMB_REALLOC(*pparams,6);
7077 if (*pparams == NULL) {
7078 reply_nterror(req, NT_STATUS_NO_MEMORY);
7083 SSVAL(params,0,fnf_handle);
7084 SSVAL(params,2,0); /* No changes */
7085 SSVAL(params,4,0); /* No EA errors */
7092 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7097 /****************************************************************************
7098 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7099 changes). Currently this does nothing.
7100 ****************************************************************************/
7102 static void call_trans2findnotifynext(connection_struct *conn,
7103 struct smb_request *req,
7104 char **pparams, int total_params,
7105 char **ppdata, int total_data,
7106 unsigned int max_data_bytes)
7108 char *params = *pparams;
7110 DEBUG(3,("call_trans2findnotifynext\n"));
7112 /* Realloc the parameter and data sizes */
7113 *pparams = (char *)SMB_REALLOC(*pparams,4);
7114 if (*pparams == NULL) {
7115 reply_nterror(req, NT_STATUS_NO_MEMORY);
7120 SSVAL(params,0,0); /* No changes */
7121 SSVAL(params,2,0); /* No EA errors */
7123 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7128 /****************************************************************************
7129 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7130 ****************************************************************************/
7132 static void call_trans2getdfsreferral(connection_struct *conn,
7133 struct smb_request *req,
7134 char **pparams, int total_params,
7135 char **ppdata, int total_data,
7136 unsigned int max_data_bytes)
7138 char *params = *pparams;
7139 char *pathname = NULL;
7141 int max_referral_level;
7142 NTSTATUS status = NT_STATUS_OK;
7143 TALLOC_CTX *ctx = talloc_tos();
7145 DEBUG(10,("call_trans2getdfsreferral\n"));
7147 if (total_params < 3) {
7148 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7152 max_referral_level = SVAL(params,0);
7154 if(!lp_host_msdfs()) {
7155 reply_doserror(req, ERRDOS, ERRbadfunc);
7159 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7160 total_params - 2, STR_TERMINATE);
7162 reply_nterror(req, NT_STATUS_NOT_FOUND);
7165 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7166 ppdata,&status)) < 0) {
7167 reply_nterror(req, status);
7171 SSVAL(req->inbuf, smb_flg2,
7172 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7173 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7178 #define LMCAT_SPL 0x53
7179 #define LMFUNC_GETJOBID 0x60
7181 /****************************************************************************
7182 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7183 ****************************************************************************/
7185 static void call_trans2ioctl(connection_struct *conn,
7186 struct smb_request *req,
7187 char **pparams, int total_params,
7188 char **ppdata, int total_data,
7189 unsigned int max_data_bytes)
7191 char *pdata = *ppdata;
7192 files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15));
7194 /* check for an invalid fid before proceeding */
7197 reply_doserror(req, ERRDOS, ERRbadfid);
7201 if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7202 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7203 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7204 if (*ppdata == NULL) {
7205 reply_nterror(req, NT_STATUS_NO_MEMORY);
7210 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7211 CAN ACCEPT THIS IN UNICODE. JRA. */
7213 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7214 srvstr_push(pdata, req->flags2, pdata + 2,
7215 global_myname(), 15,
7216 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7217 srvstr_push(pdata, req->flags2, pdata+18,
7218 lp_servicename(SNUM(conn)), 13,
7219 STR_ASCII|STR_TERMINATE); /* Service name */
7220 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7225 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7226 reply_doserror(req, ERRSRV, ERRerror);
7229 /****************************************************************************
7230 Reply to a SMBfindclose (stop trans2 directory search).
7231 ****************************************************************************/
7233 void reply_findclose(struct smb_request *req)
7237 START_PROFILE(SMBfindclose);
7240 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7241 END_PROFILE(SMBfindclose);
7245 dptr_num = SVALS(req->inbuf,smb_vwv0);
7247 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7249 dptr_close(&dptr_num);
7251 reply_outbuf(req, 0, 0);
7253 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7255 END_PROFILE(SMBfindclose);
7259 /****************************************************************************
7260 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7261 ****************************************************************************/
7263 void reply_findnclose(struct smb_request *req)
7267 START_PROFILE(SMBfindnclose);
7270 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7271 END_PROFILE(SMBfindnclose);
7275 dptr_num = SVAL(req->inbuf,smb_vwv0);
7277 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7279 /* We never give out valid handles for a
7280 findnotifyfirst - so any dptr_num is ok here.
7283 reply_outbuf(req, 0, 0);
7285 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7287 END_PROFILE(SMBfindnclose);
7291 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7292 struct trans_state *state)
7294 if (Protocol >= PROTOCOL_NT1) {
7295 req->flags2 |= 0x40; /* IS_LONG_NAME */
7296 SSVAL(req->inbuf,smb_flg2,req->flags2);
7299 if (conn->encrypt_level == Required && !req->encrypted) {
7300 if (state->call != TRANSACT2_QFSINFO &&
7301 state->call != TRANSACT2_SETFSINFO) {
7302 DEBUG(0,("handle_trans2: encryption required "
7304 (unsigned int)state->call));
7305 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7310 /* Now we must call the relevant TRANS2 function */
7311 switch(state->call) {
7312 case TRANSACT2_OPEN:
7314 START_PROFILE(Trans2_open);
7315 call_trans2open(conn, req,
7316 &state->param, state->total_param,
7317 &state->data, state->total_data,
7318 state->max_data_return);
7319 END_PROFILE(Trans2_open);
7323 case TRANSACT2_FINDFIRST:
7325 START_PROFILE(Trans2_findfirst);
7326 call_trans2findfirst(conn, req,
7327 &state->param, state->total_param,
7328 &state->data, state->total_data,
7329 state->max_data_return);
7330 END_PROFILE(Trans2_findfirst);
7334 case TRANSACT2_FINDNEXT:
7336 START_PROFILE(Trans2_findnext);
7337 call_trans2findnext(conn, req,
7338 &state->param, state->total_param,
7339 &state->data, state->total_data,
7340 state->max_data_return);
7341 END_PROFILE(Trans2_findnext);
7345 case TRANSACT2_QFSINFO:
7347 START_PROFILE(Trans2_qfsinfo);
7348 call_trans2qfsinfo(conn, req,
7349 &state->param, state->total_param,
7350 &state->data, state->total_data,
7351 state->max_data_return);
7352 END_PROFILE(Trans2_qfsinfo);
7356 case TRANSACT2_SETFSINFO:
7358 START_PROFILE(Trans2_setfsinfo);
7359 call_trans2setfsinfo(conn, req,
7360 &state->param, state->total_param,
7361 &state->data, state->total_data,
7362 state->max_data_return);
7363 END_PROFILE(Trans2_setfsinfo);
7367 case TRANSACT2_QPATHINFO:
7368 case TRANSACT2_QFILEINFO:
7370 START_PROFILE(Trans2_qpathinfo);
7371 call_trans2qfilepathinfo(conn, req, state->call,
7372 &state->param, state->total_param,
7373 &state->data, state->total_data,
7374 state->max_data_return);
7375 END_PROFILE(Trans2_qpathinfo);
7379 case TRANSACT2_SETPATHINFO:
7380 case TRANSACT2_SETFILEINFO:
7382 START_PROFILE(Trans2_setpathinfo);
7383 call_trans2setfilepathinfo(conn, req, state->call,
7384 &state->param, state->total_param,
7385 &state->data, state->total_data,
7386 state->max_data_return);
7387 END_PROFILE(Trans2_setpathinfo);
7391 case TRANSACT2_FINDNOTIFYFIRST:
7393 START_PROFILE(Trans2_findnotifyfirst);
7394 call_trans2findnotifyfirst(conn, req,
7395 &state->param, state->total_param,
7396 &state->data, state->total_data,
7397 state->max_data_return);
7398 END_PROFILE(Trans2_findnotifyfirst);
7402 case TRANSACT2_FINDNOTIFYNEXT:
7404 START_PROFILE(Trans2_findnotifynext);
7405 call_trans2findnotifynext(conn, req,
7406 &state->param, state->total_param,
7407 &state->data, state->total_data,
7408 state->max_data_return);
7409 END_PROFILE(Trans2_findnotifynext);
7413 case TRANSACT2_MKDIR:
7415 START_PROFILE(Trans2_mkdir);
7416 call_trans2mkdir(conn, req,
7417 &state->param, state->total_param,
7418 &state->data, state->total_data,
7419 state->max_data_return);
7420 END_PROFILE(Trans2_mkdir);
7424 case TRANSACT2_GET_DFS_REFERRAL:
7426 START_PROFILE(Trans2_get_dfs_referral);
7427 call_trans2getdfsreferral(conn, req,
7428 &state->param, state->total_param,
7429 &state->data, state->total_data,
7430 state->max_data_return);
7431 END_PROFILE(Trans2_get_dfs_referral);
7435 case TRANSACT2_IOCTL:
7437 START_PROFILE(Trans2_ioctl);
7438 call_trans2ioctl(conn, req,
7439 &state->param, state->total_param,
7440 &state->data, state->total_data,
7441 state->max_data_return);
7442 END_PROFILE(Trans2_ioctl);
7447 /* Error in request */
7448 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7449 reply_doserror(req, ERRSRV,ERRerror);
7453 /****************************************************************************
7454 Reply to a SMBtrans2.
7455 ****************************************************************************/
7457 void reply_trans2(struct smb_request *req)
7459 connection_struct *conn = req->conn;
7464 unsigned int tran_call;
7466 struct trans_state *state;
7469 START_PROFILE(SMBtrans2);
7471 if (req->wct < 14) {
7472 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7473 END_PROFILE(SMBtrans2);
7477 dsoff = SVAL(req->inbuf, smb_dsoff);
7478 dscnt = SVAL(req->inbuf, smb_dscnt);
7479 psoff = SVAL(req->inbuf, smb_psoff);
7480 pscnt = SVAL(req->inbuf, smb_pscnt);
7481 tran_call = SVAL(req->inbuf, smb_setup0);
7482 size = smb_len(req->inbuf) + 4;
7484 result = allow_new_trans(conn->pending_trans, req->mid);
7485 if (!NT_STATUS_IS_OK(result)) {
7486 DEBUG(2, ("Got invalid trans2 request: %s\n",
7487 nt_errstr(result)));
7488 reply_nterror(req, result);
7489 END_PROFILE(SMBtrans2);
7494 switch (tran_call) {
7495 /* List the allowed trans2 calls on IPC$ */
7496 case TRANSACT2_OPEN:
7497 case TRANSACT2_GET_DFS_REFERRAL:
7498 case TRANSACT2_QFILEINFO:
7499 case TRANSACT2_QFSINFO:
7500 case TRANSACT2_SETFSINFO:
7503 reply_doserror(req, ERRSRV, ERRaccess);
7504 END_PROFILE(SMBtrans2);
7509 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
7510 DEBUG(0, ("talloc failed\n"));
7511 reply_nterror(req, NT_STATUS_NO_MEMORY);
7512 END_PROFILE(SMBtrans2);
7516 state->cmd = SMBtrans2;
7518 state->mid = req->mid;
7519 state->vuid = req->vuid;
7520 state->setup_count = SVAL(req->inbuf, smb_suwcnt);
7521 state->setup = NULL;
7522 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7523 state->param = NULL;
7524 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7526 state->max_param_return = SVAL(req->inbuf, smb_mprcnt);
7527 state->max_data_return = SVAL(req->inbuf, smb_mdrcnt);
7528 state->max_setup_return = SVAL(req->inbuf, smb_msrcnt);
7529 state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0);
7530 state->one_way = BITSETW(req->inbuf+smb_vwv5,1);
7532 state->call = tran_call;
7534 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7535 is so as a sanity check */
7536 if (state->setup_count != 1) {
7538 * Need to have rc=0 for ioctl to get job id for OS/2.
7539 * Network printing will fail if function is not successful.
7540 * Similar function in reply.c will be used if protocol
7541 * is LANMAN1.0 instead of LM1.2X002.
7542 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7543 * outbuf doesn't have to be set(only job id is used).
7545 if ( (state->setup_count == 4)
7546 && (tran_call == TRANSACT2_IOCTL)
7547 && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7548 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7549 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7551 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7552 DEBUG(2,("Transaction is %d\n",tran_call));
7554 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7555 END_PROFILE(SMBtrans2);
7560 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7563 if (state->total_data) {
7564 /* Can't use talloc here, the core routines do realloc on the
7565 * params and data. */
7566 state->data = (char *)SMB_MALLOC(state->total_data);
7567 if (state->data == NULL) {
7568 DEBUG(0,("reply_trans2: data malloc fail for %u "
7569 "bytes !\n", (unsigned int)state->total_data));
7571 reply_nterror(req, NT_STATUS_NO_MEMORY);
7572 END_PROFILE(SMBtrans2);
7575 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
7577 if ((smb_base(req->inbuf)+dsoff+dscnt
7578 > (char *)req->inbuf + size) ||
7579 (smb_base(req->inbuf)+dsoff+dscnt < smb_base(req->inbuf)))
7582 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7585 if (state->total_param) {
7586 /* Can't use talloc here, the core routines do realloc on the
7587 * params and data. */
7588 state->param = (char *)SMB_MALLOC(state->total_param);
7589 if (state->param == NULL) {
7590 DEBUG(0,("reply_trans: param malloc fail for %u "
7591 "bytes !\n", (unsigned int)state->total_param));
7592 SAFE_FREE(state->data);
7594 reply_nterror(req, NT_STATUS_NO_MEMORY);
7595 END_PROFILE(SMBtrans2);
7598 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
7600 if ((smb_base(req->inbuf)+psoff+pscnt
7601 > (char *)req->inbuf + size) ||
7602 (smb_base(req->inbuf)+psoff+pscnt < smb_base(req->inbuf)))
7605 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7608 state->received_data = dscnt;
7609 state->received_param = pscnt;
7611 if ((state->received_param == state->total_param) &&
7612 (state->received_data == state->total_data)) {
7614 handle_trans2(conn, req, state);
7616 SAFE_FREE(state->data);
7617 SAFE_FREE(state->param);
7619 END_PROFILE(SMBtrans2);
7623 DLIST_ADD(conn->pending_trans, state);
7625 /* We need to send an interim response then receive the rest
7626 of the parameter/data bytes */
7627 reply_outbuf(req, 0, 0);
7628 show_msg((char *)req->outbuf);
7629 END_PROFILE(SMBtrans2);
7634 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7635 SAFE_FREE(state->data);
7636 SAFE_FREE(state->param);
7638 END_PROFILE(SMBtrans2);
7639 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7643 /****************************************************************************
7644 Reply to a SMBtranss2
7645 ****************************************************************************/
7647 void reply_transs2(struct smb_request *req)
7649 connection_struct *conn = req->conn;
7650 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7651 struct trans_state *state;
7654 START_PROFILE(SMBtranss2);
7656 show_msg((char *)req->inbuf);
7659 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7660 END_PROFILE(SMBtranss2);
7664 size = smb_len(req->inbuf)+4;
7666 for (state = conn->pending_trans; state != NULL;
7667 state = state->next) {
7668 if (state->mid == req->mid) {
7673 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7674 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7675 END_PROFILE(SMBtranss2);
7679 /* Revise state->total_param and state->total_data in case they have
7680 changed downwards */
7682 if (SVAL(req->inbuf, smb_tpscnt) < state->total_param)
7683 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7684 if (SVAL(req->inbuf, smb_tdscnt) < state->total_data)
7685 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7687 pcnt = SVAL(req->inbuf, smb_spscnt);
7688 poff = SVAL(req->inbuf, smb_spsoff);
7689 pdisp = SVAL(req->inbuf, smb_spsdisp);
7691 dcnt = SVAL(req->inbuf, smb_sdscnt);
7692 doff = SVAL(req->inbuf, smb_sdsoff);
7693 ddisp = SVAL(req->inbuf, smb_sdsdisp);
7695 state->received_param += pcnt;
7696 state->received_data += dcnt;
7698 if ((state->received_data > state->total_data) ||
7699 (state->received_param > state->total_param))
7703 if (pdisp+pcnt > state->total_param)
7705 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
7707 if (pdisp > state->total_param)
7709 if ((smb_base(req->inbuf) + poff + pcnt
7710 > (char *)req->inbuf + size) ||
7711 (smb_base(req->inbuf) + poff + pcnt < smb_base(req->inbuf)))
7713 if (state->param + pdisp < state->param)
7716 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,
7721 if (ddisp+dcnt > state->total_data)
7723 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
7725 if (ddisp > state->total_data)
7727 if ((smb_base(req->inbuf) + doff + dcnt
7728 > (char *)req->inbuf + size) ||
7729 (smb_base(req->inbuf) + doff + dcnt < smb_base(req->inbuf)))
7731 if (state->data + ddisp < state->data)
7734 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
7738 if ((state->received_param < state->total_param) ||
7739 (state->received_data < state->total_data)) {
7740 END_PROFILE(SMBtranss2);
7745 * construct_reply_common will copy smb_com from inbuf to
7746 * outbuf. SMBtranss2 is wrong here.
7748 SCVAL(req->inbuf,smb_com,SMBtrans2);
7750 handle_trans2(conn, req, state);
7752 DLIST_REMOVE(conn->pending_trans, state);
7753 SAFE_FREE(state->data);
7754 SAFE_FREE(state->param);
7757 END_PROFILE(SMBtranss2);
7762 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7763 DLIST_REMOVE(conn->pending_trans, state);
7764 SAFE_FREE(state->data);
7765 SAFE_FREE(state->param);
7767 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7768 END_PROFILE(SMBtranss2);