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/>.
27 #include "smbd/globals.h"
29 extern enum protocol_types Protocol;
31 #define get_file_size(sbuf) ((sbuf).st_size)
32 #define DIR_ENTRY_SAFETY_MARGIN 4096
34 static char *store_file_unix_basic(connection_struct *conn,
37 const SMB_STRUCT_STAT *psbuf);
39 static char *store_file_unix_basic_info2(connection_struct *conn,
42 const SMB_STRUCT_STAT *psbuf);
44 /********************************************************************
45 Roundup a value to the nearest allocation roundup size boundary.
46 Only do this for Windows clients.
47 ********************************************************************/
49 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
51 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
53 /* Only roundup for Windows clients. */
54 enum remote_arch_types ra_type = get_remote_arch();
55 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
56 val = SMB_ROUNDUP(val,rval);
61 /********************************************************************
62 Given a stat buffer return the allocated size on disk, taking into
64 ********************************************************************/
66 uint64_t get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
70 if(S_ISDIR(sbuf->st_mode)) {
74 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
75 ret = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_blocks;
77 ret = (uint64_t)get_file_size(*sbuf);
80 if (fsp && fsp->initial_allocation_size)
81 ret = MAX(ret,fsp->initial_allocation_size);
83 return smb_roundup(conn, ret);
86 /****************************************************************************
87 Utility functions for dealing with extended attributes.
88 ****************************************************************************/
90 /****************************************************************************
91 Refuse to allow clients to overwrite our private xattrs.
92 ****************************************************************************/
94 static bool samba_private_attr_name(const char *unix_ea_name)
96 static const char * const prohibited_ea_names[] = {
97 SAMBA_POSIX_INHERITANCE_EA_NAME,
98 SAMBA_XATTR_DOS_ATTRIB,
104 for (i = 0; prohibited_ea_names[i]; i++) {
105 if (strequal( prohibited_ea_names[i], unix_ea_name))
108 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
109 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
115 /****************************************************************************
116 Get one EA value. Fill in a struct ea_struct.
117 ****************************************************************************/
119 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
120 files_struct *fsp, const char *fname,
121 const char *ea_name, struct ea_struct *pea)
123 /* Get the value of this xattr. Max size is 64k. */
124 size_t attr_size = 256;
130 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
132 return NT_STATUS_NO_MEMORY;
135 if (fsp && fsp->fh->fd != -1) {
136 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
138 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
141 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
147 return map_nt_error_from_unix(errno);
150 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
151 dump_data(10, (uint8 *)val, sizeret);
154 if (strnequal(ea_name, "user.", 5)) {
155 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
157 pea->name = talloc_strdup(mem_ctx, ea_name);
159 if (pea->name == NULL) {
161 return NT_STATUS_NO_MEMORY;
163 pea->value.data = (unsigned char *)val;
164 pea->value.length = (size_t)sizeret;
168 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
169 files_struct *fsp, const char *fname,
170 char ***pnames, size_t *pnum_names)
172 /* Get a list of all xattrs. Max namesize is 64k. */
173 size_t ea_namelist_size = 1024;
174 char *ea_namelist = NULL;
179 ssize_t sizeret = -1;
181 if (!lp_ea_support(SNUM(conn))) {
188 * TALLOC the result early to get the talloc hierarchy right.
191 names = TALLOC_ARRAY(mem_ctx, char *, 1);
193 DEBUG(0, ("talloc failed\n"));
194 return NT_STATUS_NO_MEMORY;
197 while (ea_namelist_size <= 65536) {
199 ea_namelist = TALLOC_REALLOC_ARRAY(
200 names, ea_namelist, char, ea_namelist_size);
201 if (ea_namelist == NULL) {
202 DEBUG(0, ("talloc failed\n"));
204 return NT_STATUS_NO_MEMORY;
207 if (fsp && fsp->fh->fd != -1) {
208 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
211 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
215 if ((sizeret == -1) && (errno == ERANGE)) {
216 ea_namelist_size *= 2;
225 return map_nt_error_from_unix(errno);
228 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
229 (unsigned int)sizeret));
239 * Ensure the result is 0-terminated
242 if (ea_namelist[sizeret-1] != '\0') {
244 return NT_STATUS_INTERNAL_ERROR;
252 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
256 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
258 DEBUG(0, ("talloc failed\n"));
260 return NT_STATUS_NO_MEMORY;
266 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
267 names[num_names++] = p;
271 *pnum_names = num_names;
275 /****************************************************************************
276 Return a linked list of the total EA's. Plus the total size
277 ****************************************************************************/
279 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
280 const char *fname, size_t *pea_total_len)
282 /* Get a list of all xattrs. Max namesize is 64k. */
285 struct ea_list *ea_list_head = NULL;
290 if (!lp_ea_support(SNUM(conn))) {
294 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
297 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
301 for (i=0; i<num_names; i++) {
302 struct ea_list *listp;
305 if (strnequal(names[i], "system.", 7)
306 || samba_private_attr_name(names[i]))
309 listp = TALLOC_P(mem_ctx, struct ea_list);
314 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
320 push_ascii_fstring(dos_ea_name, listp->ea.name);
323 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
325 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
326 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
327 (unsigned int)listp->ea.value.length));
329 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
333 /* Add on 4 for total length. */
334 if (*pea_total_len) {
338 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
339 (unsigned int)*pea_total_len));
344 /****************************************************************************
345 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
347 ****************************************************************************/
349 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
350 connection_struct *conn, struct ea_list *ea_list)
352 unsigned int ret_data_size = 4;
355 SMB_ASSERT(total_data_size >= 4);
357 if (!lp_ea_support(SNUM(conn))) {
362 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
365 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
366 dos_namelen = strlen(dos_ea_name);
367 if (dos_namelen > 255 || dos_namelen == 0) {
370 if (ea_list->ea.value.length > 65535) {
373 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
377 /* We know we have room. */
378 SCVAL(p,0,ea_list->ea.flags);
379 SCVAL(p,1,dos_namelen);
380 SSVAL(p,2,ea_list->ea.value.length);
381 fstrcpy(p+4, dos_ea_name);
382 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
384 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
385 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
388 ret_data_size = PTR_DIFF(p, pdata);
389 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
390 SIVAL(pdata,0,ret_data_size);
391 return ret_data_size;
394 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
396 size_t total_ea_len = 0;
397 TALLOC_CTX *mem_ctx = NULL;
399 if (!lp_ea_support(SNUM(conn))) {
402 mem_ctx = talloc_tos();
403 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
407 /****************************************************************************
408 Ensure the EA name is case insensitive by matching any existing EA name.
409 ****************************************************************************/
411 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
414 TALLOC_CTX *mem_ctx = talloc_tos();
415 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
417 for (; ea_list; ea_list = ea_list->next) {
418 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
419 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
420 &unix_ea_name[5], ea_list->ea.name));
421 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
427 /****************************************************************************
428 Set or delete an extended attribute.
429 ****************************************************************************/
431 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
433 if (!lp_ea_support(SNUM(conn))) {
434 return NT_STATUS_EAS_NOT_SUPPORTED;
437 for (;ea_list; ea_list = ea_list->next) {
439 fstring unix_ea_name;
441 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
442 fstrcat(unix_ea_name, ea_list->ea.name);
444 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
446 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
448 if (samba_private_attr_name(unix_ea_name)) {
449 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
450 return NT_STATUS_ACCESS_DENIED;
453 if (ea_list->ea.value.length == 0) {
454 /* Remove the attribute. */
455 if (fsp && (fsp->fh->fd != -1)) {
456 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
457 unix_ea_name, fsp->fsp_name));
458 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
460 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
461 unix_ea_name, fname));
462 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
465 /* Removing a non existent attribute always succeeds. */
466 if (ret == -1 && errno == ENOATTR) {
467 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
473 if (fsp && (fsp->fh->fd != -1)) {
474 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
475 unix_ea_name, fsp->fsp_name));
476 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
477 ea_list->ea.value.data, ea_list->ea.value.length, 0);
479 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
480 unix_ea_name, fname));
481 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
482 ea_list->ea.value.data, ea_list->ea.value.length, 0);
488 if (errno == ENOTSUP) {
489 return NT_STATUS_EAS_NOT_SUPPORTED;
492 return map_nt_error_from_unix(errno);
498 /****************************************************************************
499 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
500 ****************************************************************************/
502 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
504 struct ea_list *ea_list_head = NULL;
505 size_t converted_size, offset = 0;
507 while (offset + 2 < data_size) {
508 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
509 unsigned int namelen = CVAL(pdata,offset);
511 offset++; /* Go past the namelen byte. */
513 /* integer wrap paranioa. */
514 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
515 (offset > data_size) || (namelen > data_size) ||
516 (offset + namelen >= data_size)) {
519 /* Ensure the name is null terminated. */
520 if (pdata[offset + namelen] != '\0') {
523 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
525 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
526 "failed: %s", strerror(errno)));
532 offset += (namelen + 1); /* Go past the name + terminating zero. */
533 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
534 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
540 /****************************************************************************
541 Read one EA list entry from the buffer.
542 ****************************************************************************/
544 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
546 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
548 unsigned int namelen;
549 size_t converted_size;
559 eal->ea.flags = CVAL(pdata,0);
560 namelen = CVAL(pdata,1);
561 val_len = SVAL(pdata,2);
563 if (4 + namelen + 1 + val_len > data_size) {
567 /* Ensure the name is null terminated. */
568 if (pdata[namelen + 4] != '\0') {
571 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
572 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
579 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
580 if (!eal->ea.value.data) {
584 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
586 /* Ensure we're null terminated just in case we print the value. */
587 eal->ea.value.data[val_len] = '\0';
588 /* But don't count the null. */
589 eal->ea.value.length--;
592 *pbytes_used = 4 + namelen + 1 + val_len;
595 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
596 dump_data(10, eal->ea.value.data, eal->ea.value.length);
601 /****************************************************************************
602 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
603 ****************************************************************************/
605 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
607 struct ea_list *ea_list_head = NULL;
609 size_t bytes_used = 0;
611 while (offset < data_size) {
612 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
618 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
619 offset += bytes_used;
625 /****************************************************************************
626 Count the total EA size needed.
627 ****************************************************************************/
629 static size_t ea_list_size(struct ea_list *ealist)
632 struct ea_list *listp;
635 for (listp = ealist; listp; listp = listp->next) {
636 push_ascii_fstring(dos_ea_name, listp->ea.name);
637 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
639 /* Add on 4 for total length. */
647 /****************************************************************************
648 Return a union of EA's from a file list and a list of names.
649 The TALLOC context for the two lists *MUST* be identical as we steal
650 memory from one list to add to another. JRA.
651 ****************************************************************************/
653 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
655 struct ea_list *nlistp, *flistp;
657 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
658 for (flistp = file_list; flistp; flistp = flistp->next) {
659 if (strequal(nlistp->ea.name, flistp->ea.name)) {
665 /* Copy the data from this entry. */
666 nlistp->ea.flags = flistp->ea.flags;
667 nlistp->ea.value = flistp->ea.value;
670 nlistp->ea.flags = 0;
671 ZERO_STRUCT(nlistp->ea.value);
675 *total_ea_len = ea_list_size(name_list);
679 /****************************************************************************
680 Send the required number of replies back.
681 We assume all fields other than the data fields are
682 set correctly for the type of call.
683 HACK ! Always assumes smb_setup field is zero.
684 ****************************************************************************/
686 void send_trans2_replies(connection_struct *conn,
687 struct smb_request *req,
694 /* As we are using a protocol > LANMAN1 then the max_send
695 variable must have been set in the sessetupX call.
696 This takes precedence over the max_xmit field in the
697 global struct. These different max_xmit variables should
698 be merged as this is now too confusing */
700 int data_to_send = datasize;
701 int params_to_send = paramsize;
703 const char *pp = params;
704 const char *pd = pdata;
705 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
706 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
707 int data_alignment_offset = 0;
708 bool overflow = False;
710 /* Modify the data_to_send and datasize and set the error if
711 we're trying to send more than max_data_bytes. We still send
712 the part of the packet(s) that fit. Strange, but needed
715 if (max_data_bytes > 0 && datasize > max_data_bytes) {
716 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
717 max_data_bytes, datasize ));
718 datasize = data_to_send = max_data_bytes;
722 /* If there genuinely are no parameters or data to send just send the empty packet */
724 if(params_to_send == 0 && data_to_send == 0) {
725 reply_outbuf(req, 10, 0);
726 show_msg((char *)req->outbuf);
730 /* When sending params and data ensure that both are nicely aligned */
731 /* Only do this alignment when there is also data to send - else
732 can cause NT redirector problems. */
734 if (((params_to_send % 4) != 0) && (data_to_send != 0))
735 data_alignment_offset = 4 - (params_to_send % 4);
737 /* Space is bufsize minus Netbios over TCP header minus SMB header */
738 /* The alignment_offset is to align the param bytes on an even byte
739 boundary. NT 4.0 Beta needs this to work correctly. */
741 useable_space = max_send - (smb_size
744 + data_alignment_offset);
746 if (useable_space < 0) {
747 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
748 "= %d!!!", useable_space));
749 exit_server_cleanly("send_trans2_replies: Not enough space");
752 while (params_to_send || data_to_send) {
753 /* Calculate whether we will totally or partially fill this packet */
755 total_sent_thistime = params_to_send + data_to_send;
757 /* We can never send more than useable_space */
759 * Note that 'useable_space' does not include the alignment offsets,
760 * but we must include the alignment offsets in the calculation of
761 * the length of the data we send over the wire, as the alignment offsets
762 * are sent here. Fix from Marc_Jacobsen@hp.com.
765 total_sent_thistime = MIN(total_sent_thistime, useable_space);
767 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
768 + data_alignment_offset);
771 * We might have SMBtrans2s in req which was transferred to
772 * the outbuf, fix that.
774 SCVAL(req->outbuf, smb_com, SMBtrans2);
776 /* Set total params and data to be sent */
777 SSVAL(req->outbuf,smb_tprcnt,paramsize);
778 SSVAL(req->outbuf,smb_tdrcnt,datasize);
780 /* Calculate how many parameters and data we can fit into
781 * this packet. Parameters get precedence
784 params_sent_thistime = MIN(params_to_send,useable_space);
785 data_sent_thistime = useable_space - params_sent_thistime;
786 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
788 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
790 /* smb_proff is the offset from the start of the SMB header to the
791 parameter bytes, however the first 4 bytes of outbuf are
792 the Netbios over TCP header. Thus use smb_base() to subtract
793 them from the calculation */
795 SSVAL(req->outbuf,smb_proff,
796 ((smb_buf(req->outbuf)+alignment_offset)
797 - smb_base(req->outbuf)));
799 if(params_sent_thistime == 0)
800 SSVAL(req->outbuf,smb_prdisp,0);
802 /* Absolute displacement of param bytes sent in this packet */
803 SSVAL(req->outbuf,smb_prdisp,pp - params);
805 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
806 if(data_sent_thistime == 0) {
807 SSVAL(req->outbuf,smb_droff,0);
808 SSVAL(req->outbuf,smb_drdisp, 0);
810 /* The offset of the data bytes is the offset of the
811 parameter bytes plus the number of parameters being sent this time */
812 SSVAL(req->outbuf, smb_droff,
813 ((smb_buf(req->outbuf)+alignment_offset)
814 - smb_base(req->outbuf))
815 + params_sent_thistime + data_alignment_offset);
816 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
819 /* Initialize the padding for alignment */
821 if (alignment_offset != 0) {
822 memset(smb_buf(req->outbuf), 0, alignment_offset);
825 /* Copy the param bytes into the packet */
827 if(params_sent_thistime) {
828 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
829 params_sent_thistime);
832 /* Copy in the data bytes */
833 if(data_sent_thistime) {
834 if (data_alignment_offset != 0) {
835 memset((smb_buf(req->outbuf)+alignment_offset+
836 params_sent_thistime), 0,
837 data_alignment_offset);
839 memcpy(smb_buf(req->outbuf)+alignment_offset
840 +params_sent_thistime+data_alignment_offset,
841 pd,data_sent_thistime);
844 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
845 params_sent_thistime, data_sent_thistime, useable_space));
846 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
847 params_to_send, data_to_send, paramsize, datasize));
850 error_packet_set((char *)req->outbuf,
851 ERRDOS,ERRbufferoverflow,
852 STATUS_BUFFER_OVERFLOW,
856 /* Send the packet */
857 show_msg((char *)req->outbuf);
858 if (!srv_send_smb(smbd_server_fd(),
860 IS_CONN_ENCRYPTED(conn)))
861 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
863 TALLOC_FREE(req->outbuf);
865 pp += params_sent_thistime;
866 pd += data_sent_thistime;
868 params_to_send -= params_sent_thistime;
869 data_to_send -= data_sent_thistime;
872 if(params_to_send < 0 || data_to_send < 0) {
873 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
874 params_to_send, data_to_send));
882 /****************************************************************************
883 Reply to a TRANSACT2_OPEN.
884 ****************************************************************************/
886 static void call_trans2open(connection_struct *conn,
887 struct smb_request *req,
888 char **pparams, int total_params,
889 char **ppdata, int total_data,
890 unsigned int max_data_bytes)
892 char *params = *pparams;
893 char *pdata = *ppdata;
898 bool return_additional_info;
909 SMB_STRUCT_STAT sbuf;
912 struct ea_list *ea_list = NULL;
917 uint32 create_disposition;
918 uint32 create_options = 0;
919 TALLOC_CTX *ctx = talloc_tos();
922 * Ensure we have enough parameters to perform the operation.
925 if (total_params < 29) {
926 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
930 flags = SVAL(params, 0);
931 deny_mode = SVAL(params, 2);
932 open_attr = SVAL(params,6);
933 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
934 if (oplock_request) {
935 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
939 return_additional_info = BITSETW(params,0);
940 open_sattr = SVAL(params, 4);
941 open_time = make_unix_date3(params+8);
943 open_ofun = SVAL(params,12);
944 open_size = IVAL(params,14);
948 reply_doserror(req, ERRSRV, ERRaccess);
952 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
953 total_params - 28, STR_TERMINATE,
955 if (!NT_STATUS_IS_OK(status)) {
956 reply_nterror(req, status);
960 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
961 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
962 (unsigned int)open_ofun, open_size));
964 if (open_ofun == 0) {
965 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
969 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
974 reply_doserror(req, ERRDOS, ERRbadaccess);
978 /* Any data in this call is an EA list. */
979 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
980 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
984 if (total_data != 4) {
985 if (total_data < 10) {
986 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
990 if (IVAL(pdata,0) > total_data) {
991 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
992 IVAL(pdata,0), (unsigned int)total_data));
993 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
997 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1000 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1003 } else if (IVAL(pdata,0) != 4) {
1004 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1008 status = SMB_VFS_CREATE_FILE(
1011 0, /* root_dir_fid */
1013 CFF_DOS_PATH, /* create_file_flags */
1014 access_mask, /* access_mask */
1015 share_mode, /* share_access */
1016 create_disposition, /* create_disposition*/
1017 create_options, /* create_options */
1018 open_attr, /* file_attributes */
1019 oplock_request, /* oplock_request */
1020 open_size, /* allocation_size */
1022 ea_list, /* ea_list */
1024 &smb_action, /* pinfo */
1027 if (!NT_STATUS_IS_OK(status)) {
1028 if (open_was_deferred(req->mid)) {
1029 /* We have re-scheduled this call. */
1032 reply_openerror(req, status);
1036 size = get_file_size(sbuf);
1037 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1038 mtime = sbuf.st_mtime;
1039 inode = sbuf.st_ino;
1041 close_file(req, fsp, ERROR_CLOSE);
1042 reply_doserror(req, ERRDOS,ERRnoaccess);
1046 /* Realloc the size of parameters and data we will return */
1047 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1048 if(*pparams == NULL ) {
1049 reply_nterror(req, NT_STATUS_NO_MEMORY);
1054 SSVAL(params,0,fsp->fnum);
1055 SSVAL(params,2,fattr);
1056 srv_put_dos_date2(params,4, mtime);
1057 SIVAL(params,8, (uint32)size);
1058 SSVAL(params,12,deny_mode);
1059 SSVAL(params,14,0); /* open_type - file or directory. */
1060 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1062 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1063 smb_action |= EXTENDED_OPLOCK_GRANTED;
1066 SSVAL(params,18,smb_action);
1069 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1071 SIVAL(params,20,inode);
1072 SSVAL(params,24,0); /* Padding. */
1074 uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
1075 SIVAL(params, 26, ea_size);
1077 SIVAL(params, 26, 0);
1080 /* Send the required number of replies */
1081 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1084 /*********************************************************
1085 Routine to check if a given string matches exactly.
1086 as a special case a mask of "." does NOT match. That
1087 is required for correct wildcard semantics
1088 Case can be significant or not.
1089 **********************************************************/
1091 static bool exact_match(connection_struct *conn,
1095 if (mask[0] == '.' && mask[1] == 0)
1097 if (dptr_has_wild(conn->dirptr)) {
1100 if (conn->case_sensitive)
1101 return strcmp(str,mask)==0;
1103 return StrCaseCmp(str,mask) == 0;
1106 /****************************************************************************
1107 Return the filetype for UNIX extensions.
1108 ****************************************************************************/
1110 static uint32 unix_filetype(mode_t mode)
1113 return UNIX_TYPE_FILE;
1114 else if(S_ISDIR(mode))
1115 return UNIX_TYPE_DIR;
1117 else if(S_ISLNK(mode))
1118 return UNIX_TYPE_SYMLINK;
1121 else if(S_ISCHR(mode))
1122 return UNIX_TYPE_CHARDEV;
1125 else if(S_ISBLK(mode))
1126 return UNIX_TYPE_BLKDEV;
1129 else if(S_ISFIFO(mode))
1130 return UNIX_TYPE_FIFO;
1133 else if(S_ISSOCK(mode))
1134 return UNIX_TYPE_SOCKET;
1137 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1138 return UNIX_TYPE_UNKNOWN;
1141 /****************************************************************************
1142 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1143 ****************************************************************************/
1145 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1147 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1148 SMB_STRUCT_STAT *psbuf,
1150 enum perm_type ptype,
1155 if (perms == SMB_MODE_NO_CHANGE) {
1156 if (!VALID_STAT(*psbuf)) {
1157 return NT_STATUS_INVALID_PARAMETER;
1159 *ret_perms = psbuf->st_mode;
1160 return NT_STATUS_OK;
1164 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1165 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1166 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1167 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1168 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1169 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1170 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1171 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1172 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1174 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1177 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1180 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1185 /* Apply mode mask */
1186 ret &= lp_create_mask(SNUM(conn));
1187 /* Add in force bits */
1188 ret |= lp_force_create_mode(SNUM(conn));
1191 ret &= lp_dir_mask(SNUM(conn));
1192 /* Add in force bits */
1193 ret |= lp_force_dir_mode(SNUM(conn));
1195 case PERM_EXISTING_FILE:
1196 /* Apply mode mask */
1197 ret &= lp_security_mask(SNUM(conn));
1198 /* Add in force bits */
1199 ret |= lp_force_security_mode(SNUM(conn));
1201 case PERM_EXISTING_DIR:
1202 /* Apply mode mask */
1203 ret &= lp_dir_security_mask(SNUM(conn));
1204 /* Add in force bits */
1205 ret |= lp_force_dir_security_mode(SNUM(conn));
1210 return NT_STATUS_OK;
1213 /****************************************************************************
1214 Needed to show the msdfs symlinks as directories. Modifies psbuf
1215 to be a directory if it's a msdfs link.
1216 ****************************************************************************/
1218 static bool check_msdfs_link(connection_struct *conn,
1219 const char *pathname,
1220 SMB_STRUCT_STAT *psbuf)
1222 int saved_errno = errno;
1223 if(lp_host_msdfs() &&
1224 lp_msdfs_root(SNUM(conn)) &&
1225 is_msdfs_link(conn, pathname, psbuf)) {
1227 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1230 psbuf->st_mode = (psbuf->st_mode & 0xFFF) | S_IFDIR;
1231 errno = saved_errno;
1234 errno = saved_errno;
1239 /****************************************************************************
1240 Get a level dependent lanman2 dir entry.
1241 ****************************************************************************/
1243 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1244 connection_struct *conn,
1246 const char *path_mask,
1249 int requires_resume_key,
1255 int space_remaining,
1257 bool *got_exact_match,
1258 int *last_entry_off,
1259 struct ea_list *name_list)
1263 SMB_STRUCT_STAT sbuf;
1264 const char *mask = NULL;
1265 char *pathreal = NULL;
1266 const char *fname = NULL;
1267 char *p, *q, *pdata = *ppdata;
1271 SMB_OFF_T file_size = 0;
1272 uint64_t allocation_size = 0;
1274 struct timespec mdate_ts, adate_ts, create_date_ts;
1275 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1277 char *last_entry_ptr;
1279 uint32 nt_extmode; /* Used for NT connections instead of mode */
1280 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1281 bool check_mangled_names = lp_manglednames(conn->params);
1282 char mangled_name[13]; /* mangled 8.3 name. */
1284 *out_of_space = False;
1285 *got_exact_match = False;
1287 ZERO_STRUCT(mdate_ts);
1288 ZERO_STRUCT(adate_ts);
1289 ZERO_STRUCT(create_date_ts);
1291 if (!conn->dirptr) {
1295 p = strrchr_m(path_mask,'/');
1298 mask = talloc_strdup(ctx,"*.*");
1308 bool ms_dfs_link = False;
1310 /* Needed if we run out of space */
1311 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1312 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1315 * Due to bugs in NT client redirectors we are not using
1316 * resume keys any more - set them to zero.
1317 * Check out the related comments in findfirst/findnext.
1323 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1324 (long)conn->dirptr,curr_dirpos));
1331 * fname may get mangled, dname is never mangled.
1332 * Whenever we're accessing the filesystem we use
1333 * pathreal which is composed from dname.
1339 /* Mangle fname if it's an illegal name. */
1340 if (mangle_must_mangle(dname,conn->params)) {
1341 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1342 continue; /* Error - couldn't mangle. */
1344 fname = mangled_name;
1347 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1348 got_match = mask_match(fname, mask, conn->case_sensitive);
1351 if(!got_match && check_mangled_names &&
1352 !mangle_is_8_3(fname, False, conn->params)) {
1354 * It turns out that NT matches wildcards against
1355 * both long *and* short names. This may explain some
1356 * of the wildcard wierdness from old DOS clients
1357 * that some people have been seeing.... JRA.
1359 /* Force the mangling into 8.3. */
1360 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1361 continue; /* Error - couldn't mangle. */
1364 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1365 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1370 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1372 if (dont_descend && !isdots) {
1378 pathreal = talloc_asprintf(ctx,
1383 pathreal = talloc_asprintf(ctx,
1393 if (INFO_LEVEL_IS_UNIX(info_level)) {
1394 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1395 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1396 pathreal,strerror(errno)));
1397 TALLOC_FREE(pathreal);
1400 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1401 /* Needed to show the msdfs symlinks as
1404 ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
1406 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1407 pathreal,strerror(errno)));
1408 TALLOC_FREE(pathreal);
1414 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1416 mode = dos_mode(conn,pathreal,&sbuf);
1419 if (!dir_check_ftype(conn,mode,dirtype)) {
1420 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1421 TALLOC_FREE(pathreal);
1425 if (!(mode & aDIR)) {
1426 file_size = get_file_size(sbuf);
1428 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1430 mdate_ts = get_mtimespec(&sbuf);
1431 adate_ts = get_atimespec(&sbuf);
1432 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1434 if (ask_sharemode) {
1435 struct timespec write_time_ts;
1436 struct file_id fileid;
1438 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
1439 get_file_infos(fileid, NULL, &write_time_ts);
1440 if (!null_timespec(write_time_ts)) {
1441 mdate_ts = write_time_ts;
1445 if (lp_dos_filetime_resolution(SNUM(conn))) {
1446 dos_filetime_timespec(&create_date_ts);
1447 dos_filetime_timespec(&mdate_ts);
1448 dos_filetime_timespec(&adate_ts);
1451 create_date = convert_timespec_to_time_t(create_date_ts);
1452 mdate = convert_timespec_to_time_t(mdate_ts);
1453 adate = convert_timespec_to_time_t(adate_ts);
1455 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1459 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1466 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1468 switch (info_level) {
1469 case SMB_FIND_INFO_STANDARD:
1470 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1471 if(requires_resume_key) {
1475 srv_put_dos_date2(p,0,create_date);
1476 srv_put_dos_date2(p,4,adate);
1477 srv_put_dos_date2(p,8,mdate);
1478 SIVAL(p,12,(uint32)file_size);
1479 SIVAL(p,16,(uint32)allocation_size);
1483 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1484 p += ucs2_align(base_data, p, 0);
1486 len = srvstr_push(base_data, flags2, p,
1487 fname, PTR_DIFF(end_data, p),
1489 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1491 SCVAL(nameptr, -1, len - 2);
1493 SCVAL(nameptr, -1, 0);
1497 SCVAL(nameptr, -1, len - 1);
1499 SCVAL(nameptr, -1, 0);
1505 case SMB_FIND_EA_SIZE:
1506 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1507 if(requires_resume_key) {
1511 srv_put_dos_date2(p,0,create_date);
1512 srv_put_dos_date2(p,4,adate);
1513 srv_put_dos_date2(p,8,mdate);
1514 SIVAL(p,12,(uint32)file_size);
1515 SIVAL(p,16,(uint32)allocation_size);
1518 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1519 SIVAL(p,22,ea_size); /* Extended attributes */
1523 len = srvstr_push(base_data, flags2,
1524 p, fname, PTR_DIFF(end_data, p),
1525 STR_TERMINATE | STR_NOALIGN);
1526 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1539 SCVAL(nameptr,0,len);
1541 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1544 case SMB_FIND_EA_LIST:
1546 struct ea_list *file_list = NULL;
1549 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1553 if(requires_resume_key) {
1557 srv_put_dos_date2(p,0,create_date);
1558 srv_put_dos_date2(p,4,adate);
1559 srv_put_dos_date2(p,8,mdate);
1560 SIVAL(p,12,(uint32)file_size);
1561 SIVAL(p,16,(uint32)allocation_size);
1563 p += 22; /* p now points to the EA area. */
1565 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1566 name_list = ea_list_union(name_list, file_list, &ea_len);
1568 /* We need to determine if this entry will fit in the space available. */
1569 /* Max string size is 255 bytes. */
1570 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1571 /* Move the dirptr back to prev_dirpos */
1572 dptr_SeekDir(conn->dirptr, prev_dirpos);
1573 *out_of_space = True;
1574 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1575 return False; /* Not finished - just out of space */
1578 /* Push the ea_data followed by the name. */
1579 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1581 len = srvstr_push(base_data, flags2,
1582 p + 1, fname, PTR_DIFF(end_data, p+1),
1583 STR_TERMINATE | STR_NOALIGN);
1584 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1597 SCVAL(nameptr,0,len);
1599 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1603 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1604 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1605 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1607 SIVAL(p,0,reskey); p += 4;
1608 put_long_date_timespec(p,create_date_ts); p += 8;
1609 put_long_date_timespec(p,adate_ts); p += 8;
1610 put_long_date_timespec(p,mdate_ts); p += 8;
1611 put_long_date_timespec(p,mdate_ts); p += 8;
1612 SOFF_T(p,0,file_size); p += 8;
1613 SOFF_T(p,0,allocation_size); p += 8;
1614 SIVAL(p,0,nt_extmode); p += 4;
1615 q = p; p += 4; /* q is placeholder for name length. */
1617 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1618 SIVAL(p,0,ea_size); /* Extended attributes */
1621 /* Clear the short name buffer. This is
1622 * IMPORTANT as not doing so will trigger
1623 * a Win2k client bug. JRA.
1625 if (!was_8_3 && check_mangled_names) {
1626 if (!name_to_8_3(fname,mangled_name,True,
1628 /* Error - mangle failed ! */
1629 memset(mangled_name,'\0',12);
1631 mangled_name[12] = 0;
1632 len = srvstr_push(base_data, flags2,
1633 p+2, mangled_name, 24,
1634 STR_UPPER|STR_UNICODE);
1636 memset(p + 2 + len,'\0',24 - len);
1643 len = srvstr_push(base_data, flags2, p,
1644 fname, PTR_DIFF(end_data, p),
1645 STR_TERMINATE_ASCII);
1648 SIVAL(p,0,0); /* Ensure any padding is null. */
1649 len = PTR_DIFF(p, pdata);
1650 len = (len + 3) & ~3;
1655 case SMB_FIND_FILE_DIRECTORY_INFO:
1656 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1658 SIVAL(p,0,reskey); p += 4;
1659 put_long_date_timespec(p,create_date_ts); p += 8;
1660 put_long_date_timespec(p,adate_ts); p += 8;
1661 put_long_date_timespec(p,mdate_ts); p += 8;
1662 put_long_date_timespec(p,mdate_ts); p += 8;
1663 SOFF_T(p,0,file_size); p += 8;
1664 SOFF_T(p,0,allocation_size); p += 8;
1665 SIVAL(p,0,nt_extmode); p += 4;
1666 len = srvstr_push(base_data, flags2,
1667 p + 4, fname, PTR_DIFF(end_data, p+4),
1668 STR_TERMINATE_ASCII);
1671 SIVAL(p,0,0); /* Ensure any padding is null. */
1672 len = PTR_DIFF(p, pdata);
1673 len = (len + 3) & ~3;
1678 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1679 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1681 SIVAL(p,0,reskey); p += 4;
1682 put_long_date_timespec(p,create_date_ts); p += 8;
1683 put_long_date_timespec(p,adate_ts); p += 8;
1684 put_long_date_timespec(p,mdate_ts); p += 8;
1685 put_long_date_timespec(p,mdate_ts); p += 8;
1686 SOFF_T(p,0,file_size); p += 8;
1687 SOFF_T(p,0,allocation_size); p += 8;
1688 SIVAL(p,0,nt_extmode); p += 4;
1689 q = p; p += 4; /* q is placeholder for name length. */
1691 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1692 SIVAL(p,0,ea_size); /* Extended attributes */
1695 len = srvstr_push(base_data, flags2, p,
1696 fname, PTR_DIFF(end_data, p),
1697 STR_TERMINATE_ASCII);
1701 SIVAL(p,0,0); /* Ensure any padding is null. */
1702 len = PTR_DIFF(p, pdata);
1703 len = (len + 3) & ~3;
1708 case SMB_FIND_FILE_NAMES_INFO:
1709 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1711 SIVAL(p,0,reskey); p += 4;
1713 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1714 acl on a dir (tridge) */
1715 len = srvstr_push(base_data, flags2, p,
1716 fname, PTR_DIFF(end_data, p),
1717 STR_TERMINATE_ASCII);
1720 SIVAL(p,0,0); /* Ensure any padding is null. */
1721 len = PTR_DIFF(p, pdata);
1722 len = (len + 3) & ~3;
1727 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1728 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1730 SIVAL(p,0,reskey); p += 4;
1731 put_long_date_timespec(p,create_date_ts); p += 8;
1732 put_long_date_timespec(p,adate_ts); p += 8;
1733 put_long_date_timespec(p,mdate_ts); p += 8;
1734 put_long_date_timespec(p,mdate_ts); p += 8;
1735 SOFF_T(p,0,file_size); p += 8;
1736 SOFF_T(p,0,allocation_size); p += 8;
1737 SIVAL(p,0,nt_extmode); p += 4;
1738 q = p; p += 4; /* q is placeholder for name length. */
1740 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1741 SIVAL(p,0,ea_size); /* Extended attributes */
1744 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1745 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1746 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1747 len = srvstr_push(base_data, flags2, p,
1748 fname, PTR_DIFF(end_data, p),
1749 STR_TERMINATE_ASCII);
1752 SIVAL(p,0,0); /* Ensure any padding is null. */
1753 len = PTR_DIFF(p, pdata);
1754 len = (len + 3) & ~3;
1759 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1760 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1761 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1763 SIVAL(p,0,reskey); p += 4;
1764 put_long_date_timespec(p,create_date_ts); p += 8;
1765 put_long_date_timespec(p,adate_ts); p += 8;
1766 put_long_date_timespec(p,mdate_ts); p += 8;
1767 put_long_date_timespec(p,mdate_ts); p += 8;
1768 SOFF_T(p,0,file_size); p += 8;
1769 SOFF_T(p,0,allocation_size); p += 8;
1770 SIVAL(p,0,nt_extmode); p += 4;
1771 q = p; p += 4; /* q is placeholder for name length */
1773 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1774 SIVAL(p,0,ea_size); /* Extended attributes */
1777 /* Clear the short name buffer. This is
1778 * IMPORTANT as not doing so will trigger
1779 * a Win2k client bug. JRA.
1781 if (!was_8_3 && check_mangled_names) {
1782 if (!name_to_8_3(fname,mangled_name,True,
1784 /* Error - mangle failed ! */
1785 memset(mangled_name,'\0',12);
1787 mangled_name[12] = 0;
1788 len = srvstr_push(base_data, flags2,
1789 p+2, mangled_name, 24,
1790 STR_UPPER|STR_UNICODE);
1793 memset(p + 2 + len,'\0',24 - len);
1800 SSVAL(p,0,0); p += 2; /* Reserved ? */
1801 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1802 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1803 len = srvstr_push(base_data, flags2, p,
1804 fname, PTR_DIFF(end_data, p),
1805 STR_TERMINATE_ASCII);
1808 SIVAL(p,0,0); /* Ensure any padding is null. */
1809 len = PTR_DIFF(p, pdata);
1810 len = (len + 3) & ~3;
1815 /* CIFS UNIX Extension. */
1817 case SMB_FIND_FILE_UNIX:
1818 case SMB_FIND_FILE_UNIX_INFO2:
1820 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1822 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1824 if (info_level == SMB_FIND_FILE_UNIX) {
1825 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1826 p = store_file_unix_basic(conn, p,
1828 len = srvstr_push(base_data, flags2, p,
1829 fname, PTR_DIFF(end_data, p),
1832 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1833 p = store_file_unix_basic_info2(conn, p,
1837 len = srvstr_push(base_data, flags2, p, fname,
1838 PTR_DIFF(end_data, p), 0);
1839 SIVAL(nameptr, 0, len);
1843 SIVAL(p,0,0); /* Ensure any padding is null. */
1845 len = PTR_DIFF(p, pdata);
1846 len = (len + 3) & ~3;
1847 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1849 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1858 if (PTR_DIFF(p,pdata) > space_remaining) {
1859 /* Move the dirptr back to prev_dirpos */
1860 dptr_SeekDir(conn->dirptr, prev_dirpos);
1861 *out_of_space = True;
1862 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1863 return False; /* Not finished - just out of space */
1866 /* Setup the last entry pointer, as an offset from base_data */
1867 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1868 /* Advance the data pointer to the next slot */
1874 /****************************************************************************
1875 Reply to a TRANS2_FINDFIRST.
1876 ****************************************************************************/
1878 static void call_trans2findfirst(connection_struct *conn,
1879 struct smb_request *req,
1880 char **pparams, int total_params,
1881 char **ppdata, int total_data,
1882 unsigned int max_data_bytes)
1884 /* We must be careful here that we don't return more than the
1885 allowed number of data bytes. If this means returning fewer than
1886 maxentries then so be it. We assume that the redirector has
1887 enough room for the fixed number of parameter bytes it has
1889 char *params = *pparams;
1890 char *pdata = *ppdata;
1894 uint16 findfirst_flags;
1895 bool close_after_first;
1897 bool requires_resume_key;
1899 char *directory = NULL;
1902 int last_entry_off=0;
1906 bool finished = False;
1907 bool dont_descend = False;
1908 bool out_of_space = False;
1909 int space_remaining;
1910 bool mask_contains_wcard = False;
1911 SMB_STRUCT_STAT sbuf;
1912 struct ea_list *ea_list = NULL;
1913 NTSTATUS ntstatus = NT_STATUS_OK;
1914 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1915 TALLOC_CTX *ctx = talloc_tos();
1917 if (total_params < 13) {
1918 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1922 dirtype = SVAL(params,0);
1923 maxentries = SVAL(params,2);
1924 findfirst_flags = SVAL(params,4);
1925 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1926 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1927 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1928 info_level = SVAL(params,6);
1930 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1931 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1932 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1933 info_level, max_data_bytes));
1936 /* W2K3 seems to treat zero as 1. */
1940 switch (info_level) {
1941 case SMB_FIND_INFO_STANDARD:
1942 case SMB_FIND_EA_SIZE:
1943 case SMB_FIND_EA_LIST:
1944 case SMB_FIND_FILE_DIRECTORY_INFO:
1945 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1946 case SMB_FIND_FILE_NAMES_INFO:
1947 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1948 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1949 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1951 case SMB_FIND_FILE_UNIX:
1952 case SMB_FIND_FILE_UNIX_INFO2:
1953 /* Always use filesystem for UNIX mtime query. */
1954 ask_sharemode = false;
1955 if (!lp_unix_extensions()) {
1956 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1961 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1965 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1966 params+12, total_params - 12,
1967 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1968 if (!NT_STATUS_IS_OK(ntstatus)) {
1969 reply_nterror(req, ntstatus);
1973 ntstatus = resolve_dfspath_wcard(ctx, conn,
1974 req->flags2 & FLAGS2_DFS_PATHNAMES,
1977 &mask_contains_wcard);
1978 if (!NT_STATUS_IS_OK(ntstatus)) {
1979 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1980 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1981 ERRSRV, ERRbadpath);
1984 reply_nterror(req, ntstatus);
1988 ntstatus = unix_convert(ctx, conn, directory, True, &directory, &mask, &sbuf);
1989 if (!NT_STATUS_IS_OK(ntstatus)) {
1990 reply_nterror(req, ntstatus);
1994 ntstatus = check_name(conn, directory);
1995 if (!NT_STATUS_IS_OK(ntstatus)) {
1996 reply_nterror(req, ntstatus);
2000 p = strrchr_m(directory,'/');
2002 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2003 if((directory[0] == '.') && (directory[1] == '\0')) {
2004 mask = talloc_strdup(ctx,"*");
2006 reply_nterror(req, NT_STATUS_NO_MEMORY);
2009 mask_contains_wcard = True;
2011 directory = talloc_strdup(talloc_tos(), "./");
2013 reply_nterror(req, NT_STATUS_NO_MEMORY);
2020 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2022 if (info_level == SMB_FIND_EA_LIST) {
2025 if (total_data < 4) {
2026 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2030 ea_size = IVAL(pdata,0);
2031 if (ea_size != total_data) {
2032 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2033 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2034 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2038 if (!lp_ea_support(SNUM(conn))) {
2039 reply_doserror(req, ERRDOS, ERReasnotsupported);
2043 /* Pull out the list of names. */
2044 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2046 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2051 *ppdata = (char *)SMB_REALLOC(
2052 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2053 if(*ppdata == NULL ) {
2054 reply_nterror(req, NT_STATUS_NO_MEMORY);
2058 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2060 /* Realloc the params space */
2061 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2062 if (*pparams == NULL) {
2063 reply_nterror(req, NT_STATUS_NO_MEMORY);
2068 /* Save the wildcard match and attribs we are using on this directory -
2069 needed as lanman2 assumes these are being saved between calls */
2071 ntstatus = dptr_create(conn,
2077 mask_contains_wcard,
2081 if (!NT_STATUS_IS_OK(ntstatus)) {
2082 reply_nterror(req, ntstatus);
2086 dptr_num = dptr_dnum(conn->dirptr);
2087 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2089 /* We don't need to check for VOL here as this is returned by
2090 a different TRANS2 call. */
2092 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2093 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2094 dont_descend = True;
2097 space_remaining = max_data_bytes;
2098 out_of_space = False;
2100 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2101 bool got_exact_match = False;
2103 /* this is a heuristic to avoid seeking the dirptr except when
2104 absolutely necessary. It allows for a filename of about 40 chars */
2105 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2106 out_of_space = True;
2109 finished = !get_lanman2_dir_entry(ctx,
2112 mask,dirtype,info_level,
2113 requires_resume_key,dont_descend,
2116 space_remaining, &out_of_space,
2118 &last_entry_off, ea_list);
2121 if (finished && out_of_space)
2124 if (!finished && !out_of_space)
2128 * As an optimisation if we know we aren't looking
2129 * for a wildcard name (ie. the name matches the wildcard exactly)
2130 * then we can finish on any (first) match.
2131 * This speeds up large directory searches. JRA.
2137 /* Ensure space_remaining never goes -ve. */
2138 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2139 space_remaining = 0;
2140 out_of_space = true;
2142 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2146 /* Check if we can close the dirptr */
2147 if(close_after_first || (finished && close_if_end)) {
2148 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2149 dptr_close(&dptr_num);
2153 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2154 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2155 * the protocol level is less than NT1. Tested with smbclient. JRA.
2156 * This should fix the OS/2 client bug #2335.
2159 if(numentries == 0) {
2160 dptr_close(&dptr_num);
2161 if (Protocol < PROTOCOL_NT1) {
2162 reply_doserror(req, ERRDOS, ERRnofiles);
2165 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2166 ERRDOS, ERRbadfile);
2171 /* At this point pdata points to numentries directory entries. */
2173 /* Set up the return parameter block */
2174 SSVAL(params,0,dptr_num);
2175 SSVAL(params,2,numentries);
2176 SSVAL(params,4,finished);
2177 SSVAL(params,6,0); /* Never an EA error */
2178 SSVAL(params,8,last_entry_off);
2180 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2183 if ((! *directory) && dptr_path(dptr_num)) {
2184 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2186 reply_nterror(req, NT_STATUS_NO_MEMORY);
2190 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2191 smb_fn_name(req->cmd),
2192 mask, directory, dirtype, numentries ) );
2195 * Force a name mangle here to ensure that the
2196 * mask as an 8.3 name is top of the mangled cache.
2197 * The reasons for this are subtle. Don't remove
2198 * this code unless you know what you are doing
2199 * (see PR#13758). JRA.
2202 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2203 char mangled_name[13];
2204 name_to_8_3(mask, mangled_name, True, conn->params);
2210 /****************************************************************************
2211 Reply to a TRANS2_FINDNEXT.
2212 ****************************************************************************/
2214 static void call_trans2findnext(connection_struct *conn,
2215 struct smb_request *req,
2216 char **pparams, int total_params,
2217 char **ppdata, int total_data,
2218 unsigned int max_data_bytes)
2220 /* We must be careful here that we don't return more than the
2221 allowed number of data bytes. If this means returning fewer than
2222 maxentries then so be it. We assume that the redirector has
2223 enough room for the fixed number of parameter bytes it has
2225 char *params = *pparams;
2226 char *pdata = *ppdata;
2232 uint16 findnext_flags;
2233 bool close_after_request;
2235 bool requires_resume_key;
2237 bool mask_contains_wcard = False;
2238 char *resume_name = NULL;
2239 const char *mask = NULL;
2240 const char *directory = NULL;
2244 int i, last_entry_off=0;
2245 bool finished = False;
2246 bool dont_descend = False;
2247 bool out_of_space = False;
2248 int space_remaining;
2249 struct ea_list *ea_list = NULL;
2250 NTSTATUS ntstatus = NT_STATUS_OK;
2251 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2252 TALLOC_CTX *ctx = talloc_tos();
2254 if (total_params < 13) {
2255 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2259 dptr_num = SVAL(params,0);
2260 maxentries = SVAL(params,2);
2261 info_level = SVAL(params,4);
2262 resume_key = IVAL(params,6);
2263 findnext_flags = SVAL(params,10);
2264 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2265 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2266 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2267 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2269 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2271 total_params - 12, STR_TERMINATE, &ntstatus,
2272 &mask_contains_wcard);
2273 if (!NT_STATUS_IS_OK(ntstatus)) {
2274 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2275 complain (it thinks we're asking for the directory above the shared
2276 path or an invalid name). Catch this as the resume name is only compared, never used in
2277 a file access. JRA. */
2278 srvstr_pull_talloc(ctx, params, req->flags2,
2279 &resume_name, params+12,
2283 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2284 reply_nterror(req, ntstatus);
2289 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2290 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2291 resume_key = %d resume name = %s continue=%d level = %d\n",
2292 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2293 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2296 /* W2K3 seems to treat zero as 1. */
2300 switch (info_level) {
2301 case SMB_FIND_INFO_STANDARD:
2302 case SMB_FIND_EA_SIZE:
2303 case SMB_FIND_EA_LIST:
2304 case SMB_FIND_FILE_DIRECTORY_INFO:
2305 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2306 case SMB_FIND_FILE_NAMES_INFO:
2307 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2308 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2309 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2311 case SMB_FIND_FILE_UNIX:
2312 case SMB_FIND_FILE_UNIX_INFO2:
2313 /* Always use filesystem for UNIX mtime query. */
2314 ask_sharemode = false;
2315 if (!lp_unix_extensions()) {
2316 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2321 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2325 if (info_level == SMB_FIND_EA_LIST) {
2328 if (total_data < 4) {
2329 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2333 ea_size = IVAL(pdata,0);
2334 if (ea_size != total_data) {
2335 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2336 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2337 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2341 if (!lp_ea_support(SNUM(conn))) {
2342 reply_doserror(req, ERRDOS, ERReasnotsupported);
2346 /* Pull out the list of names. */
2347 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2349 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2354 *ppdata = (char *)SMB_REALLOC(
2355 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2356 if(*ppdata == NULL) {
2357 reply_nterror(req, NT_STATUS_NO_MEMORY);
2362 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2364 /* Realloc the params space */
2365 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2366 if(*pparams == NULL ) {
2367 reply_nterror(req, NT_STATUS_NO_MEMORY);
2373 /* Check that the dptr is valid */
2374 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2375 reply_doserror(req, ERRDOS, ERRnofiles);
2379 string_set(&conn->dirpath,dptr_path(dptr_num));
2381 /* Get the wildcard mask from the dptr */
2382 if((p = dptr_wcard(dptr_num))== NULL) {
2383 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2384 reply_doserror(req, ERRDOS, ERRnofiles);
2389 directory = conn->dirpath;
2391 /* Get the attr mask from the dptr */
2392 dirtype = dptr_attr(dptr_num);
2394 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2395 dptr_num, mask, dirtype,
2397 dptr_TellDir(conn->dirptr)));
2399 /* We don't need to check for VOL here as this is returned by
2400 a different TRANS2 call. */
2402 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2403 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2404 dont_descend = True;
2407 space_remaining = max_data_bytes;
2408 out_of_space = False;
2411 * Seek to the correct position. We no longer use the resume key but
2412 * depend on the last file name instead.
2415 if(*resume_name && !continue_bit) {
2418 long current_pos = 0;
2420 * Remember, name_to_8_3 is called by
2421 * get_lanman2_dir_entry(), so the resume name
2422 * could be mangled. Ensure we check the unmangled name.
2425 if (mangle_is_mangled(resume_name, conn->params)) {
2426 char *new_resume_name = NULL;
2427 mangle_lookup_name_from_8_3(ctx,
2431 if (new_resume_name) {
2432 resume_name = new_resume_name;
2437 * Fix for NT redirector problem triggered by resume key indexes
2438 * changing between directory scans. We now return a resume key of 0
2439 * and instead look for the filename to continue from (also given
2440 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2441 * findfirst/findnext (as is usual) then the directory pointer
2442 * should already be at the correct place.
2445 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2446 } /* end if resume_name && !continue_bit */
2448 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2449 bool got_exact_match = False;
2451 /* this is a heuristic to avoid seeking the dirptr except when
2452 absolutely necessary. It allows for a filename of about 40 chars */
2453 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2454 out_of_space = True;
2457 finished = !get_lanman2_dir_entry(ctx,
2460 mask,dirtype,info_level,
2461 requires_resume_key,dont_descend,
2464 space_remaining, &out_of_space,
2466 &last_entry_off, ea_list);
2469 if (finished && out_of_space)
2472 if (!finished && !out_of_space)
2476 * As an optimisation if we know we aren't looking
2477 * for a wildcard name (ie. the name matches the wildcard exactly)
2478 * then we can finish on any (first) match.
2479 * This speeds up large directory searches. JRA.
2485 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2488 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2489 smb_fn_name(req->cmd),
2490 mask, directory, dirtype, numentries ) );
2492 /* Check if we can close the dirptr */
2493 if(close_after_request || (finished && close_if_end)) {
2494 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2495 dptr_close(&dptr_num); /* This frees up the saved mask */
2498 /* Set up the return parameter block */
2499 SSVAL(params,0,numentries);
2500 SSVAL(params,2,finished);
2501 SSVAL(params,4,0); /* Never an EA error */
2502 SSVAL(params,6,last_entry_off);
2504 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2510 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2512 E_md4hash(lp_servicename(SNUM(conn)),objid);
2516 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2518 SMB_ASSERT(extended_info != NULL);
2520 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2521 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2522 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2523 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2524 #ifdef SAMBA_VERSION_REVISION
2525 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2527 extended_info->samba_subversion = 0;
2528 #ifdef SAMBA_VERSION_RC_RELEASE
2529 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2531 #ifdef SAMBA_VERSION_PRE_RELEASE
2532 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2535 #ifdef SAMBA_VERSION_VENDOR_PATCH
2536 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2538 extended_info->samba_gitcommitdate = 0;
2539 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2540 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2543 memset(extended_info->samba_version_string, 0,
2544 sizeof(extended_info->samba_version_string));
2546 snprintf (extended_info->samba_version_string,
2547 sizeof(extended_info->samba_version_string),
2548 "%s", samba_version_string());
2551 /****************************************************************************
2552 Reply to a TRANS2_QFSINFO (query filesystem info).
2553 ****************************************************************************/
2555 static void call_trans2qfsinfo(connection_struct *conn,
2556 struct smb_request *req,
2557 char **pparams, int total_params,
2558 char **ppdata, int total_data,
2559 unsigned int max_data_bytes)
2561 char *pdata, *end_data;
2562 char *params = *pparams;
2566 const char *vname = volume_label(SNUM(conn));
2567 int snum = SNUM(conn);
2568 char *fstype = lp_fstype(SNUM(conn));
2569 uint32 additional_flags = 0;
2571 if (total_params < 2) {
2572 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2576 info_level = SVAL(params,0);
2579 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2580 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2581 "info level (0x%x) on IPC$.\n",
2582 (unsigned int)info_level));
2583 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2588 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2589 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2590 DEBUG(0,("call_trans2qfsinfo: encryption required "
2591 "and info level 0x%x sent.\n",
2592 (unsigned int)info_level));
2593 exit_server_cleanly("encryption required "
2599 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2601 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2602 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2603 reply_doserror(req, ERRSRV, ERRinvdevice);
2607 *ppdata = (char *)SMB_REALLOC(
2608 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2609 if (*ppdata == NULL ) {
2610 reply_nterror(req, NT_STATUS_NO_MEMORY);
2615 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2616 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2618 switch (info_level) {
2619 case SMB_INFO_ALLOCATION:
2621 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2623 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2624 reply_unixerror(req, ERRHRD, ERRgeneral);
2628 block_size = lp_block_size(snum);
2629 if (bsize < block_size) {
2630 uint64_t factor = block_size/bsize;
2635 if (bsize > block_size) {
2636 uint64_t factor = bsize/block_size;
2641 bytes_per_sector = 512;
2642 sectors_per_unit = bsize/bytes_per_sector;
2644 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2645 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2646 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2648 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2649 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2650 SIVAL(pdata,l1_cUnit,dsize);
2651 SIVAL(pdata,l1_cUnitAvail,dfree);
2652 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2656 case SMB_INFO_VOLUME:
2657 /* Return volume name */
2659 * Add volume serial number - hash of a combination of
2660 * the called hostname and the service name.
2662 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2664 * Win2k3 and previous mess this up by sending a name length
2665 * one byte short. I believe only older clients (OS/2 Win9x) use
2666 * this call so try fixing this by adding a terminating null to
2667 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2671 pdata+l2_vol_szVolLabel, vname,
2672 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2673 STR_NOALIGN|STR_TERMINATE);
2674 SCVAL(pdata,l2_vol_cch,len);
2675 data_len = l2_vol_szVolLabel + len;
2676 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2677 (unsigned)st.st_ctime, len, vname));
2680 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2681 case SMB_FS_ATTRIBUTE_INFORMATION:
2683 additional_flags = 0;
2684 #if defined(HAVE_SYS_QUOTAS)
2685 additional_flags |= FILE_VOLUME_QUOTAS;
2688 if(lp_nt_acl_support(SNUM(conn))) {
2689 additional_flags |= FILE_PERSISTENT_ACLS;
2692 /* Capabilities are filled in at connection time through STATVFS call */
2693 additional_flags |= conn->fs_capabilities;
2695 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2696 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2697 additional_flags); /* FS ATTRIBUTES */
2699 SIVAL(pdata,4,255); /* Max filename component length */
2700 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2701 and will think we can't do long filenames */
2702 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2703 PTR_DIFF(end_data, pdata+12),
2706 data_len = 12 + len;
2709 case SMB_QUERY_FS_LABEL_INFO:
2710 case SMB_FS_LABEL_INFORMATION:
2711 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2712 PTR_DIFF(end_data, pdata+4), 0);
2717 case SMB_QUERY_FS_VOLUME_INFO:
2718 case SMB_FS_VOLUME_INFORMATION:
2721 * Add volume serial number - hash of a combination of
2722 * the called hostname and the service name.
2724 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2725 (str_checksum(get_local_machine_name())<<16));
2727 /* Max label len is 32 characters. */
2728 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2729 PTR_DIFF(end_data, pdata+18),
2731 SIVAL(pdata,12,len);
2734 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2735 (int)strlen(vname),vname, lp_servicename(snum)));
2738 case SMB_QUERY_FS_SIZE_INFO:
2739 case SMB_FS_SIZE_INFORMATION:
2741 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2743 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2744 reply_unixerror(req, ERRHRD, ERRgeneral);
2747 block_size = lp_block_size(snum);
2748 if (bsize < block_size) {
2749 uint64_t factor = block_size/bsize;
2754 if (bsize > block_size) {
2755 uint64_t factor = bsize/block_size;
2760 bytes_per_sector = 512;
2761 sectors_per_unit = bsize/bytes_per_sector;
2762 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2763 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2764 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2765 SBIG_UINT(pdata,0,dsize);
2766 SBIG_UINT(pdata,8,dfree);
2767 SIVAL(pdata,16,sectors_per_unit);
2768 SIVAL(pdata,20,bytes_per_sector);
2772 case SMB_FS_FULL_SIZE_INFORMATION:
2774 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2776 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2777 reply_unixerror(req, ERRHRD, ERRgeneral);
2780 block_size = lp_block_size(snum);
2781 if (bsize < block_size) {
2782 uint64_t factor = block_size/bsize;
2787 if (bsize > block_size) {
2788 uint64_t factor = bsize/block_size;
2793 bytes_per_sector = 512;
2794 sectors_per_unit = bsize/bytes_per_sector;
2795 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2796 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2797 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2798 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2799 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2800 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2801 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2802 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2806 case SMB_QUERY_FS_DEVICE_INFO:
2807 case SMB_FS_DEVICE_INFORMATION:
2809 SIVAL(pdata,0,0); /* dev type */
2810 SIVAL(pdata,4,0); /* characteristics */
2813 #ifdef HAVE_SYS_QUOTAS
2814 case SMB_FS_QUOTA_INFORMATION:
2816 * what we have to send --metze:
2818 * Unknown1: 24 NULL bytes
2819 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2820 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2821 * Quota Flags: 2 byte :
2822 * Unknown3: 6 NULL bytes
2826 * details for Quota Flags:
2828 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2829 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2830 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2831 * 0x0001 Enable Quotas: enable quota for this fs
2835 /* we need to fake up a fsp here,
2836 * because its not send in this call
2839 SMB_NTQUOTA_STRUCT quotas;
2842 ZERO_STRUCT(quotas);
2848 if (conn->server_info->utok.uid != 0) {
2849 DEBUG(0,("set_user_quota: access_denied "
2850 "service [%s] user [%s]\n",
2851 lp_servicename(SNUM(conn)),
2852 conn->server_info->unix_name));
2853 reply_doserror(req, ERRDOS, ERRnoaccess);
2857 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2858 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2859 reply_doserror(req, ERRSRV, ERRerror);
2865 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2867 /* Unknown1 24 NULL bytes*/
2868 SBIG_UINT(pdata,0,(uint64_t)0);
2869 SBIG_UINT(pdata,8,(uint64_t)0);
2870 SBIG_UINT(pdata,16,(uint64_t)0);
2872 /* Default Soft Quota 8 bytes */
2873 SBIG_UINT(pdata,24,quotas.softlim);
2875 /* Default Hard Quota 8 bytes */
2876 SBIG_UINT(pdata,32,quotas.hardlim);
2878 /* Quota flag 2 bytes */
2879 SSVAL(pdata,40,quotas.qflags);
2881 /* Unknown3 6 NULL bytes */
2887 #endif /* HAVE_SYS_QUOTAS */
2888 case SMB_FS_OBJECTID_INFORMATION:
2890 unsigned char objid[16];
2891 struct smb_extended_info extended_info;
2892 memcpy(pdata,create_volume_objectid(conn, objid),16);
2893 samba_extended_info_version (&extended_info);
2894 SIVAL(pdata,16,extended_info.samba_magic);
2895 SIVAL(pdata,20,extended_info.samba_version);
2896 SIVAL(pdata,24,extended_info.samba_subversion);
2897 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2898 memcpy(pdata+36,extended_info.samba_version_string,28);
2904 * Query the version and capabilities of the CIFS UNIX extensions
2908 case SMB_QUERY_CIFS_UNIX_INFO:
2910 bool large_write = lp_min_receive_file_size() &&
2911 !srv_is_signing_active();
2912 bool large_read = !srv_is_signing_active();
2913 int encrypt_caps = 0;
2915 if (!lp_unix_extensions()) {
2916 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2920 switch (conn->encrypt_level) {
2926 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2929 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2930 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2931 large_write = false;
2937 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2938 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2940 /* We have POSIX ACLs, pathname, encryption,
2941 * large read/write, and locking capability. */
2943 SBIG_UINT(pdata,4,((uint64_t)(
2944 CIFS_UNIX_POSIX_ACLS_CAP|
2945 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2946 CIFS_UNIX_FCNTL_LOCKS_CAP|
2947 CIFS_UNIX_EXTATTR_CAP|
2948 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2950 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2952 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2956 case SMB_QUERY_POSIX_FS_INFO:
2959 vfs_statvfs_struct svfs;
2961 if (!lp_unix_extensions()) {
2962 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2966 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2970 SIVAL(pdata,0,svfs.OptimalTransferSize);
2971 SIVAL(pdata,4,svfs.BlockSize);
2972 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2973 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2974 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2975 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2976 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2977 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2978 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2980 } else if (rc == EOPNOTSUPP) {
2981 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2983 #endif /* EOPNOTSUPP */
2985 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2986 reply_doserror(req, ERRSRV, ERRerror);
2992 case SMB_QUERY_POSIX_WHOAMI:
2998 if (!lp_unix_extensions()) {
2999 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3003 if (max_data_bytes < 40) {
3004 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
3008 /* We ARE guest if global_sid_Builtin_Guests is
3009 * in our list of SIDs.
3011 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3012 conn->server_info->ptok)) {
3013 flags |= SMB_WHOAMI_GUEST;
3016 /* We are NOT guest if global_sid_Authenticated_Users
3017 * is in our list of SIDs.
3019 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3020 conn->server_info->ptok)) {
3021 flags &= ~SMB_WHOAMI_GUEST;
3024 /* NOTE: 8 bytes for UID/GID, irrespective of native
3025 * platform size. This matches
3026 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3028 data_len = 4 /* flags */
3035 + 4 /* pad/reserved */
3036 + (conn->server_info->utok.ngroups * 8)
3038 + (conn->server_info->ptok->num_sids *
3042 SIVAL(pdata, 0, flags);
3043 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3045 (uint64_t)conn->server_info->utok.uid);
3046 SBIG_UINT(pdata, 16,
3047 (uint64_t)conn->server_info->utok.gid);
3050 if (data_len >= max_data_bytes) {
3051 /* Potential overflow, skip the GIDs and SIDs. */
3053 SIVAL(pdata, 24, 0); /* num_groups */
3054 SIVAL(pdata, 28, 0); /* num_sids */
3055 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3056 SIVAL(pdata, 36, 0); /* reserved */
3062 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3063 SIVAL(pdata, 28, conn->server_info->num_sids);
3065 /* We walk the SID list twice, but this call is fairly
3066 * infrequent, and I don't expect that it's performance
3067 * sensitive -- jpeach
3069 for (i = 0, sid_bytes = 0;
3070 i < conn->server_info->ptok->num_sids; ++i) {
3071 sid_bytes += ndr_size_dom_sid(
3072 &conn->server_info->ptok->user_sids[i],
3077 /* SID list byte count */
3078 SIVAL(pdata, 32, sid_bytes);
3080 /* 4 bytes pad/reserved - must be zero */
3081 SIVAL(pdata, 36, 0);
3085 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3086 SBIG_UINT(pdata, data_len,
3087 (uint64_t)conn->server_info->utok.groups[i]);
3093 i < conn->server_info->ptok->num_sids; ++i) {
3094 int sid_len = ndr_size_dom_sid(
3095 &conn->server_info->ptok->user_sids[i],
3099 sid_linearize(pdata + data_len, sid_len,
3100 &conn->server_info->ptok->user_sids[i]);
3101 data_len += sid_len;
3107 case SMB_MAC_QUERY_FS_INFO:
3109 * Thursby MAC extension... ONLY on NTFS filesystems
3110 * once we do streams then we don't need this
3112 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3114 SIVAL(pdata,84,0x100); /* Don't support mac... */
3119 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3124 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3127 DEBUG( 4, ( "%s info_level = %d\n",
3128 smb_fn_name(req->cmd), info_level) );
3133 /****************************************************************************
3134 Reply to a TRANS2_SETFSINFO (set filesystem info).
3135 ****************************************************************************/
3137 static void call_trans2setfsinfo(connection_struct *conn,
3138 struct smb_request *req,
3139 char **pparams, int total_params,
3140 char **ppdata, int total_data,
3141 unsigned int max_data_bytes)
3143 char *pdata = *ppdata;
3144 char *params = *pparams;
3147 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3150 if (total_params < 4) {
3151 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3153 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3157 info_level = SVAL(params,2);
3160 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3161 info_level != SMB_SET_CIFS_UNIX_INFO) {
3162 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3163 "info level (0x%x) on IPC$.\n",
3164 (unsigned int)info_level));
3165 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3170 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3171 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3172 DEBUG(0,("call_trans2setfsinfo: encryption required "
3173 "and info level 0x%x sent.\n",
3174 (unsigned int)info_level));
3175 exit_server_cleanly("encryption required "
3181 switch(info_level) {
3182 case SMB_SET_CIFS_UNIX_INFO:
3184 uint16 client_unix_major;
3185 uint16 client_unix_minor;
3186 uint32 client_unix_cap_low;
3187 uint32 client_unix_cap_high;
3189 if (!lp_unix_extensions()) {
3191 NT_STATUS_INVALID_LEVEL);
3195 /* There should be 12 bytes of capabilities set. */
3196 if (total_data < 8) {
3199 NT_STATUS_INVALID_PARAMETER);
3202 client_unix_major = SVAL(pdata,0);
3203 client_unix_minor = SVAL(pdata,2);
3204 client_unix_cap_low = IVAL(pdata,4);
3205 client_unix_cap_high = IVAL(pdata,8);
3206 /* Just print these values for now. */
3207 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3208 cap_low = 0x%x, cap_high = 0x%x\n",
3209 (unsigned int)client_unix_major,
3210 (unsigned int)client_unix_minor,
3211 (unsigned int)client_unix_cap_low,
3212 (unsigned int)client_unix_cap_high ));
3214 /* Here is where we must switch to posix pathname processing... */
3215 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3216 lp_set_posix_pathnames();
3217 mangle_change_to_posix();
3220 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3221 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3222 /* Client that knows how to do posix locks,
3223 * but not posix open/mkdir operations. Set a
3224 * default type for read/write checks. */
3226 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3232 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3235 size_t param_len = 0;
3236 size_t data_len = total_data;
3238 if (!lp_unix_extensions()) {
3241 NT_STATUS_INVALID_LEVEL);
3245 if (lp_smb_encrypt(SNUM(conn)) == false) {
3248 NT_STATUS_NOT_SUPPORTED);
3252 DEBUG( 4,("call_trans2setfsinfo: "
3253 "request transport encryption.\n"));
3255 status = srv_request_encryption_setup(conn,
3256 (unsigned char **)ppdata,
3258 (unsigned char **)pparams,
3261 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3262 !NT_STATUS_IS_OK(status)) {
3263 reply_nterror(req, status);
3267 send_trans2_replies(conn, req,
3274 if (NT_STATUS_IS_OK(status)) {
3275 /* Server-side transport
3276 * encryption is now *on*. */
3277 status = srv_encryption_start(conn);
3278 if (!NT_STATUS_IS_OK(status)) {
3279 exit_server_cleanly(
3280 "Failure in setting "
3281 "up encrypted transport");
3287 case SMB_FS_QUOTA_INFORMATION:
3289 files_struct *fsp = NULL;
3290 SMB_NTQUOTA_STRUCT quotas;
3292 ZERO_STRUCT(quotas);
3295 if ((conn->server_info->utok.uid != 0)
3296 ||!CAN_WRITE(conn)) {
3297 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3298 lp_servicename(SNUM(conn)),
3299 conn->server_info->unix_name));
3300 reply_doserror(req, ERRSRV, ERRaccess);
3304 /* note: normaly there're 48 bytes,
3305 * but we didn't use the last 6 bytes for now
3308 fsp = file_fsp(req, SVAL(params,0));
3310 if (!check_fsp_ntquota_handle(conn, req,
3312 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3314 req, NT_STATUS_INVALID_HANDLE);
3318 if (total_data < 42) {
3319 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3323 NT_STATUS_INVALID_PARAMETER);
3327 /* unknown_1 24 NULL bytes in pdata*/
3329 /* the soft quotas 8 bytes (uint64_t)*/
3330 quotas.softlim = (uint64_t)IVAL(pdata,24);
3331 #ifdef LARGE_SMB_OFF_T
3332 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3333 #else /* LARGE_SMB_OFF_T */
3334 if ((IVAL(pdata,28) != 0)&&
3335 ((quotas.softlim != 0xFFFFFFFF)||
3336 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3337 /* more than 32 bits? */
3340 NT_STATUS_INVALID_PARAMETER);
3343 #endif /* LARGE_SMB_OFF_T */
3345 /* the hard quotas 8 bytes (uint64_t)*/
3346 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3347 #ifdef LARGE_SMB_OFF_T
3348 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3349 #else /* LARGE_SMB_OFF_T */
3350 if ((IVAL(pdata,36) != 0)&&
3351 ((quotas.hardlim != 0xFFFFFFFF)||
3352 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3353 /* more than 32 bits? */
3356 NT_STATUS_INVALID_PARAMETER);
3359 #endif /* LARGE_SMB_OFF_T */
3361 /* quota_flags 2 bytes **/
3362 quotas.qflags = SVAL(pdata,40);
3364 /* unknown_2 6 NULL bytes follow*/
3366 /* now set the quotas */
3367 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3368 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3369 reply_doserror(req, ERRSRV, ERRerror);
3376 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3378 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3384 * sending this reply works fine,
3385 * but I'm not sure it's the same
3386 * like windows do...
3389 reply_outbuf(req, 10, 0);
3392 #if defined(HAVE_POSIX_ACLS)
3393 /****************************************************************************
3394 Utility function to count the number of entries in a POSIX acl.
3395 ****************************************************************************/
3397 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3399 unsigned int ace_count = 0;
3400 int entry_id = SMB_ACL_FIRST_ENTRY;
3401 SMB_ACL_ENTRY_T entry;
3403 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3405 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3406 entry_id = SMB_ACL_NEXT_ENTRY;
3413 /****************************************************************************
3414 Utility function to marshall a POSIX acl into wire format.
3415 ****************************************************************************/
3417 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3419 int entry_id = SMB_ACL_FIRST_ENTRY;
3420 SMB_ACL_ENTRY_T entry;
3422 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3423 SMB_ACL_TAG_T tagtype;
3424 SMB_ACL_PERMSET_T permset;
3425 unsigned char perms = 0;
3426 unsigned int own_grp;
3429 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3430 entry_id = SMB_ACL_NEXT_ENTRY;
3433 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3434 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3438 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3439 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3443 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3444 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3445 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3447 SCVAL(pdata,1,perms);
3450 case SMB_ACL_USER_OBJ:
3451 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3452 own_grp = (unsigned int)pst->st_uid;
3453 SIVAL(pdata,2,own_grp);
3458 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3460 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3463 own_grp = (unsigned int)*puid;
3464 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3465 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3466 SIVAL(pdata,2,own_grp);
3470 case SMB_ACL_GROUP_OBJ:
3471 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3472 own_grp = (unsigned int)pst->st_gid;
3473 SIVAL(pdata,2,own_grp);
3478 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3480 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3483 own_grp = (unsigned int)*pgid;
3484 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3485 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3486 SIVAL(pdata,2,own_grp);
3491 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3492 SIVAL(pdata,2,0xFFFFFFFF);
3493 SIVAL(pdata,6,0xFFFFFFFF);
3496 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3497 SIVAL(pdata,2,0xFFFFFFFF);
3498 SIVAL(pdata,6,0xFFFFFFFF);
3501 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3504 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3511 /****************************************************************************
3512 Store the FILE_UNIX_BASIC info.
3513 ****************************************************************************/
3515 static char *store_file_unix_basic(connection_struct *conn,
3518 const SMB_STRUCT_STAT *psbuf)
3520 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3521 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3523 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3526 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3529 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3530 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3531 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3534 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3538 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3542 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3545 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3549 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3553 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3556 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3560 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3567 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3568 * the chflags(2) (or equivalent) flags.
3570 * XXX: this really should be behind the VFS interface. To do this, we would
3571 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3572 * Each VFS module could then implement its own mapping as appropriate for the
3573 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3575 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3579 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3583 { UF_IMMUTABLE, EXT_IMMUTABLE },
3587 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3591 { UF_HIDDEN, EXT_HIDDEN },
3594 /* Do not remove. We need to guarantee that this array has at least one
3595 * entry to build on HP-UX.
3601 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3602 uint32 *smb_fflags, uint32 *smb_fmask)
3604 #ifdef HAVE_STAT_ST_FLAGS
3607 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3608 *smb_fmask |= info2_flags_map[i].smb_fflag;
3609 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3610 *smb_fflags |= info2_flags_map[i].smb_fflag;
3613 #endif /* HAVE_STAT_ST_FLAGS */
3616 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3617 const uint32 smb_fflags,
3618 const uint32 smb_fmask,
3621 #ifdef HAVE_STAT_ST_FLAGS
3622 uint32 max_fmask = 0;
3625 *stat_fflags = psbuf->st_flags;
3627 /* For each flags requested in smb_fmask, check the state of the
3628 * corresponding flag in smb_fflags and set or clear the matching
3632 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3633 max_fmask |= info2_flags_map[i].smb_fflag;
3634 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3635 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3636 *stat_fflags |= info2_flags_map[i].stat_fflag;
3638 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3643 /* If smb_fmask is asking to set any bits that are not supported by
3644 * our flag mappings, we should fail.
3646 if ((smb_fmask & max_fmask) != smb_fmask) {
3653 #endif /* HAVE_STAT_ST_FLAGS */
3657 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3658 * of file flags and birth (create) time.
3660 static char *store_file_unix_basic_info2(connection_struct *conn,
3663 const SMB_STRUCT_STAT *psbuf)
3665 uint32 file_flags = 0;
3666 uint32 flags_mask = 0;
3668 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3670 /* Create (birth) time 64 bit */
3671 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3674 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3675 SIVAL(pdata, 0, file_flags); /* flags */
3676 SIVAL(pdata, 4, flags_mask); /* mask */
3682 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3683 const struct stream_struct *streams,
3685 unsigned int max_data_bytes,
3686 unsigned int *data_size)
3689 unsigned int ofs = 0;
3691 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3692 unsigned int next_offset;
3694 smb_ucs2_t *namebuf;
3696 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3697 streams[i].name, &namelen) ||
3700 return NT_STATUS_INVALID_PARAMETER;
3704 * name_buf is now null-terminated, we need to marshall as not
3710 SIVAL(data, ofs+4, namelen);
3711 SOFF_T(data, ofs+8, streams[i].size);
3712 SOFF_T(data, ofs+16, streams[i].alloc_size);
3713 memcpy(data+ofs+24, namebuf, namelen);
3714 TALLOC_FREE(namebuf);
3716 next_offset = ofs + 24 + namelen;
3718 if (i == num_streams-1) {
3719 SIVAL(data, ofs, 0);
3722 unsigned int align = ndr_align_size(next_offset, 8);
3724 memset(data+next_offset, 0, align);
3725 next_offset += align;
3727 SIVAL(data, ofs, next_offset - ofs);
3736 return NT_STATUS_OK;
3739 /****************************************************************************
3740 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3741 ****************************************************************************/
3743 static void call_trans2qpipeinfo(connection_struct *conn,
3744 struct smb_request *req,
3745 unsigned int tran_call,
3746 char **pparams, int total_params,
3747 char **ppdata, int total_data,
3748 unsigned int max_data_bytes)
3750 char *params = *pparams;
3751 char *pdata = *ppdata;
3752 unsigned int data_size = 0;
3753 unsigned int param_size = 2;
3758 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3762 if (total_params < 4) {
3763 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3767 fsp = file_fsp(req, SVAL(params,0));
3768 if (!fsp_is_np(fsp)) {
3769 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3773 info_level = SVAL(params,2);
3775 *pparams = (char *)SMB_REALLOC(*pparams,2);
3776 if (*pparams == NULL) {
3777 reply_nterror(req, NT_STATUS_NO_MEMORY);
3782 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3783 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3784 if (*ppdata == NULL ) {
3785 reply_nterror(req, NT_STATUS_NO_MEMORY);
3790 switch (info_level) {
3791 case SMB_FILE_STANDARD_INFORMATION:
3793 SOFF_T(pdata,0,4096LL);
3800 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3804 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3810 /****************************************************************************
3811 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3812 file name or file id).
3813 ****************************************************************************/
3815 static void call_trans2qfilepathinfo(connection_struct *conn,
3816 struct smb_request *req,
3817 unsigned int tran_call,
3818 char **pparams, int total_params,
3819 char **ppdata, int total_data,
3820 unsigned int max_data_bytes)
3822 char *params = *pparams;
3823 char *pdata = *ppdata;
3824 char *dstart, *dend;
3828 SMB_OFF_T file_size=0;
3829 uint64_t allocation_size=0;
3830 unsigned int data_size = 0;
3831 unsigned int param_size = 2;
3832 SMB_STRUCT_STAT sbuf;
3833 char *dos_fname = NULL;
3839 bool delete_pending = False;
3841 time_t create_time, mtime, atime;
3842 struct timespec create_time_ts, mtime_ts, atime_ts;
3843 struct timespec write_time_ts;
3844 files_struct *fsp = NULL;
3845 struct file_id fileid;
3846 struct ea_list *ea_list = NULL;
3847 char *lock_data = NULL;
3848 bool ms_dfs_link = false;
3849 TALLOC_CTX *ctx = talloc_tos();
3852 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3857 ZERO_STRUCT(write_time_ts);
3859 if (tran_call == TRANSACT2_QFILEINFO) {
3860 if (total_params < 4) {
3861 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3866 call_trans2qpipeinfo(conn, req, tran_call,
3867 pparams, total_params,
3873 fsp = file_fsp(req, SVAL(params,0));
3874 info_level = SVAL(params,2);
3876 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3878 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3879 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3883 /* Initial check for valid fsp ptr. */
3884 if (!check_fsp_open(conn, req, fsp)) {
3888 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3890 reply_nterror(req, NT_STATUS_NO_MEMORY);
3894 if(fsp->fake_file_handle) {
3896 * This is actually for the QUOTA_FAKE_FILE --metze
3899 /* We know this name is ok, it's already passed the checks. */
3901 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3903 * This is actually a QFILEINFO on a directory
3904 * handle (returned from an NT SMB). NT5.0 seems
3905 * to do this call. JRA.
3908 if (INFO_LEVEL_IS_UNIX(info_level)) {
3909 /* Always do lstat for UNIX calls. */
3910 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3911 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3912 reply_unixerror(req,ERRDOS,ERRbadpath);
3915 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3916 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3917 reply_unixerror(req, ERRDOS, ERRbadpath);
3921 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3922 get_file_infos(fileid, &delete_pending, &write_time_ts);
3925 * Original code - this is an open file.
3927 if (!check_fsp(conn, req, fsp)) {
3931 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3932 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3933 reply_unixerror(req, ERRDOS, ERRbadfid);
3936 pos = fsp->fh->position_information;
3937 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3938 get_file_infos(fileid, &delete_pending, &write_time_ts);
3942 NTSTATUS status = NT_STATUS_OK;
3945 if (total_params < 7) {
3946 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3950 info_level = SVAL(params,0);
3952 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3954 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3955 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3959 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
3961 STR_TERMINATE, &status);
3962 if (!NT_STATUS_IS_OK(status)) {
3963 reply_nterror(req, status);
3967 status = resolve_dfspath(ctx,
3969 req->flags2 & FLAGS2_DFS_PATHNAMES,
3972 if (!NT_STATUS_IS_OK(status)) {
3973 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3974 reply_botherror(req,
3975 NT_STATUS_PATH_NOT_COVERED,
3976 ERRSRV, ERRbadpath);
3978 reply_nterror(req, status);
3982 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3983 if (!NT_STATUS_IS_OK(status)) {
3984 reply_nterror(req, status);
3987 status = check_name(conn, fname);
3988 if (!NT_STATUS_IS_OK(status)) {
3989 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3990 reply_nterror(req, status);
3994 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
3995 && is_ntfs_stream_name(fname)) {
3997 SMB_STRUCT_STAT bsbuf;
3999 status = split_ntfs_stream_name(talloc_tos(), fname,
4001 if (!NT_STATUS_IS_OK(status)) {
4002 DEBUG(10, ("create_file_unixpath: "
4003 "split_ntfs_stream_name failed: %s\n",
4004 nt_errstr(status)));
4005 reply_nterror(req, status);
4009 SMB_ASSERT(!is_ntfs_stream_name(base)); /* paranoia.. */
4011 if (INFO_LEVEL_IS_UNIX(info_level)) {
4012 /* Always do lstat for UNIX calls. */
4013 if (SMB_VFS_LSTAT(conn,base,&bsbuf)) {
4014 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",base,strerror(errno)));
4015 reply_unixerror(req,ERRDOS,ERRbadpath);
4019 if (SMB_VFS_STAT(conn,base,&bsbuf) != 0) {
4020 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",base,strerror(errno)));
4021 reply_unixerror(req,ERRDOS,ERRbadpath);
4026 fileid = vfs_file_id_from_sbuf(conn, &bsbuf);
4027 get_file_infos(fileid, &delete_pending, NULL);
4028 if (delete_pending) {
4029 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4034 if (INFO_LEVEL_IS_UNIX(info_level)) {
4035 /* Always do lstat for UNIX calls. */
4036 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
4037 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
4038 reply_unixerror(req, ERRDOS, ERRbadpath);
4042 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
4043 ms_dfs_link = check_msdfs_link(conn,fname,&sbuf);
4046 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
4047 reply_unixerror(req, ERRDOS, ERRbadpath);
4052 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4053 get_file_infos(fileid, &delete_pending, &write_time_ts);
4054 if (delete_pending) {
4055 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4060 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4061 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4065 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4066 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4068 p = strrchr_m(fname,'/');
4075 mode = dos_mode_msdfs(conn,fname,&sbuf);
4077 mode = dos_mode(conn,fname,&sbuf);
4080 mode = FILE_ATTRIBUTE_NORMAL;
4082 nlink = sbuf.st_nlink;
4084 if (nlink && (mode&aDIR)) {
4088 if ((nlink > 0) && delete_pending) {
4092 fullpathname = fname;
4094 file_size = get_file_size(sbuf);
4096 /* Pull out any data sent here before we realloc. */
4097 switch (info_level) {
4098 case SMB_INFO_QUERY_EAS_FROM_LIST:
4100 /* Pull any EA list from the data portion. */
4103 if (total_data < 4) {
4105 req, NT_STATUS_INVALID_PARAMETER);
4108 ea_size = IVAL(pdata,0);
4110 if (total_data > 0 && ea_size != total_data) {
4111 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4112 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4114 req, NT_STATUS_INVALID_PARAMETER);
4118 if (!lp_ea_support(SNUM(conn))) {
4119 reply_doserror(req, ERRDOS,
4120 ERReasnotsupported);
4124 /* Pull out the list of names. */
4125 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4128 req, NT_STATUS_INVALID_PARAMETER);
4134 case SMB_QUERY_POSIX_LOCK:
4136 if (fsp == NULL || fsp->fh->fd == -1) {
4137 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4141 if (total_data != POSIX_LOCK_DATA_SIZE) {
4143 req, NT_STATUS_INVALID_PARAMETER);
4147 /* Copy the lock range data. */
4148 lock_data = (char *)TALLOC_MEMDUP(
4149 ctx, pdata, total_data);
4151 reply_nterror(req, NT_STATUS_NO_MEMORY);
4159 *pparams = (char *)SMB_REALLOC(*pparams,2);
4160 if (*pparams == NULL) {
4161 reply_nterror(req, NT_STATUS_NO_MEMORY);
4166 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4167 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4168 if (*ppdata == NULL ) {
4169 reply_nterror(req, NT_STATUS_NO_MEMORY);
4174 dend = dstart + data_size - 1;
4176 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
4177 mtime_ts = get_mtimespec(&sbuf);
4178 atime_ts = get_atimespec(&sbuf);
4180 allocation_size = get_allocation_size(conn,fsp,&sbuf);
4183 /* Do we have this path open ? */
4185 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4186 fsp1 = file_find_di_first(fileid);
4187 if (fsp1 && fsp1->initial_allocation_size) {
4188 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
4192 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4193 mtime_ts = write_time_ts;
4196 if (lp_dos_filetime_resolution(SNUM(conn))) {
4197 dos_filetime_timespec(&create_time_ts);
4198 dos_filetime_timespec(&mtime_ts);
4199 dos_filetime_timespec(&atime_ts);
4202 create_time = convert_timespec_to_time_t(create_time_ts);
4203 mtime = convert_timespec_to_time_t(mtime_ts);
4204 atime = convert_timespec_to_time_t(atime_ts);
4206 /* NT expects the name to be in an exact form of the *full*
4207 filename. See the trans2 torture test */
4208 if (ISDOT(base_name)) {
4209 dos_fname = talloc_strdup(ctx, "\\");
4211 reply_nterror(req, NT_STATUS_NO_MEMORY);
4215 dos_fname = talloc_asprintf(ctx,
4219 reply_nterror(req, NT_STATUS_NO_MEMORY);
4222 string_replace(dos_fname, '/', '\\');
4225 switch (info_level) {
4226 case SMB_INFO_STANDARD:
4227 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4229 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4230 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4231 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4232 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4233 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4234 SSVAL(pdata,l1_attrFile,mode);
4237 case SMB_INFO_QUERY_EA_SIZE:
4239 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4240 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4242 srv_put_dos_date2(pdata,0,create_time);
4243 srv_put_dos_date2(pdata,4,atime);
4244 srv_put_dos_date2(pdata,8,mtime); /* write time */
4245 SIVAL(pdata,12,(uint32)file_size);
4246 SIVAL(pdata,16,(uint32)allocation_size);
4247 SSVAL(pdata,20,mode);
4248 SIVAL(pdata,22,ea_size);
4252 case SMB_INFO_IS_NAME_VALID:
4253 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4254 if (tran_call == TRANSACT2_QFILEINFO) {
4255 /* os/2 needs this ? really ?*/
4256 reply_doserror(req, ERRDOS, ERRbadfunc);
4263 case SMB_INFO_QUERY_EAS_FROM_LIST:
4265 size_t total_ea_len = 0;
4266 struct ea_list *ea_file_list = NULL;
4268 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4270 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4271 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4273 if (!ea_list || (total_ea_len > data_size)) {
4275 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4279 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4283 case SMB_INFO_QUERY_ALL_EAS:
4285 /* We have data_size bytes to put EA's into. */
4286 size_t total_ea_len = 0;
4288 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4290 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4291 if (!ea_list || (total_ea_len > data_size)) {
4293 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4297 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4301 case SMB_FILE_BASIC_INFORMATION:
4302 case SMB_QUERY_FILE_BASIC_INFO:
4304 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4305 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4306 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4308 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4312 put_long_date_timespec(pdata,create_time_ts);
4313 put_long_date_timespec(pdata+8,atime_ts);
4314 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4315 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4316 SIVAL(pdata,32,mode);
4318 DEBUG(5,("SMB_QFBI - "));
4319 DEBUG(5,("create: %s ", ctime(&create_time)));
4320 DEBUG(5,("access: %s ", ctime(&atime)));
4321 DEBUG(5,("write: %s ", ctime(&mtime)));
4322 DEBUG(5,("change: %s ", ctime(&mtime)));
4323 DEBUG(5,("mode: %x\n", mode));
4326 case SMB_FILE_STANDARD_INFORMATION:
4327 case SMB_QUERY_FILE_STANDARD_INFO:
4329 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4331 SOFF_T(pdata,0,allocation_size);
4332 SOFF_T(pdata,8,file_size);
4333 SIVAL(pdata,16,nlink);
4334 SCVAL(pdata,20,delete_pending?1:0);
4335 SCVAL(pdata,21,(mode&aDIR)?1:0);
4336 SSVAL(pdata,22,0); /* Padding. */
4339 case SMB_FILE_EA_INFORMATION:
4340 case SMB_QUERY_FILE_EA_INFO:
4342 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4343 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4345 SIVAL(pdata,0,ea_size);
4349 /* Get the 8.3 name - used if NT SMB was negotiated. */
4350 case SMB_QUERY_FILE_ALT_NAME_INFO:
4351 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4353 char mangled_name[13];
4354 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4355 if (!name_to_8_3(base_name,mangled_name,
4356 True,conn->params)) {
4359 NT_STATUS_NO_MEMORY);
4361 len = srvstr_push(dstart, req->flags2,
4362 pdata+4, mangled_name,
4363 PTR_DIFF(dend, pdata+4),
4365 data_size = 4 + len;
4370 case SMB_QUERY_FILE_NAME_INFO:
4372 this must be *exactly* right for ACLs on mapped drives to work
4374 len = srvstr_push(dstart, req->flags2,
4376 PTR_DIFF(dend, pdata+4),
4378 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4379 data_size = 4 + len;
4383 case SMB_FILE_ALLOCATION_INFORMATION:
4384 case SMB_QUERY_FILE_ALLOCATION_INFO:
4385 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4387 SOFF_T(pdata,0,allocation_size);
4390 case SMB_FILE_END_OF_FILE_INFORMATION:
4391 case SMB_QUERY_FILE_END_OF_FILEINFO:
4392 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4394 SOFF_T(pdata,0,file_size);
4397 case SMB_QUERY_FILE_ALL_INFO:
4398 case SMB_FILE_ALL_INFORMATION:
4400 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4401 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4402 put_long_date_timespec(pdata,create_time_ts);
4403 put_long_date_timespec(pdata+8,atime_ts);
4404 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4405 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4406 SIVAL(pdata,32,mode);
4407 SIVAL(pdata,36,0); /* padding. */
4409 SOFF_T(pdata,0,allocation_size);
4410 SOFF_T(pdata,8,file_size);
4411 SIVAL(pdata,16,nlink);
4412 SCVAL(pdata,20,delete_pending);
4413 SCVAL(pdata,21,(mode&aDIR)?1:0);
4416 SIVAL(pdata,0,ea_size);
4417 pdata += 4; /* EA info */
4418 len = srvstr_push(dstart, req->flags2,
4420 PTR_DIFF(dend, pdata+4),
4424 data_size = PTR_DIFF(pdata,(*ppdata));
4427 case SMB_FILE_INTERNAL_INFORMATION:
4428 /* This should be an index number - looks like
4431 I think this causes us to fail the IFSKIT
4432 BasicFileInformationTest. -tpot */
4434 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4435 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4436 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4440 case SMB_FILE_ACCESS_INFORMATION:
4441 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4443 SIVAL(pdata,0,fsp->access_mask);
4445 /* GENERIC_EXECUTE mapping from Windows */
4446 SIVAL(pdata,0,0x12019F);
4451 case SMB_FILE_NAME_INFORMATION:
4452 /* Pathname with leading '\'. */
4455 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4456 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4457 SIVAL(pdata,0,byte_len);
4458 data_size = 4 + byte_len;
4462 case SMB_FILE_DISPOSITION_INFORMATION:
4463 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4465 SCVAL(pdata,0,delete_pending);
4468 case SMB_FILE_POSITION_INFORMATION:
4469 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4471 SOFF_T(pdata,0,pos);
4474 case SMB_FILE_MODE_INFORMATION:
4475 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4476 SIVAL(pdata,0,mode);
4480 case SMB_FILE_ALIGNMENT_INFORMATION:
4481 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4482 SIVAL(pdata,0,0); /* No alignment needed. */
4487 * NT4 server just returns "invalid query" to this - if we try
4488 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4491 /* The first statement above is false - verified using Thursby
4492 * client against NT4 -- gcolley.
4494 case SMB_QUERY_FILE_STREAM_INFO:
4495 case SMB_FILE_STREAM_INFORMATION: {
4496 unsigned int num_streams;
4497 struct stream_struct *streams;
4500 DEBUG(10,("call_trans2qfilepathinfo: "
4501 "SMB_FILE_STREAM_INFORMATION\n"));
4503 status = SMB_VFS_STREAMINFO(
4504 conn, fsp, fname, talloc_tos(),
4505 &num_streams, &streams);
4507 if (!NT_STATUS_IS_OK(status)) {
4508 DEBUG(10, ("could not get stream info: %s\n",
4509 nt_errstr(status)));
4510 reply_nterror(req, status);
4514 status = marshall_stream_info(num_streams, streams,
4515 pdata, max_data_bytes,
4518 if (!NT_STATUS_IS_OK(status)) {
4519 DEBUG(10, ("marshall_stream_info failed: %s\n",
4520 nt_errstr(status)));
4521 reply_nterror(req, status);
4525 TALLOC_FREE(streams);
4529 case SMB_QUERY_COMPRESSION_INFO:
4530 case SMB_FILE_COMPRESSION_INFORMATION:
4531 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4532 SOFF_T(pdata,0,file_size);
4533 SIVAL(pdata,8,0); /* ??? */
4534 SIVAL(pdata,12,0); /* ??? */
4538 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4539 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4540 put_long_date_timespec(pdata,create_time_ts);
4541 put_long_date_timespec(pdata+8,atime_ts);
4542 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4543 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4544 SOFF_T(pdata,32,allocation_size);
4545 SOFF_T(pdata,40,file_size);
4546 SIVAL(pdata,48,mode);
4547 SIVAL(pdata,52,0); /* ??? */
4551 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4552 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4553 SIVAL(pdata,0,mode);
4559 * CIFS UNIX Extensions.
4562 case SMB_QUERY_FILE_UNIX_BASIC:
4564 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4565 data_size = PTR_DIFF(pdata,(*ppdata));
4569 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4571 for (i=0; i<100; i++)
4572 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4578 case SMB_QUERY_FILE_UNIX_INFO2:
4580 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4581 data_size = PTR_DIFF(pdata,(*ppdata));
4585 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4587 for (i=0; i<100; i++)
4588 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4594 case SMB_QUERY_FILE_UNIX_LINK:
4596 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4599 reply_nterror(req, NT_STATUS_NO_MEMORY);
4603 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4605 if(!S_ISLNK(sbuf.st_mode)) {
4606 reply_unixerror(req, ERRSRV,
4611 reply_unixerror(req, ERRDOS, ERRbadlink);
4614 len = SMB_VFS_READLINK(conn,fullpathname,
4617 reply_unixerror(req, ERRDOS,
4622 len = srvstr_push(dstart, req->flags2,
4624 PTR_DIFF(dend, pdata),
4627 data_size = PTR_DIFF(pdata,(*ppdata));
4632 #if defined(HAVE_POSIX_ACLS)
4633 case SMB_QUERY_POSIX_ACL:
4635 SMB_ACL_T file_acl = NULL;
4636 SMB_ACL_T def_acl = NULL;
4637 uint16 num_file_acls = 0;
4638 uint16 num_def_acls = 0;
4640 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4641 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4643 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4646 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4647 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4651 NT_STATUS_NOT_IMPLEMENTED);
4655 if (S_ISDIR(sbuf.st_mode)) {
4656 if (fsp && fsp->is_directory) {
4657 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4659 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4661 def_acl = free_empty_sys_acl(conn, def_acl);
4664 num_file_acls = count_acl_entries(conn, file_acl);
4665 num_def_acls = count_acl_entries(conn, def_acl);
4667 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4668 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4670 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4671 SMB_POSIX_ACL_HEADER_SIZE) ));
4673 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4676 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4680 NT_STATUS_BUFFER_TOO_SMALL);
4684 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4685 SSVAL(pdata,2,num_file_acls);
4686 SSVAL(pdata,4,num_def_acls);
4687 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4689 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4692 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4695 req, NT_STATUS_INTERNAL_ERROR);
4698 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4700 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4703 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4707 NT_STATUS_INTERNAL_ERROR);
4712 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4715 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4717 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4723 case SMB_QUERY_POSIX_LOCK:
4725 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4729 enum brl_type lock_type;
4731 if (total_data != POSIX_LOCK_DATA_SIZE) {
4733 req, NT_STATUS_INVALID_PARAMETER);
4737 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4738 case POSIX_LOCK_TYPE_READ:
4739 lock_type = READ_LOCK;
4741 case POSIX_LOCK_TYPE_WRITE:
4742 lock_type = WRITE_LOCK;
4744 case POSIX_LOCK_TYPE_UNLOCK:
4746 /* There's no point in asking for an unlock... */
4749 NT_STATUS_INVALID_PARAMETER);
4753 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4754 #if defined(HAVE_LONGLONG)
4755 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4756 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4757 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4758 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4759 #else /* HAVE_LONGLONG */
4760 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4761 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4762 #endif /* HAVE_LONGLONG */
4764 status = query_lock(fsp,
4771 if (ERROR_WAS_LOCK_DENIED(status)) {
4772 /* Here we need to report who has it locked... */
4773 data_size = POSIX_LOCK_DATA_SIZE;
4775 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4776 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4777 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4778 #if defined(HAVE_LONGLONG)
4779 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4780 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4781 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4782 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4783 #else /* HAVE_LONGLONG */
4784 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4785 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4786 #endif /* HAVE_LONGLONG */
4788 } else if (NT_STATUS_IS_OK(status)) {
4789 /* For success we just return a copy of what we sent
4790 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4791 data_size = POSIX_LOCK_DATA_SIZE;
4792 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4793 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4795 reply_nterror(req, status);
4802 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4806 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4812 /****************************************************************************
4813 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4815 ****************************************************************************/
4817 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4818 connection_struct *conn,
4819 const char *oldname_in,
4820 const char *newname_in)
4822 SMB_STRUCT_STAT sbuf1, sbuf2;
4823 char *last_component_oldname = NULL;
4824 char *last_component_newname = NULL;
4825 char *oldname = NULL;
4826 char *newname = NULL;
4827 NTSTATUS status = NT_STATUS_OK;
4832 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4833 &last_component_oldname, &sbuf1);
4834 if (!NT_STATUS_IS_OK(status)) {
4838 status = check_name(conn, oldname);
4839 if (!NT_STATUS_IS_OK(status)) {
4843 /* source must already exist. */
4844 if (!VALID_STAT(sbuf1)) {
4845 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4848 status = unix_convert(ctx, conn, newname_in, False, &newname,
4849 &last_component_newname, &sbuf2);
4850 if (!NT_STATUS_IS_OK(status)) {
4854 status = check_name(conn, newname);
4855 if (!NT_STATUS_IS_OK(status)) {
4859 /* Disallow if newname already exists. */
4860 if (VALID_STAT(sbuf2)) {
4861 return NT_STATUS_OBJECT_NAME_COLLISION;
4864 /* No links from a directory. */
4865 if (S_ISDIR(sbuf1.st_mode)) {
4866 return NT_STATUS_FILE_IS_A_DIRECTORY;
4869 /* Ensure this is within the share. */
4870 status = check_reduced_name(conn, oldname);
4871 if (!NT_STATUS_IS_OK(status)) {
4875 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4877 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4878 status = map_nt_error_from_unix(errno);
4879 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4880 nt_errstr(status), newname, oldname));
4886 /****************************************************************************
4887 Deal with setting the time from any of the setfilepathinfo functions.
4888 ****************************************************************************/
4890 NTSTATUS smb_set_file_time(connection_struct *conn,
4893 const SMB_STRUCT_STAT *psbuf,
4894 struct timespec ts[2],
4895 bool setting_write_time)
4898 FILE_NOTIFY_CHANGE_LAST_ACCESS
4899 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4901 if (!VALID_STAT(*psbuf)) {
4902 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4905 /* get some defaults (no modifications) if any info is zero or -1. */
4906 if (null_timespec(ts[0])) {
4907 ts[0] = get_atimespec(psbuf);
4908 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4911 if (null_timespec(ts[1])) {
4912 ts[1] = get_mtimespec(psbuf);
4913 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4916 if (!setting_write_time) {
4917 /* ts[1] comes from change time, not write time. */
4918 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4921 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4922 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4925 * Try and set the times of this file if
4926 * they are different from the current values.
4930 struct timespec mts = get_mtimespec(psbuf);
4931 struct timespec ats = get_atimespec(psbuf);
4932 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4933 return NT_STATUS_OK;
4937 if (setting_write_time) {
4939 * This was a setfileinfo on an open file.
4940 * NT does this a lot. We also need to
4941 * set the time here, as it can be read by
4942 * FindFirst/FindNext and with the patch for bug #2045
4943 * in smbd/fileio.c it ensures that this timestamp is
4944 * kept sticky even after a write. We save the request
4945 * away and will set it on file close and after a write. JRA.
4948 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4949 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4952 if (fsp->base_fsp) {
4953 set_sticky_write_time_fsp(fsp->base_fsp, ts[1]);
4955 set_sticky_write_time_fsp(fsp, ts[1]);
4958 set_sticky_write_time_path(conn, fname,
4959 vfs_file_id_from_sbuf(conn, psbuf),
4964 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4966 if (fsp && fsp->base_fsp) {
4967 fname = fsp->base_fsp->fsp_name;
4970 if(file_ntimes(conn, fname, ts)!=0) {
4971 return map_nt_error_from_unix(errno);
4973 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4975 return NT_STATUS_OK;
4978 /****************************************************************************
4979 Deal with setting the dosmode from any of the setfilepathinfo functions.
4980 ****************************************************************************/
4982 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4984 SMB_STRUCT_STAT *psbuf,
4987 if (!VALID_STAT(*psbuf)) {
4988 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4992 if (S_ISDIR(psbuf->st_mode)) {
4999 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5001 /* check the mode isn't different, before changing it */
5002 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
5004 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
5005 fname, (unsigned int)dosmode ));
5007 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
5008 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
5009 fname, strerror(errno)));
5010 return map_nt_error_from_unix(errno);
5013 return NT_STATUS_OK;
5016 /****************************************************************************
5017 Deal with setting the size from any of the setfilepathinfo functions.
5018 ****************************************************************************/
5020 static NTSTATUS smb_set_file_size(connection_struct *conn,
5021 struct smb_request *req,
5024 SMB_STRUCT_STAT *psbuf,
5027 NTSTATUS status = NT_STATUS_OK;
5028 files_struct *new_fsp = NULL;
5030 if (!VALID_STAT(*psbuf)) {
5031 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5034 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5036 if (size == get_file_size(*psbuf)) {
5037 return NT_STATUS_OK;
5040 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5041 fname, (double)size ));
5043 if (fsp && fsp->fh->fd != -1) {
5044 /* Handle based call. */
5045 if (vfs_set_filelen(fsp, size) == -1) {
5046 return map_nt_error_from_unix(errno);
5048 trigger_write_time_update_immediate(fsp);
5049 return NT_STATUS_OK;
5052 status = SMB_VFS_CREATE_FILE(
5055 0, /* root_dir_fid */
5057 0, /* create_file_flags */
5058 FILE_WRITE_ATTRIBUTES, /* access_mask */
5059 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5061 FILE_OPEN, /* create_disposition*/
5062 0, /* create_options */
5063 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5064 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5065 0, /* allocation_size */
5068 &new_fsp, /* result */
5072 if (!NT_STATUS_IS_OK(status)) {
5073 /* NB. We check for open_was_deferred in the caller. */
5077 if (vfs_set_filelen(new_fsp, size) == -1) {
5078 status = map_nt_error_from_unix(errno);
5079 close_file(req, new_fsp,NORMAL_CLOSE);
5083 trigger_write_time_update_immediate(new_fsp);
5084 close_file(req, new_fsp,NORMAL_CLOSE);
5085 return NT_STATUS_OK;
5088 /****************************************************************************
5089 Deal with SMB_INFO_SET_EA.
5090 ****************************************************************************/
5092 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5098 struct ea_list *ea_list = NULL;
5099 TALLOC_CTX *ctx = NULL;
5100 NTSTATUS status = NT_STATUS_OK;
5102 if (total_data < 10) {
5104 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5105 length. They seem to have no effect. Bug #3212. JRA */
5107 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5108 /* We're done. We only get EA info in this call. */
5109 return NT_STATUS_OK;
5112 return NT_STATUS_INVALID_PARAMETER;
5115 if (IVAL(pdata,0) > total_data) {
5116 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5117 IVAL(pdata,0), (unsigned int)total_data));
5118 return NT_STATUS_INVALID_PARAMETER;
5122 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5124 return NT_STATUS_INVALID_PARAMETER;
5126 status = set_ea(conn, fsp, fname, ea_list);
5131 /****************************************************************************
5132 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5133 ****************************************************************************/
5135 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5140 SMB_STRUCT_STAT *psbuf)
5142 NTSTATUS status = NT_STATUS_OK;
5143 bool delete_on_close;
5146 if (total_data < 1) {
5147 return NT_STATUS_INVALID_PARAMETER;
5151 return NT_STATUS_INVALID_HANDLE;
5154 delete_on_close = (CVAL(pdata,0) ? True : False);
5155 dosmode = dos_mode(conn, fname, psbuf);
5157 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5158 "delete_on_close = %u\n",
5160 (unsigned int)dosmode,
5161 (unsigned int)delete_on_close ));
5163 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5165 if (!NT_STATUS_IS_OK(status)) {
5169 /* The set is across all open files on this dev/inode pair. */
5170 if (!set_delete_on_close(fsp, delete_on_close,
5171 &conn->server_info->utok)) {
5172 return NT_STATUS_ACCESS_DENIED;
5174 return NT_STATUS_OK;
5177 /****************************************************************************
5178 Deal with SMB_FILE_POSITION_INFORMATION.
5179 ****************************************************************************/
5181 static NTSTATUS smb_file_position_information(connection_struct *conn,
5186 uint64_t position_information;
5188 if (total_data < 8) {
5189 return NT_STATUS_INVALID_PARAMETER;
5193 /* Ignore on pathname based set. */
5194 return NT_STATUS_OK;
5197 position_information = (uint64_t)IVAL(pdata,0);
5198 #ifdef LARGE_SMB_OFF_T
5199 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5200 #else /* LARGE_SMB_OFF_T */
5201 if (IVAL(pdata,4) != 0) {
5202 /* more than 32 bits? */
5203 return NT_STATUS_INVALID_PARAMETER;
5205 #endif /* LARGE_SMB_OFF_T */
5207 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5208 fsp->fsp_name, (double)position_information ));
5209 fsp->fh->position_information = position_information;
5210 return NT_STATUS_OK;
5213 /****************************************************************************
5214 Deal with SMB_FILE_MODE_INFORMATION.
5215 ****************************************************************************/
5217 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5223 if (total_data < 4) {
5224 return NT_STATUS_INVALID_PARAMETER;
5226 mode = IVAL(pdata,0);
5227 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5228 return NT_STATUS_INVALID_PARAMETER;
5230 return NT_STATUS_OK;
5233 /****************************************************************************
5234 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5235 ****************************************************************************/
5237 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5238 struct smb_request *req,
5243 char *link_target = NULL;
5244 const char *newname = fname;
5245 NTSTATUS status = NT_STATUS_OK;
5246 TALLOC_CTX *ctx = talloc_tos();
5248 /* Set a symbolic link. */
5249 /* Don't allow this if follow links is false. */
5251 if (total_data == 0) {
5252 return NT_STATUS_INVALID_PARAMETER;
5255 if (!lp_symlinks(SNUM(conn))) {
5256 return NT_STATUS_ACCESS_DENIED;
5259 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5260 total_data, STR_TERMINATE);
5263 return NT_STATUS_INVALID_PARAMETER;
5266 /* !widelinks forces the target path to be within the share. */
5267 /* This means we can interpret the target as a pathname. */
5268 if (!lp_widelinks(SNUM(conn))) {
5269 char *rel_name = NULL;
5270 char *last_dirp = NULL;
5272 if (*link_target == '/') {
5273 /* No absolute paths allowed. */
5274 return NT_STATUS_ACCESS_DENIED;
5276 rel_name = talloc_strdup(ctx,newname);
5278 return NT_STATUS_NO_MEMORY;
5280 last_dirp = strrchr_m(rel_name, '/');
5282 last_dirp[1] = '\0';
5284 rel_name = talloc_strdup(ctx,"./");
5286 return NT_STATUS_NO_MEMORY;
5289 rel_name = talloc_asprintf_append(rel_name,
5293 return NT_STATUS_NO_MEMORY;
5296 status = check_name(conn, rel_name);
5297 if (!NT_STATUS_IS_OK(status)) {
5302 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5303 newname, link_target ));
5305 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5306 return map_nt_error_from_unix(errno);
5309 return NT_STATUS_OK;
5312 /****************************************************************************
5313 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5314 ****************************************************************************/
5316 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5317 struct smb_request *req,
5318 const char *pdata, int total_data,
5321 char *oldname = NULL;
5322 TALLOC_CTX *ctx = talloc_tos();
5323 NTSTATUS status = NT_STATUS_OK;
5325 /* Set a hard link. */
5326 if (total_data == 0) {
5327 return NT_STATUS_INVALID_PARAMETER;
5330 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5331 total_data, STR_TERMINATE, &status);
5332 if (!NT_STATUS_IS_OK(status)) {
5336 status = resolve_dfspath(ctx, conn,
5337 req->flags2 & FLAGS2_DFS_PATHNAMES,
5340 if (!NT_STATUS_IS_OK(status)) {
5344 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5347 return hardlink_internals(ctx, conn, oldname, fname);
5350 /****************************************************************************
5351 Deal with SMB_FILE_RENAME_INFORMATION.
5352 ****************************************************************************/
5354 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5355 struct smb_request *req,
5364 char *newname = NULL;
5365 char *base_name = NULL;
5366 bool dest_has_wcard = False;
5367 SMB_STRUCT_STAT sbuf;
5368 char *newname_last_component = NULL;
5369 NTSTATUS status = NT_STATUS_OK;
5371 TALLOC_CTX *ctx = talloc_tos();
5373 if (total_data < 13) {
5374 return NT_STATUS_INVALID_PARAMETER;
5379 overwrite = (CVAL(pdata,0) ? True : False);
5380 root_fid = IVAL(pdata,4);
5381 len = IVAL(pdata,8);
5383 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5384 return NT_STATUS_INVALID_PARAMETER;
5387 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5390 if (!NT_STATUS_IS_OK(status)) {
5394 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5397 status = resolve_dfspath_wcard(ctx, conn,
5398 req->flags2 & FLAGS2_DFS_PATHNAMES,
5402 if (!NT_STATUS_IS_OK(status)) {
5406 /* Check the new name has no '/' characters. */
5407 if (strchr_m(newname, '/')) {
5408 return NT_STATUS_NOT_SUPPORTED;
5411 if (fsp && fsp->base_fsp) {
5412 /* newname must be a stream name. */
5413 if (newname[0] != ':') {
5414 return NT_STATUS_NOT_SUPPORTED;
5416 base_name = talloc_asprintf(ctx, "%s%s",
5417 fsp->base_fsp->fsp_name,
5420 return NT_STATUS_NO_MEMORY;
5423 /* newname must *not* be a stream name. */
5424 if (is_ntfs_stream_name(newname)) {
5425 return NT_STATUS_NOT_SUPPORTED;
5428 /* Create the base directory. */
5429 base_name = talloc_strdup(ctx, fname);
5431 return NT_STATUS_NO_MEMORY;
5433 p = strrchr_m(base_name, '/');
5437 base_name = talloc_strdup(ctx, "./");
5439 return NT_STATUS_NO_MEMORY;
5442 /* Append the new name. */
5443 base_name = talloc_asprintf_append(base_name,
5447 return NT_STATUS_NO_MEMORY;
5450 status = unix_convert(ctx, conn, newname, False,
5452 &newname_last_component,
5455 /* If an error we expect this to be
5456 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5458 if (!NT_STATUS_IS_OK(status)
5459 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5466 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5467 fsp->fnum, fsp->fsp_name, base_name ));
5468 status = rename_internals_fsp(conn, fsp, base_name,
5469 newname_last_component, 0,
5472 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5473 fname, base_name ));
5474 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5475 overwrite, False, dest_has_wcard,
5476 FILE_WRITE_ATTRIBUTES);
5482 /****************************************************************************
5483 Deal with SMB_SET_POSIX_ACL.
5484 ****************************************************************************/
5486 #if defined(HAVE_POSIX_ACLS)
5487 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5492 SMB_STRUCT_STAT *psbuf)
5494 uint16 posix_acl_version;
5495 uint16 num_file_acls;
5496 uint16 num_def_acls;
5497 bool valid_file_acls = True;
5498 bool valid_def_acls = True;
5500 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5501 return NT_STATUS_INVALID_PARAMETER;
5503 posix_acl_version = SVAL(pdata,0);
5504 num_file_acls = SVAL(pdata,2);
5505 num_def_acls = SVAL(pdata,4);
5507 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5508 valid_file_acls = False;
5512 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5513 valid_def_acls = False;
5517 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5518 return NT_STATUS_INVALID_PARAMETER;
5521 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5522 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5523 return NT_STATUS_INVALID_PARAMETER;
5526 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5527 fname ? fname : fsp->fsp_name,
5528 (unsigned int)num_file_acls,
5529 (unsigned int)num_def_acls));
5531 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5532 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5533 return map_nt_error_from_unix(errno);
5536 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5537 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5538 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5539 return map_nt_error_from_unix(errno);
5541 return NT_STATUS_OK;
5545 /****************************************************************************
5546 Deal with SMB_SET_POSIX_LOCK.
5547 ****************************************************************************/
5549 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5550 struct smb_request *req,
5558 bool blocking_lock = False;
5559 enum brl_type lock_type;
5561 NTSTATUS status = NT_STATUS_OK;
5563 if (fsp == NULL || fsp->fh->fd == -1) {
5564 return NT_STATUS_INVALID_HANDLE;
5567 if (total_data != POSIX_LOCK_DATA_SIZE) {
5568 return NT_STATUS_INVALID_PARAMETER;
5571 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5572 case POSIX_LOCK_TYPE_READ:
5573 lock_type = READ_LOCK;
5575 case POSIX_LOCK_TYPE_WRITE:
5576 /* Return the right POSIX-mappable error code for files opened read-only. */
5577 if (!fsp->can_write) {
5578 return NT_STATUS_INVALID_HANDLE;
5580 lock_type = WRITE_LOCK;
5582 case POSIX_LOCK_TYPE_UNLOCK:
5583 lock_type = UNLOCK_LOCK;
5586 return NT_STATUS_INVALID_PARAMETER;
5589 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5590 blocking_lock = False;
5591 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5592 blocking_lock = True;
5594 return NT_STATUS_INVALID_PARAMETER;
5597 if (!lp_blocking_locks(SNUM(conn))) {
5598 blocking_lock = False;
5601 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5602 #if defined(HAVE_LONGLONG)
5603 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5604 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5605 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5606 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5607 #else /* HAVE_LONGLONG */
5608 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5609 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5610 #endif /* HAVE_LONGLONG */
5612 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5613 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5615 (unsigned int)lock_type,
5616 (unsigned int)lock_pid,
5620 if (lock_type == UNLOCK_LOCK) {
5621 status = do_unlock(smbd_messaging_context(),
5628 uint32 block_smbpid;
5630 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5641 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5643 * A blocking lock was requested. Package up
5644 * this smb into a queued request and push it
5645 * onto the blocking lock queue.
5647 if(push_blocking_lock_request(br_lck,
5650 -1, /* infinite timeout. */
5658 TALLOC_FREE(br_lck);
5662 TALLOC_FREE(br_lck);
5668 /****************************************************************************
5669 Deal with SMB_INFO_STANDARD.
5670 ****************************************************************************/
5672 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5677 const SMB_STRUCT_STAT *psbuf)
5679 struct timespec ts[2];
5681 if (total_data < 12) {
5682 return NT_STATUS_INVALID_PARAMETER;
5686 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5688 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5690 DEBUG(10,("smb_set_info_standard: file %s\n",
5691 fname ? fname : fsp->fsp_name ));
5693 return smb_set_file_time(conn,
5701 /****************************************************************************
5702 Deal with SMB_SET_FILE_BASIC_INFO.
5703 ****************************************************************************/
5705 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5710 SMB_STRUCT_STAT *psbuf)
5712 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5713 struct timespec write_time;
5714 struct timespec changed_time;
5716 struct timespec ts[2];
5717 NTSTATUS status = NT_STATUS_OK;
5718 bool setting_write_time = true;
5720 if (total_data < 36) {
5721 return NT_STATUS_INVALID_PARAMETER;
5724 /* Set the attributes */
5725 dosmode = IVAL(pdata,32);
5726 status = smb_set_file_dosmode(conn,
5730 if (!NT_STATUS_IS_OK(status)) {
5734 /* Ignore create time at offset pdata. */
5737 ts[0] = interpret_long_date(pdata+8);
5739 write_time = interpret_long_date(pdata+16);
5740 changed_time = interpret_long_date(pdata+24);
5743 ts[1] = timespec_min(&write_time, &changed_time);
5745 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5749 /* Prefer a defined time to an undefined one. */
5750 if (null_timespec(ts[1])) {
5751 if (null_timespec(write_time)) {
5752 ts[1] = changed_time;
5753 setting_write_time = false;
5759 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5760 fname ? fname : fsp->fsp_name ));
5762 return smb_set_file_time(conn,
5767 setting_write_time);
5770 /****************************************************************************
5771 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5772 ****************************************************************************/
5774 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5775 struct smb_request *req,
5780 SMB_STRUCT_STAT *psbuf)
5782 uint64_t allocation_size = 0;
5783 NTSTATUS status = NT_STATUS_OK;
5784 files_struct *new_fsp = NULL;
5786 if (!VALID_STAT(*psbuf)) {
5787 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5790 if (total_data < 8) {
5791 return NT_STATUS_INVALID_PARAMETER;
5794 allocation_size = (uint64_t)IVAL(pdata,0);
5795 #ifdef LARGE_SMB_OFF_T
5796 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
5797 #else /* LARGE_SMB_OFF_T */
5798 if (IVAL(pdata,4) != 0) {
5799 /* more than 32 bits? */
5800 return NT_STATUS_INVALID_PARAMETER;
5802 #endif /* LARGE_SMB_OFF_T */
5804 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5805 fname, (double)allocation_size ));
5807 if (allocation_size) {
5808 allocation_size = smb_roundup(conn, allocation_size);
5811 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5812 fname, (double)allocation_size ));
5814 if (fsp && fsp->fh->fd != -1) {
5815 /* Open file handle. */
5816 /* Only change if needed. */
5817 if (allocation_size != get_file_size(*psbuf)) {
5818 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5819 return map_nt_error_from_unix(errno);
5822 /* But always update the time. */
5824 * This is equivalent to a write. Ensure it's seen immediately
5825 * if there are no pending writes.
5827 trigger_write_time_update_immediate(fsp);
5828 return NT_STATUS_OK;
5831 /* Pathname or stat or directory file. */
5833 status = SMB_VFS_CREATE_FILE(
5836 0, /* root_dir_fid */
5838 0, /* create_file_flags */
5839 FILE_WRITE_DATA, /* access_mask */
5840 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5842 FILE_OPEN, /* create_disposition*/
5843 0, /* create_options */
5844 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5845 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5846 0, /* allocation_size */
5849 &new_fsp, /* result */
5853 if (!NT_STATUS_IS_OK(status)) {
5854 /* NB. We check for open_was_deferred in the caller. */
5858 /* Only change if needed. */
5859 if (allocation_size != get_file_size(*psbuf)) {
5860 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5861 status = map_nt_error_from_unix(errno);
5862 close_file(req, new_fsp, NORMAL_CLOSE);
5867 /* Changing the allocation size should set the last mod time. */
5869 * This is equivalent to a write. Ensure it's seen immediately
5870 * if there are no pending writes.
5872 trigger_write_time_update_immediate(new_fsp);
5874 close_file(req, new_fsp, NORMAL_CLOSE);
5875 return NT_STATUS_OK;
5878 /****************************************************************************
5879 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5880 ****************************************************************************/
5882 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5883 struct smb_request *req,
5888 SMB_STRUCT_STAT *psbuf)
5892 if (total_data < 8) {
5893 return NT_STATUS_INVALID_PARAMETER;
5896 size = IVAL(pdata,0);
5897 #ifdef LARGE_SMB_OFF_T
5898 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5899 #else /* LARGE_SMB_OFF_T */
5900 if (IVAL(pdata,4) != 0) {
5901 /* more than 32 bits? */
5902 return NT_STATUS_INVALID_PARAMETER;
5904 #endif /* LARGE_SMB_OFF_T */
5905 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5906 "file %s to %.0f\n", fname, (double)size ));
5908 return smb_set_file_size(conn, req,
5915 /****************************************************************************
5916 Allow a UNIX info mknod.
5917 ****************************************************************************/
5919 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5923 SMB_STRUCT_STAT *psbuf)
5925 uint32 file_type = IVAL(pdata,56);
5926 #if defined(HAVE_MAKEDEV)
5927 uint32 dev_major = IVAL(pdata,60);
5928 uint32 dev_minor = IVAL(pdata,68);
5930 SMB_DEV_T dev = (SMB_DEV_T)0;
5931 uint32 raw_unixmode = IVAL(pdata,84);
5935 if (total_data < 100) {
5936 return NT_STATUS_INVALID_PARAMETER;
5939 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5940 if (!NT_STATUS_IS_OK(status)) {
5944 #if defined(HAVE_MAKEDEV)
5945 dev = makedev(dev_major, dev_minor);
5948 switch (file_type) {
5949 #if defined(S_IFIFO)
5950 case UNIX_TYPE_FIFO:
5951 unixmode |= S_IFIFO;
5954 #if defined(S_IFSOCK)
5955 case UNIX_TYPE_SOCKET:
5956 unixmode |= S_IFSOCK;
5959 #if defined(S_IFCHR)
5960 case UNIX_TYPE_CHARDEV:
5961 unixmode |= S_IFCHR;
5964 #if defined(S_IFBLK)
5965 case UNIX_TYPE_BLKDEV:
5966 unixmode |= S_IFBLK;
5970 return NT_STATUS_INVALID_PARAMETER;
5973 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5974 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5976 /* Ok - do the mknod. */
5977 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5978 return map_nt_error_from_unix(errno);
5981 /* If any of the other "set" calls fail we
5982 * don't want to end up with a half-constructed mknod.
5985 if (lp_inherit_perms(SNUM(conn))) {
5987 if (!parent_dirname(talloc_tos(), fname, &parent, NULL)) {
5988 return NT_STATUS_NO_MEMORY;
5990 inherit_access_posix_acl(conn, parent, fname, unixmode);
5991 TALLOC_FREE(parent);
5994 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5995 status = map_nt_error_from_unix(errno);
5996 SMB_VFS_UNLINK(conn,fname);
5999 return NT_STATUS_OK;
6002 /****************************************************************************
6003 Deal with SMB_SET_FILE_UNIX_BASIC.
6004 ****************************************************************************/
6006 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6007 struct smb_request *req,
6012 SMB_STRUCT_STAT *psbuf)
6014 struct timespec ts[2];
6015 uint32 raw_unixmode;
6018 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6019 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6020 NTSTATUS status = NT_STATUS_OK;
6021 bool delete_on_fail = False;
6022 enum perm_type ptype;
6024 if (total_data < 100) {
6025 return NT_STATUS_INVALID_PARAMETER;
6028 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6029 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6030 size=IVAL(pdata,0); /* first 8 Bytes are size */
6031 #ifdef LARGE_SMB_OFF_T
6032 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6033 #else /* LARGE_SMB_OFF_T */
6034 if (IVAL(pdata,4) != 0) {
6035 /* more than 32 bits? */
6036 return NT_STATUS_INVALID_PARAMETER;
6038 #endif /* LARGE_SMB_OFF_T */
6041 ts[0] = interpret_long_date(pdata+24); /* access_time */
6042 ts[1] = interpret_long_date(pdata+32); /* modification_time */
6043 set_owner = (uid_t)IVAL(pdata,40);
6044 set_grp = (gid_t)IVAL(pdata,48);
6045 raw_unixmode = IVAL(pdata,84);
6047 if (VALID_STAT(*psbuf)) {
6048 if (S_ISDIR(psbuf->st_mode)) {
6049 ptype = PERM_EXISTING_DIR;
6051 ptype = PERM_EXISTING_FILE;
6054 ptype = PERM_NEW_FILE;
6057 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
6058 if (!NT_STATUS_IS_OK(status)) {
6062 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
6063 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6064 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
6066 if (!VALID_STAT(*psbuf)) {
6068 * The only valid use of this is to create character and block
6069 * devices, and named pipes. This is deprecated (IMHO) and
6070 * a new info level should be used for mknod. JRA.
6073 status = smb_unix_mknod(conn,
6078 if (!NT_STATUS_IS_OK(status)) {
6082 /* Ensure we don't try and change anything else. */
6083 raw_unixmode = SMB_MODE_NO_CHANGE;
6084 size = get_file_size(*psbuf);
6085 ts[0] = get_atimespec(psbuf);
6086 ts[1] = get_mtimespec(psbuf);
6088 * We continue here as we might want to change the
6091 delete_on_fail = True;
6095 /* Horrible backwards compatibility hack as an old server bug
6096 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6100 size = get_file_size(*psbuf);
6105 * Deal with the UNIX specific mode set.
6108 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6109 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6110 (unsigned int)unixmode, fname ));
6111 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
6112 return map_nt_error_from_unix(errno);
6117 * Deal with the UNIX specific uid set.
6120 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
6123 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6124 (unsigned int)set_owner, fname ));
6126 if (S_ISLNK(psbuf->st_mode)) {
6127 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6129 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6133 status = map_nt_error_from_unix(errno);
6134 if (delete_on_fail) {
6135 SMB_VFS_UNLINK(conn,fname);
6142 * Deal with the UNIX specific gid set.
6145 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
6146 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6147 (unsigned int)set_owner, fname ));
6148 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6149 status = map_nt_error_from_unix(errno);
6150 if (delete_on_fail) {
6151 SMB_VFS_UNLINK(conn,fname);
6157 /* Deal with any size changes. */
6159 status = smb_set_file_size(conn, req,
6164 if (!NT_STATUS_IS_OK(status)) {
6168 /* Deal with any time changes. */
6170 return smb_set_file_time(conn,
6178 /****************************************************************************
6179 Deal with SMB_SET_FILE_UNIX_INFO2.
6180 ****************************************************************************/
6182 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6183 struct smb_request *req,
6188 SMB_STRUCT_STAT *psbuf)
6194 if (total_data < 116) {
6195 return NT_STATUS_INVALID_PARAMETER;
6198 /* Start by setting all the fields that are common between UNIX_BASIC
6201 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6203 if (!NT_STATUS_IS_OK(status)) {
6207 smb_fflags = IVAL(pdata, 108);
6208 smb_fmask = IVAL(pdata, 112);
6210 /* NB: We should only attempt to alter the file flags if the client
6211 * sends a non-zero mask.
6213 if (smb_fmask != 0) {
6214 int stat_fflags = 0;
6216 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6218 /* Client asked to alter a flag we don't understand. */
6219 return NT_STATUS_INVALID_PARAMETER;
6222 if (fsp && fsp->fh->fd != -1) {
6223 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6224 return NT_STATUS_NOT_SUPPORTED;
6226 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6227 return map_nt_error_from_unix(errno);
6232 /* XXX: need to add support for changing the create_time here. You
6233 * can do this for paths on Darwin with setattrlist(2). The right way
6234 * to hook this up is probably by extending the VFS utimes interface.
6237 return NT_STATUS_OK;
6240 /****************************************************************************
6241 Create a directory with POSIX semantics.
6242 ****************************************************************************/
6244 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6245 struct smb_request *req,
6249 SMB_STRUCT_STAT *psbuf,
6250 int *pdata_return_size)
6252 NTSTATUS status = NT_STATUS_OK;
6253 uint32 raw_unixmode = 0;
6254 uint32 mod_unixmode = 0;
6255 mode_t unixmode = (mode_t)0;
6256 files_struct *fsp = NULL;
6257 uint16 info_level_return = 0;
6259 char *pdata = *ppdata;
6261 if (total_data < 18) {
6262 return NT_STATUS_INVALID_PARAMETER;
6265 raw_unixmode = IVAL(pdata,8);
6266 /* Next 4 bytes are not yet defined. */
6268 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6269 if (!NT_STATUS_IS_OK(status)) {
6273 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6275 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6276 fname, (unsigned int)unixmode ));
6278 status = SMB_VFS_CREATE_FILE(
6281 0, /* root_dir_fid */
6283 0, /* create_file_flags */
6284 FILE_READ_ATTRIBUTES, /* access_mask */
6285 FILE_SHARE_NONE, /* share_access */
6286 FILE_CREATE, /* create_disposition*/
6287 FILE_DIRECTORY_FILE, /* create_options */
6288 mod_unixmode, /* file_attributes */
6289 0, /* oplock_request */
6290 0, /* allocation_size */
6297 if (NT_STATUS_IS_OK(status)) {
6298 close_file(req, fsp, NORMAL_CLOSE);
6301 info_level_return = SVAL(pdata,16);
6303 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6304 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6305 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6306 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6308 *pdata_return_size = 12;
6311 /* Realloc the data size */
6312 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6313 if (*ppdata == NULL) {
6314 *pdata_return_size = 0;
6315 return NT_STATUS_NO_MEMORY;
6319 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6320 SSVAL(pdata,2,0); /* No fnum. */
6321 SIVAL(pdata,4,info); /* Was directory created. */
6323 switch (info_level_return) {
6324 case SMB_QUERY_FILE_UNIX_BASIC:
6325 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6326 SSVAL(pdata,10,0); /* Padding. */
6327 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6329 case SMB_QUERY_FILE_UNIX_INFO2:
6330 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6331 SSVAL(pdata,10,0); /* Padding. */
6332 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6335 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6336 SSVAL(pdata,10,0); /* Padding. */
6343 /****************************************************************************
6344 Open/Create a file with POSIX semantics.
6345 ****************************************************************************/
6347 static NTSTATUS smb_posix_open(connection_struct *conn,
6348 struct smb_request *req,
6352 SMB_STRUCT_STAT *psbuf,
6353 int *pdata_return_size)
6355 bool extended_oplock_granted = False;
6356 char *pdata = *ppdata;
6358 uint32 wire_open_mode = 0;
6359 uint32 raw_unixmode = 0;
6360 uint32 mod_unixmode = 0;
6361 uint32 create_disp = 0;
6362 uint32 access_mask = 0;
6363 uint32 create_options = 0;
6364 NTSTATUS status = NT_STATUS_OK;
6365 mode_t unixmode = (mode_t)0;
6366 files_struct *fsp = NULL;
6367 int oplock_request = 0;
6369 uint16 info_level_return = 0;
6371 if (total_data < 18) {
6372 return NT_STATUS_INVALID_PARAMETER;
6375 flags = IVAL(pdata,0);
6376 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6377 if (oplock_request) {
6378 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6381 wire_open_mode = IVAL(pdata,4);
6383 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6384 return smb_posix_mkdir(conn, req,
6392 switch (wire_open_mode & SMB_ACCMODE) {
6394 access_mask = FILE_READ_DATA;
6397 access_mask = FILE_WRITE_DATA;
6400 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6403 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6404 (unsigned int)wire_open_mode ));
6405 return NT_STATUS_INVALID_PARAMETER;
6408 wire_open_mode &= ~SMB_ACCMODE;
6410 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6411 create_disp = FILE_CREATE;
6412 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6413 create_disp = FILE_OVERWRITE_IF;
6414 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6415 create_disp = FILE_OPEN_IF;
6417 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6418 (unsigned int)wire_open_mode ));
6419 return NT_STATUS_INVALID_PARAMETER;
6422 raw_unixmode = IVAL(pdata,8);
6423 /* Next 4 bytes are not yet defined. */
6425 status = unix_perms_from_wire(conn,
6428 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6431 if (!NT_STATUS_IS_OK(status)) {
6435 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6437 if (wire_open_mode & SMB_O_SYNC) {
6438 create_options |= FILE_WRITE_THROUGH;
6440 if (wire_open_mode & SMB_O_APPEND) {
6441 access_mask |= FILE_APPEND_DATA;
6443 if (wire_open_mode & SMB_O_DIRECT) {
6444 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6447 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6449 (unsigned int)wire_open_mode,
6450 (unsigned int)unixmode ));
6452 status = SMB_VFS_CREATE_FILE(
6455 0, /* root_dir_fid */
6457 0, /* create_file_flags */
6458 access_mask, /* access_mask */
6459 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6461 create_disp, /* create_disposition*/
6462 0, /* create_options */
6463 mod_unixmode, /* file_attributes */
6464 oplock_request, /* oplock_request */
6465 0, /* allocation_size */
6472 if (!NT_STATUS_IS_OK(status)) {
6476 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6477 extended_oplock_granted = True;
6480 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6481 extended_oplock_granted = True;
6484 info_level_return = SVAL(pdata,16);
6486 /* Allocate the correct return size. */
6488 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6489 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6490 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6491 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6493 *pdata_return_size = 12;
6496 /* Realloc the data size */
6497 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6498 if (*ppdata == NULL) {
6499 close_file(req, fsp, ERROR_CLOSE);
6500 *pdata_return_size = 0;
6501 return NT_STATUS_NO_MEMORY;
6505 if (extended_oplock_granted) {
6506 if (flags & REQUEST_BATCH_OPLOCK) {
6507 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6509 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6511 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6512 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6514 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6517 SSVAL(pdata,2,fsp->fnum);
6518 SIVAL(pdata,4,info); /* Was file created etc. */
6520 switch (info_level_return) {
6521 case SMB_QUERY_FILE_UNIX_BASIC:
6522 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6523 SSVAL(pdata,10,0); /* padding. */
6524 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6526 case SMB_QUERY_FILE_UNIX_INFO2:
6527 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6528 SSVAL(pdata,10,0); /* padding. */
6529 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6532 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6533 SSVAL(pdata,10,0); /* padding. */
6536 return NT_STATUS_OK;
6539 /****************************************************************************
6540 Delete a file with POSIX semantics.
6541 ****************************************************************************/
6543 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6544 struct smb_request *req,
6548 SMB_STRUCT_STAT *psbuf)
6550 NTSTATUS status = NT_STATUS_OK;
6551 files_struct *fsp = NULL;
6555 int create_options = 0;
6557 struct share_mode_lock *lck = NULL;
6559 if (total_data < 2) {
6560 return NT_STATUS_INVALID_PARAMETER;
6563 flags = SVAL(pdata,0);
6565 if (!VALID_STAT(*psbuf)) {
6566 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6569 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6570 !VALID_STAT_OF_DIR(*psbuf)) {
6571 return NT_STATUS_NOT_A_DIRECTORY;
6574 DEBUG(10,("smb_posix_unlink: %s %s\n",
6575 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6578 if (VALID_STAT_OF_DIR(*psbuf)) {
6579 create_options |= FILE_DIRECTORY_FILE;
6582 status = SMB_VFS_CREATE_FILE(
6585 0, /* root_dir_fid */
6587 0, /* create_file_flags */
6588 DELETE_ACCESS, /* access_mask */
6589 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6591 FILE_OPEN, /* create_disposition*/
6592 create_options, /* create_options */
6593 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
6594 0, /* oplock_request */
6595 0, /* allocation_size */
6602 if (!NT_STATUS_IS_OK(status)) {
6607 * Don't lie to client. If we can't really delete due to
6608 * non-POSIX opens return SHARING_VIOLATION.
6611 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6614 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6615 "lock for file %s\n", fsp->fsp_name));
6616 close_file(req, fsp, NORMAL_CLOSE);
6617 return NT_STATUS_INVALID_PARAMETER;
6621 * See if others still have the file open. If this is the case, then
6622 * don't delete. If all opens are POSIX delete we can set the delete
6623 * on close disposition.
6625 for (i=0; i<lck->num_share_modes; i++) {
6626 struct share_mode_entry *e = &lck->share_modes[i];
6627 if (is_valid_share_mode_entry(e)) {
6628 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6631 /* Fail with sharing violation. */
6632 close_file(req, fsp, NORMAL_CLOSE);
6634 return NT_STATUS_SHARING_VIOLATION;
6639 * Set the delete on close.
6641 status = smb_set_file_disposition_info(conn,
6648 if (!NT_STATUS_IS_OK(status)) {
6649 close_file(req, fsp, NORMAL_CLOSE);
6654 return close_file(req, fsp, NORMAL_CLOSE);
6657 /****************************************************************************
6658 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6659 ****************************************************************************/
6661 static void call_trans2setfilepathinfo(connection_struct *conn,
6662 struct smb_request *req,
6663 unsigned int tran_call,
6664 char **pparams, int total_params,
6665 char **ppdata, int total_data,
6666 unsigned int max_data_bytes)
6668 char *params = *pparams;
6669 char *pdata = *ppdata;
6671 SMB_STRUCT_STAT sbuf;
6673 files_struct *fsp = NULL;
6674 NTSTATUS status = NT_STATUS_OK;
6675 int data_return_size = 0;
6676 TALLOC_CTX *ctx = talloc_tos();
6679 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6685 if (tran_call == TRANSACT2_SETFILEINFO) {
6686 if (total_params < 4) {
6687 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6691 fsp = file_fsp(req, SVAL(params,0));
6692 /* Basic check for non-null fsp. */
6693 if (!check_fsp_open(conn, req, fsp)) {
6696 info_level = SVAL(params,2);
6698 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6700 reply_nterror(req, NT_STATUS_NO_MEMORY);
6704 if(fsp->is_directory || fsp->fh->fd == -1) {
6706 * This is actually a SETFILEINFO on a directory
6707 * handle (returned from an NT SMB). NT5.0 seems
6708 * to do this call. JRA.
6710 if (INFO_LEVEL_IS_UNIX(info_level)) {
6711 /* Always do lstat for UNIX calls. */
6712 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6713 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6714 reply_unixerror(req,ERRDOS,ERRbadpath);
6718 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6719 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6720 reply_unixerror(req,ERRDOS,ERRbadpath);
6724 } else if (fsp->print_file) {
6726 * Doing a DELETE_ON_CLOSE should cancel a print job.
6728 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6729 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6731 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6734 send_trans2_replies(conn, req, params, 2,
6739 reply_unixerror(req, ERRDOS, ERRbadpath);
6744 * Original code - this is an open file.
6746 if (!check_fsp(conn, req, fsp)) {
6750 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6751 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6752 reply_unixerror(req, ERRDOS, ERRbadfid);
6758 if (total_params < 7) {
6759 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6763 info_level = SVAL(params,0);
6764 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
6765 total_params - 6, STR_TERMINATE,
6767 if (!NT_STATUS_IS_OK(status)) {
6768 reply_nterror(req, status);
6772 status = resolve_dfspath(ctx, conn,
6773 req->flags2 & FLAGS2_DFS_PATHNAMES,
6776 if (!NT_STATUS_IS_OK(status)) {
6777 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6778 reply_botherror(req,
6779 NT_STATUS_PATH_NOT_COVERED,
6780 ERRSRV, ERRbadpath);
6783 reply_nterror(req, status);
6787 status = unix_convert(ctx, conn, fname, False,
6788 &fname, NULL, &sbuf);
6789 if (!NT_STATUS_IS_OK(status)) {
6790 reply_nterror(req, status);
6794 status = check_name(conn, fname);
6795 if (!NT_STATUS_IS_OK(status)) {
6796 reply_nterror(req, status);
6800 if (INFO_LEVEL_IS_UNIX(info_level)) {
6802 * For CIFS UNIX extensions the target name may not exist.
6805 /* Always do lstat for UNIX calls. */
6806 SMB_VFS_LSTAT(conn,fname,&sbuf);
6808 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6809 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6810 reply_unixerror(req, ERRDOS, ERRbadpath);
6815 if (!CAN_WRITE(conn)) {
6816 reply_doserror(req, ERRSRV, ERRaccess);
6820 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6821 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6825 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6826 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6828 /* Realloc the parameter size */
6829 *pparams = (char *)SMB_REALLOC(*pparams,2);
6830 if (*pparams == NULL) {
6831 reply_nterror(req, NT_STATUS_NO_MEMORY);
6838 switch (info_level) {
6840 case SMB_INFO_STANDARD:
6842 status = smb_set_info_standard(conn,
6851 case SMB_INFO_SET_EA:
6853 status = smb_info_set_ea(conn,
6861 case SMB_SET_FILE_BASIC_INFO:
6862 case SMB_FILE_BASIC_INFORMATION:
6864 status = smb_set_file_basic_info(conn,
6873 case SMB_FILE_ALLOCATION_INFORMATION:
6874 case SMB_SET_FILE_ALLOCATION_INFO:
6876 status = smb_set_file_allocation_info(conn, req,
6885 case SMB_FILE_END_OF_FILE_INFORMATION:
6886 case SMB_SET_FILE_END_OF_FILE_INFO:
6888 status = smb_set_file_end_of_file_info(conn, req,
6897 case SMB_FILE_DISPOSITION_INFORMATION:
6898 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6901 /* JRA - We used to just ignore this on a path ?
6902 * Shouldn't this be invalid level on a pathname
6905 if (tran_call != TRANSACT2_SETFILEINFO) {
6906 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6909 status = smb_set_file_disposition_info(conn,
6918 case SMB_FILE_POSITION_INFORMATION:
6920 status = smb_file_position_information(conn,
6927 /* From tridge Samba4 :
6928 * MODE_INFORMATION in setfileinfo (I have no
6929 * idea what "mode information" on a file is - it takes a value of 0,
6930 * 2, 4 or 6. What could it be?).
6933 case SMB_FILE_MODE_INFORMATION:
6935 status = smb_file_mode_information(conn,
6942 * CIFS UNIX extensions.
6945 case SMB_SET_FILE_UNIX_BASIC:
6947 status = smb_set_file_unix_basic(conn, req,
6956 case SMB_SET_FILE_UNIX_INFO2:
6958 status = smb_set_file_unix_info2(conn, req,
6967 case SMB_SET_FILE_UNIX_LINK:
6969 if (tran_call != TRANSACT2_SETPATHINFO) {
6970 /* We must have a pathname for this. */
6971 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6974 status = smb_set_file_unix_link(conn, req, pdata,
6979 case SMB_SET_FILE_UNIX_HLINK:
6981 if (tran_call != TRANSACT2_SETPATHINFO) {
6982 /* We must have a pathname for this. */
6983 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6986 status = smb_set_file_unix_hlink(conn, req,
6992 case SMB_FILE_RENAME_INFORMATION:
6994 status = smb_file_rename_information(conn, req,
7000 #if defined(HAVE_POSIX_ACLS)
7001 case SMB_SET_POSIX_ACL:
7003 status = smb_set_posix_acl(conn,
7013 case SMB_SET_POSIX_LOCK:
7015 if (tran_call != TRANSACT2_SETFILEINFO) {
7016 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7019 status = smb_set_posix_lock(conn, req,
7020 pdata, total_data, fsp);
7024 case SMB_POSIX_PATH_OPEN:
7026 if (tran_call != TRANSACT2_SETPATHINFO) {
7027 /* We must have a pathname for this. */
7028 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7032 status = smb_posix_open(conn, req,
7041 case SMB_POSIX_PATH_UNLINK:
7043 if (tran_call != TRANSACT2_SETPATHINFO) {
7044 /* We must have a pathname for this. */
7045 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7049 status = smb_posix_unlink(conn, req,
7058 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7063 if (!NT_STATUS_IS_OK(status)) {
7064 if (open_was_deferred(req->mid)) {
7065 /* We have re-scheduled this call. */
7068 if (blocking_lock_was_deferred(req->mid)) {
7069 /* We have re-scheduled this call. */
7072 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7073 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7074 ERRSRV, ERRbadpath);
7077 if (info_level == SMB_POSIX_PATH_OPEN) {
7078 reply_openerror(req, status);
7082 reply_nterror(req, status);
7087 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7093 /****************************************************************************
7094 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7095 ****************************************************************************/
7097 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7098 char **pparams, int total_params,
7099 char **ppdata, int total_data,
7100 unsigned int max_data_bytes)
7102 char *params = *pparams;
7103 char *pdata = *ppdata;
7104 char *directory = NULL;
7105 SMB_STRUCT_STAT sbuf;
7106 NTSTATUS status = NT_STATUS_OK;
7107 struct ea_list *ea_list = NULL;
7108 TALLOC_CTX *ctx = talloc_tos();
7110 if (!CAN_WRITE(conn)) {
7111 reply_doserror(req, ERRSRV, ERRaccess);
7115 if (total_params < 5) {
7116 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7120 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7121 total_params - 4, STR_TERMINATE,
7123 if (!NT_STATUS_IS_OK(status)) {
7124 reply_nterror(req, status);
7128 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7130 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
7131 if (!NT_STATUS_IS_OK(status)) {
7132 reply_nterror(req, status);
7136 status = check_name(conn, directory);
7137 if (!NT_STATUS_IS_OK(status)) {
7138 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
7139 reply_nterror(req, status);
7143 /* Any data in this call is an EA list. */
7144 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7145 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7150 * OS/2 workplace shell seems to send SET_EA requests of "null"
7151 * length (4 bytes containing IVAL 4).
7152 * They seem to have no effect. Bug #3212. JRA.
7155 if (total_data != 4) {
7156 if (total_data < 10) {
7157 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7161 if (IVAL(pdata,0) > total_data) {
7162 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7163 IVAL(pdata,0), (unsigned int)total_data));
7164 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7168 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7171 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7175 /* If total_data == 4 Windows doesn't care what values
7176 * are placed in that field, it just ignores them.
7177 * The System i QNTC IBM SMB client puts bad values here,
7178 * so ignore them. */
7180 status = create_directory(conn, req, directory);
7182 if (!NT_STATUS_IS_OK(status)) {
7183 reply_nterror(req, status);
7187 /* Try and set any given EA. */
7189 status = set_ea(conn, NULL, directory, ea_list);
7190 if (!NT_STATUS_IS_OK(status)) {
7191 reply_nterror(req, status);
7196 /* Realloc the parameter and data sizes */
7197 *pparams = (char *)SMB_REALLOC(*pparams,2);
7198 if(*pparams == NULL) {
7199 reply_nterror(req, NT_STATUS_NO_MEMORY);
7206 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7211 /****************************************************************************
7212 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7213 We don't actually do this - we just send a null response.
7214 ****************************************************************************/
7216 static void call_trans2findnotifyfirst(connection_struct *conn,
7217 struct smb_request *req,
7218 char **pparams, int total_params,
7219 char **ppdata, int total_data,
7220 unsigned int max_data_bytes)
7222 char *params = *pparams;
7225 if (total_params < 6) {
7226 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7230 info_level = SVAL(params,4);
7231 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7233 switch (info_level) {
7238 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7242 /* Realloc the parameter and data sizes */
7243 *pparams = (char *)SMB_REALLOC(*pparams,6);
7244 if (*pparams == NULL) {
7245 reply_nterror(req, NT_STATUS_NO_MEMORY);
7250 SSVAL(params,0,fnf_handle);
7251 SSVAL(params,2,0); /* No changes */
7252 SSVAL(params,4,0); /* No EA errors */
7259 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7264 /****************************************************************************
7265 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7266 changes). Currently this does nothing.
7267 ****************************************************************************/
7269 static void call_trans2findnotifynext(connection_struct *conn,
7270 struct smb_request *req,
7271 char **pparams, int total_params,
7272 char **ppdata, int total_data,
7273 unsigned int max_data_bytes)
7275 char *params = *pparams;
7277 DEBUG(3,("call_trans2findnotifynext\n"));
7279 /* Realloc the parameter and data sizes */
7280 *pparams = (char *)SMB_REALLOC(*pparams,4);
7281 if (*pparams == NULL) {
7282 reply_nterror(req, NT_STATUS_NO_MEMORY);
7287 SSVAL(params,0,0); /* No changes */
7288 SSVAL(params,2,0); /* No EA errors */
7290 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7295 /****************************************************************************
7296 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7297 ****************************************************************************/
7299 static void call_trans2getdfsreferral(connection_struct *conn,
7300 struct smb_request *req,
7301 char **pparams, int total_params,
7302 char **ppdata, int total_data,
7303 unsigned int max_data_bytes)
7305 char *params = *pparams;
7306 char *pathname = NULL;
7308 int max_referral_level;
7309 NTSTATUS status = NT_STATUS_OK;
7310 TALLOC_CTX *ctx = talloc_tos();
7312 DEBUG(10,("call_trans2getdfsreferral\n"));
7314 if (total_params < 3) {
7315 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7319 max_referral_level = SVAL(params,0);
7321 if(!lp_host_msdfs()) {
7322 reply_doserror(req, ERRDOS, ERRbadfunc);
7326 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7327 total_params - 2, STR_TERMINATE);
7329 reply_nterror(req, NT_STATUS_NOT_FOUND);
7332 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7333 ppdata,&status)) < 0) {
7334 reply_nterror(req, status);
7338 SSVAL(req->inbuf, smb_flg2,
7339 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7340 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7345 #define LMCAT_SPL 0x53
7346 #define LMFUNC_GETJOBID 0x60
7348 /****************************************************************************
7349 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7350 ****************************************************************************/
7352 static void call_trans2ioctl(connection_struct *conn,
7353 struct smb_request *req,
7354 char **pparams, int total_params,
7355 char **ppdata, int total_data,
7356 unsigned int max_data_bytes)
7358 char *pdata = *ppdata;
7359 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7361 /* check for an invalid fid before proceeding */
7364 reply_doserror(req, ERRDOS, ERRbadfid);
7368 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7369 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7370 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7371 if (*ppdata == NULL) {
7372 reply_nterror(req, NT_STATUS_NO_MEMORY);
7377 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7378 CAN ACCEPT THIS IN UNICODE. JRA. */
7380 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7381 srvstr_push(pdata, req->flags2, pdata + 2,
7382 global_myname(), 15,
7383 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7384 srvstr_push(pdata, req->flags2, pdata+18,
7385 lp_servicename(SNUM(conn)), 13,
7386 STR_ASCII|STR_TERMINATE); /* Service name */
7387 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7392 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7393 reply_doserror(req, ERRSRV, ERRerror);
7396 /****************************************************************************
7397 Reply to a SMBfindclose (stop trans2 directory search).
7398 ****************************************************************************/
7400 void reply_findclose(struct smb_request *req)
7404 START_PROFILE(SMBfindclose);
7407 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7408 END_PROFILE(SMBfindclose);
7412 dptr_num = SVALS(req->vwv+0, 0);
7414 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7416 dptr_close(&dptr_num);
7418 reply_outbuf(req, 0, 0);
7420 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7422 END_PROFILE(SMBfindclose);
7426 /****************************************************************************
7427 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7428 ****************************************************************************/
7430 void reply_findnclose(struct smb_request *req)
7434 START_PROFILE(SMBfindnclose);
7437 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7438 END_PROFILE(SMBfindnclose);
7442 dptr_num = SVAL(req->vwv+0, 0);
7444 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7446 /* We never give out valid handles for a
7447 findnotifyfirst - so any dptr_num is ok here.
7450 reply_outbuf(req, 0, 0);
7452 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7454 END_PROFILE(SMBfindnclose);
7458 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7459 struct trans_state *state)
7461 if (Protocol >= PROTOCOL_NT1) {
7462 req->flags2 |= 0x40; /* IS_LONG_NAME */
7463 SSVAL(req->inbuf,smb_flg2,req->flags2);
7466 if (conn->encrypt_level == Required && !req->encrypted) {
7467 if (state->call != TRANSACT2_QFSINFO &&
7468 state->call != TRANSACT2_SETFSINFO) {
7469 DEBUG(0,("handle_trans2: encryption required "
7471 (unsigned int)state->call));
7472 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7477 /* Now we must call the relevant TRANS2 function */
7478 switch(state->call) {
7479 case TRANSACT2_OPEN:
7481 START_PROFILE(Trans2_open);
7482 call_trans2open(conn, req,
7483 &state->param, state->total_param,
7484 &state->data, state->total_data,
7485 state->max_data_return);
7486 END_PROFILE(Trans2_open);
7490 case TRANSACT2_FINDFIRST:
7492 START_PROFILE(Trans2_findfirst);
7493 call_trans2findfirst(conn, req,
7494 &state->param, state->total_param,
7495 &state->data, state->total_data,
7496 state->max_data_return);
7497 END_PROFILE(Trans2_findfirst);
7501 case TRANSACT2_FINDNEXT:
7503 START_PROFILE(Trans2_findnext);
7504 call_trans2findnext(conn, req,
7505 &state->param, state->total_param,
7506 &state->data, state->total_data,
7507 state->max_data_return);
7508 END_PROFILE(Trans2_findnext);
7512 case TRANSACT2_QFSINFO:
7514 START_PROFILE(Trans2_qfsinfo);
7515 call_trans2qfsinfo(conn, req,
7516 &state->param, state->total_param,
7517 &state->data, state->total_data,
7518 state->max_data_return);
7519 END_PROFILE(Trans2_qfsinfo);
7523 case TRANSACT2_SETFSINFO:
7525 START_PROFILE(Trans2_setfsinfo);
7526 call_trans2setfsinfo(conn, req,
7527 &state->param, state->total_param,
7528 &state->data, state->total_data,
7529 state->max_data_return);
7530 END_PROFILE(Trans2_setfsinfo);
7534 case TRANSACT2_QPATHINFO:
7535 case TRANSACT2_QFILEINFO:
7537 START_PROFILE(Trans2_qpathinfo);
7538 call_trans2qfilepathinfo(conn, req, state->call,
7539 &state->param, state->total_param,
7540 &state->data, state->total_data,
7541 state->max_data_return);
7542 END_PROFILE(Trans2_qpathinfo);
7546 case TRANSACT2_SETPATHINFO:
7547 case TRANSACT2_SETFILEINFO:
7549 START_PROFILE(Trans2_setpathinfo);
7550 call_trans2setfilepathinfo(conn, req, state->call,
7551 &state->param, state->total_param,
7552 &state->data, state->total_data,
7553 state->max_data_return);
7554 END_PROFILE(Trans2_setpathinfo);
7558 case TRANSACT2_FINDNOTIFYFIRST:
7560 START_PROFILE(Trans2_findnotifyfirst);
7561 call_trans2findnotifyfirst(conn, req,
7562 &state->param, state->total_param,
7563 &state->data, state->total_data,
7564 state->max_data_return);
7565 END_PROFILE(Trans2_findnotifyfirst);
7569 case TRANSACT2_FINDNOTIFYNEXT:
7571 START_PROFILE(Trans2_findnotifynext);
7572 call_trans2findnotifynext(conn, req,
7573 &state->param, state->total_param,
7574 &state->data, state->total_data,
7575 state->max_data_return);
7576 END_PROFILE(Trans2_findnotifynext);
7580 case TRANSACT2_MKDIR:
7582 START_PROFILE(Trans2_mkdir);
7583 call_trans2mkdir(conn, req,
7584 &state->param, state->total_param,
7585 &state->data, state->total_data,
7586 state->max_data_return);
7587 END_PROFILE(Trans2_mkdir);
7591 case TRANSACT2_GET_DFS_REFERRAL:
7593 START_PROFILE(Trans2_get_dfs_referral);
7594 call_trans2getdfsreferral(conn, req,
7595 &state->param, state->total_param,
7596 &state->data, state->total_data,
7597 state->max_data_return);
7598 END_PROFILE(Trans2_get_dfs_referral);
7602 case TRANSACT2_IOCTL:
7604 START_PROFILE(Trans2_ioctl);
7605 call_trans2ioctl(conn, req,
7606 &state->param, state->total_param,
7607 &state->data, state->total_data,
7608 state->max_data_return);
7609 END_PROFILE(Trans2_ioctl);
7614 /* Error in request */
7615 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7616 reply_doserror(req, ERRSRV,ERRerror);
7620 /****************************************************************************
7621 Reply to a SMBtrans2.
7622 ****************************************************************************/
7624 void reply_trans2(struct smb_request *req)
7626 connection_struct *conn = req->conn;
7631 unsigned int tran_call;
7632 struct trans_state *state;
7635 START_PROFILE(SMBtrans2);
7637 if (req->wct < 14) {
7638 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7639 END_PROFILE(SMBtrans2);
7643 dsoff = SVAL(req->vwv+12, 0);
7644 dscnt = SVAL(req->vwv+11, 0);
7645 psoff = SVAL(req->vwv+10, 0);
7646 pscnt = SVAL(req->vwv+9, 0);
7647 tran_call = SVAL(req->vwv+14, 0);
7649 result = allow_new_trans(conn->pending_trans, req->mid);
7650 if (!NT_STATUS_IS_OK(result)) {
7651 DEBUG(2, ("Got invalid trans2 request: %s\n",
7652 nt_errstr(result)));
7653 reply_nterror(req, result);
7654 END_PROFILE(SMBtrans2);
7659 switch (tran_call) {
7660 /* List the allowed trans2 calls on IPC$ */
7661 case TRANSACT2_OPEN:
7662 case TRANSACT2_GET_DFS_REFERRAL:
7663 case TRANSACT2_QFILEINFO:
7664 case TRANSACT2_QFSINFO:
7665 case TRANSACT2_SETFSINFO:
7668 reply_doserror(req, ERRSRV, ERRaccess);
7669 END_PROFILE(SMBtrans2);
7674 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
7675 DEBUG(0, ("talloc failed\n"));
7676 reply_nterror(req, NT_STATUS_NO_MEMORY);
7677 END_PROFILE(SMBtrans2);
7681 state->cmd = SMBtrans2;
7683 state->mid = req->mid;
7684 state->vuid = req->vuid;
7685 state->setup_count = SVAL(req->vwv+13, 0);
7686 state->setup = NULL;
7687 state->total_param = SVAL(req->vwv+0, 0);
7688 state->param = NULL;
7689 state->total_data = SVAL(req->vwv+1, 0);
7691 state->max_param_return = SVAL(req->vwv+2, 0);
7692 state->max_data_return = SVAL(req->vwv+3, 0);
7693 state->max_setup_return = SVAL(req->vwv+4, 0);
7694 state->close_on_completion = BITSETW(req->vwv+5, 0);
7695 state->one_way = BITSETW(req->vwv+5, 1);
7697 state->call = tran_call;
7699 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7700 is so as a sanity check */
7701 if (state->setup_count != 1) {
7703 * Need to have rc=0 for ioctl to get job id for OS/2.
7704 * Network printing will fail if function is not successful.
7705 * Similar function in reply.c will be used if protocol
7706 * is LANMAN1.0 instead of LM1.2X002.
7707 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7708 * outbuf doesn't have to be set(only job id is used).
7710 if ( (state->setup_count == 4)
7711 && (tran_call == TRANSACT2_IOCTL)
7712 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
7713 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7714 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7716 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7717 DEBUG(2,("Transaction is %d\n",tran_call));
7719 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7720 END_PROFILE(SMBtrans2);
7725 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7728 if (state->total_data) {
7730 if (trans_oob(state->total_data, 0, dscnt)
7731 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
7735 /* Can't use talloc here, the core routines do realloc on the
7736 * params and data. */
7737 state->data = (char *)SMB_MALLOC(state->total_data);
7738 if (state->data == NULL) {
7739 DEBUG(0,("reply_trans2: data malloc fail for %u "
7740 "bytes !\n", (unsigned int)state->total_data));
7742 reply_nterror(req, NT_STATUS_NO_MEMORY);
7743 END_PROFILE(SMBtrans2);
7747 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7750 if (state->total_param) {
7752 if (trans_oob(state->total_param, 0, pscnt)
7753 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
7757 /* Can't use talloc here, the core routines do realloc on the
7758 * params and data. */
7759 state->param = (char *)SMB_MALLOC(state->total_param);
7760 if (state->param == NULL) {
7761 DEBUG(0,("reply_trans: param malloc fail for %u "
7762 "bytes !\n", (unsigned int)state->total_param));
7763 SAFE_FREE(state->data);
7765 reply_nterror(req, NT_STATUS_NO_MEMORY);
7766 END_PROFILE(SMBtrans2);
7770 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7773 state->received_data = dscnt;
7774 state->received_param = pscnt;
7776 if ((state->received_param == state->total_param) &&
7777 (state->received_data == state->total_data)) {
7779 handle_trans2(conn, req, state);
7781 SAFE_FREE(state->data);
7782 SAFE_FREE(state->param);
7784 END_PROFILE(SMBtrans2);
7788 DLIST_ADD(conn->pending_trans, state);
7790 /* We need to send an interim response then receive the rest
7791 of the parameter/data bytes */
7792 reply_outbuf(req, 0, 0);
7793 show_msg((char *)req->outbuf);
7794 END_PROFILE(SMBtrans2);
7799 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7800 SAFE_FREE(state->data);
7801 SAFE_FREE(state->param);
7803 END_PROFILE(SMBtrans2);
7804 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7808 /****************************************************************************
7809 Reply to a SMBtranss2
7810 ****************************************************************************/
7812 void reply_transs2(struct smb_request *req)
7814 connection_struct *conn = req->conn;
7815 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7816 struct trans_state *state;
7818 START_PROFILE(SMBtranss2);
7820 show_msg((char *)req->inbuf);
7823 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7824 END_PROFILE(SMBtranss2);
7828 for (state = conn->pending_trans; state != NULL;
7829 state = state->next) {
7830 if (state->mid == req->mid) {
7835 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7836 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7837 END_PROFILE(SMBtranss2);
7841 /* Revise state->total_param and state->total_data in case they have
7842 changed downwards */
7844 if (SVAL(req->vwv+0, 0) < state->total_param)
7845 state->total_param = SVAL(req->vwv+0, 0);
7846 if (SVAL(req->vwv+1, 0) < state->total_data)
7847 state->total_data = SVAL(req->vwv+1, 0);
7849 pcnt = SVAL(req->vwv+2, 0);
7850 poff = SVAL(req->vwv+3, 0);
7851 pdisp = SVAL(req->vwv+4, 0);
7853 dcnt = SVAL(req->vwv+5, 0);
7854 doff = SVAL(req->vwv+6, 0);
7855 ddisp = SVAL(req->vwv+7, 0);
7857 state->received_param += pcnt;
7858 state->received_data += dcnt;
7860 if ((state->received_data > state->total_data) ||
7861 (state->received_param > state->total_param))
7865 if (trans_oob(state->total_param, pdisp, pcnt)
7866 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
7869 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
7873 if (trans_oob(state->total_data, ddisp, dcnt)
7874 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
7877 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
7880 if ((state->received_param < state->total_param) ||
7881 (state->received_data < state->total_data)) {
7882 END_PROFILE(SMBtranss2);
7886 handle_trans2(conn, req, state);
7888 DLIST_REMOVE(conn->pending_trans, state);
7889 SAFE_FREE(state->data);
7890 SAFE_FREE(state->param);
7893 END_PROFILE(SMBtranss2);
7898 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7899 DLIST_REMOVE(conn->pending_trans, state);
7900 SAFE_FREE(state->data);
7901 SAFE_FREE(state->param);
7903 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7904 END_PROFILE(SMBtranss2);