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/>.
28 #include "smbd/globals.h"
29 #include "../libcli/auth/libcli_auth.h"
31 extern enum protocol_types Protocol;
33 #define DIR_ENTRY_SAFETY_MARGIN 4096
35 static char *store_file_unix_basic(connection_struct *conn,
38 const SMB_STRUCT_STAT *psbuf);
40 static char *store_file_unix_basic_info2(connection_struct *conn,
43 const SMB_STRUCT_STAT *psbuf);
45 /********************************************************************
46 Roundup a value to the nearest allocation roundup size boundary.
47 Only do this for Windows clients.
48 ********************************************************************/
50 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
52 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
54 /* Only roundup for Windows clients. */
55 enum remote_arch_types ra_type = get_remote_arch();
56 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
57 val = SMB_ROUNDUP(val,rval);
62 /****************************************************************************
63 Utility functions for dealing with extended attributes.
64 ****************************************************************************/
66 /****************************************************************************
67 Refuse to allow clients to overwrite our private xattrs.
68 ****************************************************************************/
70 static bool samba_private_attr_name(const char *unix_ea_name)
72 static const char * const prohibited_ea_names[] = {
73 SAMBA_POSIX_INHERITANCE_EA_NAME,
74 SAMBA_XATTR_DOS_ATTRIB,
80 for (i = 0; prohibited_ea_names[i]; i++) {
81 if (strequal( prohibited_ea_names[i], unix_ea_name))
84 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
85 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
91 /****************************************************************************
92 Get one EA value. Fill in a struct ea_struct.
93 ****************************************************************************/
95 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
96 files_struct *fsp, const char *fname,
97 const char *ea_name, struct ea_struct *pea)
99 /* Get the value of this xattr. Max size is 64k. */
100 size_t attr_size = 256;
106 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
108 return NT_STATUS_NO_MEMORY;
111 if (fsp && fsp->fh->fd != -1) {
112 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
114 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
117 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
123 return map_nt_error_from_unix(errno);
126 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
127 dump_data(10, (uint8 *)val, sizeret);
130 if (strnequal(ea_name, "user.", 5)) {
131 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
133 pea->name = talloc_strdup(mem_ctx, ea_name);
135 if (pea->name == NULL) {
137 return NT_STATUS_NO_MEMORY;
139 pea->value.data = (unsigned char *)val;
140 pea->value.length = (size_t)sizeret;
144 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
145 files_struct *fsp, const char *fname,
146 char ***pnames, size_t *pnum_names)
148 /* Get a list of all xattrs. Max namesize is 64k. */
149 size_t ea_namelist_size = 1024;
150 char *ea_namelist = NULL;
155 ssize_t sizeret = -1;
157 if (!lp_ea_support(SNUM(conn))) {
164 * TALLOC the result early to get the talloc hierarchy right.
167 names = TALLOC_ARRAY(mem_ctx, char *, 1);
169 DEBUG(0, ("talloc failed\n"));
170 return NT_STATUS_NO_MEMORY;
173 while (ea_namelist_size <= 65536) {
175 ea_namelist = TALLOC_REALLOC_ARRAY(
176 names, ea_namelist, char, ea_namelist_size);
177 if (ea_namelist == NULL) {
178 DEBUG(0, ("talloc failed\n"));
180 return NT_STATUS_NO_MEMORY;
183 if (fsp && fsp->fh->fd != -1) {
184 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
187 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
191 if ((sizeret == -1) && (errno == ERANGE)) {
192 ea_namelist_size *= 2;
201 return map_nt_error_from_unix(errno);
204 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
205 (unsigned int)sizeret));
215 * Ensure the result is 0-terminated
218 if (ea_namelist[sizeret-1] != '\0') {
220 return NT_STATUS_INTERNAL_ERROR;
228 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
232 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
234 DEBUG(0, ("talloc failed\n"));
236 return NT_STATUS_NO_MEMORY;
242 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
243 names[num_names++] = p;
247 *pnum_names = num_names;
251 /****************************************************************************
252 Return a linked list of the total EA's. Plus the total size
253 ****************************************************************************/
255 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
256 const char *fname, size_t *pea_total_len)
258 /* Get a list of all xattrs. Max namesize is 64k. */
261 struct ea_list *ea_list_head = NULL;
266 if (!lp_ea_support(SNUM(conn))) {
270 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
273 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
277 for (i=0; i<num_names; i++) {
278 struct ea_list *listp;
281 if (strnequal(names[i], "system.", 7)
282 || samba_private_attr_name(names[i]))
285 listp = TALLOC_P(mem_ctx, struct ea_list);
290 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
296 push_ascii_fstring(dos_ea_name, listp->ea.name);
299 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
301 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
302 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
303 (unsigned int)listp->ea.value.length));
305 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
309 /* Add on 4 for total length. */
310 if (*pea_total_len) {
314 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
315 (unsigned int)*pea_total_len));
320 /****************************************************************************
321 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
323 ****************************************************************************/
325 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
326 connection_struct *conn, struct ea_list *ea_list)
328 unsigned int ret_data_size = 4;
331 SMB_ASSERT(total_data_size >= 4);
333 if (!lp_ea_support(SNUM(conn))) {
338 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
341 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
342 dos_namelen = strlen(dos_ea_name);
343 if (dos_namelen > 255 || dos_namelen == 0) {
346 if (ea_list->ea.value.length > 65535) {
349 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
353 /* We know we have room. */
354 SCVAL(p,0,ea_list->ea.flags);
355 SCVAL(p,1,dos_namelen);
356 SSVAL(p,2,ea_list->ea.value.length);
357 fstrcpy(p+4, dos_ea_name);
358 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
360 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
361 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
364 ret_data_size = PTR_DIFF(p, pdata);
365 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
366 SIVAL(pdata,0,ret_data_size);
367 return ret_data_size;
370 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
372 unsigned int total_data_size,
373 unsigned int *ret_data_size,
374 connection_struct *conn,
375 struct ea_list *ea_list)
377 uint8_t *p = (uint8_t *)pdata;
378 uint8_t *last_start = NULL;
382 if (!lp_ea_support(SNUM(conn))) {
383 return NT_STATUS_NO_EAS_ON_FILE;
386 for (; ea_list; ea_list = ea_list->next) {
392 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
396 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
397 dos_namelen = strlen(dos_ea_name);
398 if (dos_namelen > 255 || dos_namelen == 0) {
399 return NT_STATUS_INTERNAL_ERROR;
401 if (ea_list->ea.value.length > 65535) {
402 return NT_STATUS_INTERNAL_ERROR;
405 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
408 size_t pad = 4 - (this_size % 4);
412 if (this_size > total_data_size) {
413 return NT_STATUS_INFO_LENGTH_MISMATCH;
416 /* We know we have room. */
417 SIVAL(p, 0x00, 0); /* next offset */
418 SCVAL(p, 0x04, ea_list->ea.flags);
419 SCVAL(p, 0x05, dos_namelen);
420 SSVAL(p, 0x06, ea_list->ea.value.length);
421 fstrcpy((char *)(p+0x08), dos_ea_name);
422 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
424 total_data_size -= this_size;
428 *ret_data_size = PTR_DIFF(p, pdata);
429 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
433 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
435 size_t total_ea_len = 0;
436 TALLOC_CTX *mem_ctx = NULL;
438 if (!lp_ea_support(SNUM(conn))) {
441 mem_ctx = talloc_tos();
442 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
446 /****************************************************************************
447 Ensure the EA name is case insensitive by matching any existing EA name.
448 ****************************************************************************/
450 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
453 TALLOC_CTX *mem_ctx = talloc_tos();
454 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
456 for (; ea_list; ea_list = ea_list->next) {
457 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
458 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
459 &unix_ea_name[5], ea_list->ea.name));
460 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
466 /****************************************************************************
467 Set or delete an extended attribute.
468 ****************************************************************************/
470 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
471 const struct smb_filename *smb_fname, struct ea_list *ea_list)
475 if (!lp_ea_support(SNUM(conn))) {
476 return NT_STATUS_EAS_NOT_SUPPORTED;
479 /* For now setting EAs on streams isn't supported. */
480 fname = smb_fname->base_name;
482 for (;ea_list; ea_list = ea_list->next) {
484 fstring unix_ea_name;
486 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
487 fstrcat(unix_ea_name, ea_list->ea.name);
489 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
491 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
493 if (samba_private_attr_name(unix_ea_name)) {
494 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
495 return NT_STATUS_ACCESS_DENIED;
498 if (ea_list->ea.value.length == 0) {
499 /* Remove the attribute. */
500 if (fsp && (fsp->fh->fd != -1)) {
501 DEBUG(10,("set_ea: deleting ea name %s on "
502 "file %s by file descriptor.\n",
503 unix_ea_name, fsp_str_dbg(fsp)));
504 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
506 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
507 unix_ea_name, fname));
508 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
511 /* Removing a non existent attribute always succeeds. */
512 if (ret == -1 && errno == ENOATTR) {
513 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
519 if (fsp && (fsp->fh->fd != -1)) {
520 DEBUG(10,("set_ea: setting ea name %s on file "
521 "%s by file descriptor.\n",
522 unix_ea_name, fsp_str_dbg(fsp)));
523 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
524 ea_list->ea.value.data, ea_list->ea.value.length, 0);
526 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
527 unix_ea_name, fname));
528 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
529 ea_list->ea.value.data, ea_list->ea.value.length, 0);
535 if (errno == ENOTSUP) {
536 return NT_STATUS_EAS_NOT_SUPPORTED;
539 return map_nt_error_from_unix(errno);
545 /****************************************************************************
546 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
547 ****************************************************************************/
549 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
551 struct ea_list *ea_list_head = NULL;
552 size_t converted_size, offset = 0;
554 while (offset + 2 < data_size) {
555 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
556 unsigned int namelen = CVAL(pdata,offset);
558 offset++; /* Go past the namelen byte. */
560 /* integer wrap paranioa. */
561 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
562 (offset > data_size) || (namelen > data_size) ||
563 (offset + namelen >= data_size)) {
566 /* Ensure the name is null terminated. */
567 if (pdata[offset + namelen] != '\0') {
570 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
572 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
573 "failed: %s", strerror(errno)));
579 offset += (namelen + 1); /* Go past the name + terminating zero. */
580 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
581 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
587 /****************************************************************************
588 Read one EA list entry from the buffer.
589 ****************************************************************************/
591 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
593 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
595 unsigned int namelen;
596 size_t converted_size;
606 eal->ea.flags = CVAL(pdata,0);
607 namelen = CVAL(pdata,1);
608 val_len = SVAL(pdata,2);
610 if (4 + namelen + 1 + val_len > data_size) {
614 /* Ensure the name is null terminated. */
615 if (pdata[namelen + 4] != '\0') {
618 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
619 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
626 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
627 if (!eal->ea.value.data) {
631 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
633 /* Ensure we're null terminated just in case we print the value. */
634 eal->ea.value.data[val_len] = '\0';
635 /* But don't count the null. */
636 eal->ea.value.length--;
639 *pbytes_used = 4 + namelen + 1 + val_len;
642 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
643 dump_data(10, eal->ea.value.data, eal->ea.value.length);
648 /****************************************************************************
649 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
650 ****************************************************************************/
652 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
654 struct ea_list *ea_list_head = NULL;
656 size_t bytes_used = 0;
658 while (offset < data_size) {
659 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
665 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
666 offset += bytes_used;
672 /****************************************************************************
673 Count the total EA size needed.
674 ****************************************************************************/
676 static size_t ea_list_size(struct ea_list *ealist)
679 struct ea_list *listp;
682 for (listp = ealist; listp; listp = listp->next) {
683 push_ascii_fstring(dos_ea_name, listp->ea.name);
684 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
686 /* Add on 4 for total length. */
694 /****************************************************************************
695 Return a union of EA's from a file list and a list of names.
696 The TALLOC context for the two lists *MUST* be identical as we steal
697 memory from one list to add to another. JRA.
698 ****************************************************************************/
700 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
702 struct ea_list *nlistp, *flistp;
704 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
705 for (flistp = file_list; flistp; flistp = flistp->next) {
706 if (strequal(nlistp->ea.name, flistp->ea.name)) {
712 /* Copy the data from this entry. */
713 nlistp->ea.flags = flistp->ea.flags;
714 nlistp->ea.value = flistp->ea.value;
717 nlistp->ea.flags = 0;
718 ZERO_STRUCT(nlistp->ea.value);
722 *total_ea_len = ea_list_size(name_list);
726 /****************************************************************************
727 Send the required number of replies back.
728 We assume all fields other than the data fields are
729 set correctly for the type of call.
730 HACK ! Always assumes smb_setup field is zero.
731 ****************************************************************************/
733 void send_trans2_replies(connection_struct *conn,
734 struct smb_request *req,
741 /* As we are using a protocol > LANMAN1 then the max_send
742 variable must have been set in the sessetupX call.
743 This takes precedence over the max_xmit field in the
744 global struct. These different max_xmit variables should
745 be merged as this is now too confusing */
747 int data_to_send = datasize;
748 int params_to_send = paramsize;
750 const char *pp = params;
751 const char *pd = pdata;
752 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
753 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
754 int data_alignment_offset = 0;
755 bool overflow = False;
756 struct smbd_server_connection *sconn = smbd_server_conn;
757 int max_send = sconn->smb1.sessions.max_send;
759 /* Modify the data_to_send and datasize and set the error if
760 we're trying to send more than max_data_bytes. We still send
761 the part of the packet(s) that fit. Strange, but needed
764 if (max_data_bytes > 0 && datasize > max_data_bytes) {
765 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
766 max_data_bytes, datasize ));
767 datasize = data_to_send = max_data_bytes;
771 /* If there genuinely are no parameters or data to send just send the empty packet */
773 if(params_to_send == 0 && data_to_send == 0) {
774 reply_outbuf(req, 10, 0);
775 show_msg((char *)req->outbuf);
776 if (!srv_send_smb(smbd_server_fd(),
779 IS_CONN_ENCRYPTED(conn),
781 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
783 TALLOC_FREE(req->outbuf);
787 /* When sending params and data ensure that both are nicely aligned */
788 /* Only do this alignment when there is also data to send - else
789 can cause NT redirector problems. */
791 if (((params_to_send % 4) != 0) && (data_to_send != 0))
792 data_alignment_offset = 4 - (params_to_send % 4);
794 /* Space is bufsize minus Netbios over TCP header minus SMB header */
795 /* The alignment_offset is to align the param bytes on an even byte
796 boundary. NT 4.0 Beta needs this to work correctly. */
798 useable_space = max_send - (smb_size
801 + data_alignment_offset);
803 if (useable_space < 0) {
804 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
805 "= %d!!!", useable_space));
806 exit_server_cleanly("send_trans2_replies: Not enough space");
809 while (params_to_send || data_to_send) {
810 /* Calculate whether we will totally or partially fill this packet */
812 total_sent_thistime = params_to_send + data_to_send;
814 /* We can never send more than useable_space */
816 * Note that 'useable_space' does not include the alignment offsets,
817 * but we must include the alignment offsets in the calculation of
818 * the length of the data we send over the wire, as the alignment offsets
819 * are sent here. Fix from Marc_Jacobsen@hp.com.
822 total_sent_thistime = MIN(total_sent_thistime, useable_space);
824 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
825 + data_alignment_offset);
828 * We might have SMBtrans2s in req which was transferred to
829 * the outbuf, fix that.
831 SCVAL(req->outbuf, smb_com, SMBtrans2);
833 /* Set total params and data to be sent */
834 SSVAL(req->outbuf,smb_tprcnt,paramsize);
835 SSVAL(req->outbuf,smb_tdrcnt,datasize);
837 /* Calculate how many parameters and data we can fit into
838 * this packet. Parameters get precedence
841 params_sent_thistime = MIN(params_to_send,useable_space);
842 data_sent_thistime = useable_space - params_sent_thistime;
843 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
845 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
847 /* smb_proff is the offset from the start of the SMB header to the
848 parameter bytes, however the first 4 bytes of outbuf are
849 the Netbios over TCP header. Thus use smb_base() to subtract
850 them from the calculation */
852 SSVAL(req->outbuf,smb_proff,
853 ((smb_buf(req->outbuf)+alignment_offset)
854 - smb_base(req->outbuf)));
856 if(params_sent_thistime == 0)
857 SSVAL(req->outbuf,smb_prdisp,0);
859 /* Absolute displacement of param bytes sent in this packet */
860 SSVAL(req->outbuf,smb_prdisp,pp - params);
862 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
863 if(data_sent_thistime == 0) {
864 SSVAL(req->outbuf,smb_droff,0);
865 SSVAL(req->outbuf,smb_drdisp, 0);
867 /* The offset of the data bytes is the offset of the
868 parameter bytes plus the number of parameters being sent this time */
869 SSVAL(req->outbuf, smb_droff,
870 ((smb_buf(req->outbuf)+alignment_offset)
871 - smb_base(req->outbuf))
872 + params_sent_thistime + data_alignment_offset);
873 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
876 /* Initialize the padding for alignment */
878 if (alignment_offset != 0) {
879 memset(smb_buf(req->outbuf), 0, alignment_offset);
882 /* Copy the param bytes into the packet */
884 if(params_sent_thistime) {
885 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
886 params_sent_thistime);
889 /* Copy in the data bytes */
890 if(data_sent_thistime) {
891 if (data_alignment_offset != 0) {
892 memset((smb_buf(req->outbuf)+alignment_offset+
893 params_sent_thistime), 0,
894 data_alignment_offset);
896 memcpy(smb_buf(req->outbuf)+alignment_offset
897 +params_sent_thistime+data_alignment_offset,
898 pd,data_sent_thistime);
901 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
902 params_sent_thistime, data_sent_thistime, useable_space));
903 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
904 params_to_send, data_to_send, paramsize, datasize));
907 error_packet_set((char *)req->outbuf,
908 ERRDOS,ERRbufferoverflow,
909 STATUS_BUFFER_OVERFLOW,
913 /* Send the packet */
914 show_msg((char *)req->outbuf);
915 if (!srv_send_smb(smbd_server_fd(),
918 IS_CONN_ENCRYPTED(conn),
920 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
922 TALLOC_FREE(req->outbuf);
924 pp += params_sent_thistime;
925 pd += data_sent_thistime;
927 params_to_send -= params_sent_thistime;
928 data_to_send -= data_sent_thistime;
931 if(params_to_send < 0 || data_to_send < 0) {
932 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
933 params_to_send, data_to_send));
941 /****************************************************************************
942 Reply to a TRANSACT2_OPEN.
943 ****************************************************************************/
945 static void call_trans2open(connection_struct *conn,
946 struct smb_request *req,
947 char **pparams, int total_params,
948 char **ppdata, int total_data,
949 unsigned int max_data_bytes)
951 struct smb_filename *smb_fname = NULL;
952 char *params = *pparams;
953 char *pdata = *ppdata;
958 bool return_additional_info;
971 struct ea_list *ea_list = NULL;
976 uint32 create_disposition;
977 uint32 create_options = 0;
978 TALLOC_CTX *ctx = talloc_tos();
981 * Ensure we have enough parameters to perform the operation.
984 if (total_params < 29) {
985 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
989 flags = SVAL(params, 0);
990 deny_mode = SVAL(params, 2);
991 open_attr = SVAL(params,6);
992 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
993 if (oplock_request) {
994 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
998 return_additional_info = BITSETW(params,0);
999 open_sattr = SVAL(params, 4);
1000 open_time = make_unix_date3(params+8);
1002 open_ofun = SVAL(params,12);
1003 open_size = IVAL(params,14);
1004 pname = ¶ms[28];
1007 reply_doserror(req, ERRSRV, ERRaccess);
1011 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1012 total_params - 28, STR_TERMINATE,
1014 if (!NT_STATUS_IS_OK(status)) {
1015 reply_nterror(req, status);
1019 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1020 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1021 (unsigned int)open_ofun, open_size));
1023 status = filename_convert(ctx,
1025 req->flags2 & FLAGS2_DFS_PATHNAMES,
1030 if (!NT_STATUS_IS_OK(status)) {
1031 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1032 reply_botherror(req,
1033 NT_STATUS_PATH_NOT_COVERED,
1034 ERRSRV, ERRbadpath);
1037 reply_nterror(req, status);
1041 if (open_ofun == 0) {
1042 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1046 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, open_ofun,
1047 &access_mask, &share_mode,
1048 &create_disposition,
1050 reply_doserror(req, ERRDOS, ERRbadaccess);
1054 /* Any data in this call is an EA list. */
1055 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
1056 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1060 if (total_data != 4) {
1061 if (total_data < 10) {
1062 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1066 if (IVAL(pdata,0) > total_data) {
1067 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1068 IVAL(pdata,0), (unsigned int)total_data));
1069 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1073 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1076 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1079 } else if (IVAL(pdata,0) != 4) {
1080 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1084 status = SMB_VFS_CREATE_FILE(
1087 0, /* root_dir_fid */
1088 smb_fname, /* fname */
1089 access_mask, /* access_mask */
1090 share_mode, /* share_access */
1091 create_disposition, /* create_disposition*/
1092 create_options, /* create_options */
1093 open_attr, /* file_attributes */
1094 oplock_request, /* oplock_request */
1095 open_size, /* allocation_size */
1097 ea_list, /* ea_list */
1099 &smb_action); /* psbuf */
1101 if (!NT_STATUS_IS_OK(status)) {
1102 if (open_was_deferred(req->mid)) {
1103 /* We have re-scheduled this call. */
1106 reply_openerror(req, status);
1110 size = get_file_size_stat(&smb_fname->st);
1111 fattr = dos_mode(conn, smb_fname);
1112 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1113 inode = smb_fname->st.st_ex_ino;
1115 close_file(req, fsp, ERROR_CLOSE);
1116 reply_doserror(req, ERRDOS,ERRnoaccess);
1120 /* Realloc the size of parameters and data we will return */
1121 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1122 if(*pparams == NULL ) {
1123 reply_nterror(req, NT_STATUS_NO_MEMORY);
1128 SSVAL(params,0,fsp->fnum);
1129 SSVAL(params,2,fattr);
1130 srv_put_dos_date2(params,4, mtime);
1131 SIVAL(params,8, (uint32)size);
1132 SSVAL(params,12,deny_mode);
1133 SSVAL(params,14,0); /* open_type - file or directory. */
1134 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1136 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1137 smb_action |= EXTENDED_OPLOCK_GRANTED;
1140 SSVAL(params,18,smb_action);
1143 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1145 SIVAL(params,20,inode);
1146 SSVAL(params,24,0); /* Padding. */
1148 uint32 ea_size = estimate_ea_size(conn, fsp,
1149 fsp->fsp_name->base_name);
1150 SIVAL(params, 26, ea_size);
1152 SIVAL(params, 26, 0);
1155 /* Send the required number of replies */
1156 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1158 TALLOC_FREE(smb_fname);
1161 /*********************************************************
1162 Routine to check if a given string matches exactly.
1163 as a special case a mask of "." does NOT match. That
1164 is required for correct wildcard semantics
1165 Case can be significant or not.
1166 **********************************************************/
1168 static bool exact_match(connection_struct *conn,
1172 if (mask[0] == '.' && mask[1] == 0)
1174 if (dptr_has_wild(conn->dirptr)) {
1177 if (conn->case_sensitive)
1178 return strcmp(str,mask)==0;
1180 return StrCaseCmp(str,mask) == 0;
1183 /****************************************************************************
1184 Return the filetype for UNIX extensions.
1185 ****************************************************************************/
1187 static uint32 unix_filetype(mode_t mode)
1190 return UNIX_TYPE_FILE;
1191 else if(S_ISDIR(mode))
1192 return UNIX_TYPE_DIR;
1194 else if(S_ISLNK(mode))
1195 return UNIX_TYPE_SYMLINK;
1198 else if(S_ISCHR(mode))
1199 return UNIX_TYPE_CHARDEV;
1202 else if(S_ISBLK(mode))
1203 return UNIX_TYPE_BLKDEV;
1206 else if(S_ISFIFO(mode))
1207 return UNIX_TYPE_FIFO;
1210 else if(S_ISSOCK(mode))
1211 return UNIX_TYPE_SOCKET;
1214 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1215 return UNIX_TYPE_UNKNOWN;
1218 /****************************************************************************
1219 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1220 ****************************************************************************/
1222 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1224 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1225 const SMB_STRUCT_STAT *psbuf,
1227 enum perm_type ptype,
1232 if (perms == SMB_MODE_NO_CHANGE) {
1233 if (!VALID_STAT(*psbuf)) {
1234 return NT_STATUS_INVALID_PARAMETER;
1236 *ret_perms = psbuf->st_ex_mode;
1237 return NT_STATUS_OK;
1241 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1242 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1243 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1244 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1245 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1246 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1247 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1248 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1249 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1251 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1254 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1257 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1262 /* Apply mode mask */
1263 ret &= lp_create_mask(SNUM(conn));
1264 /* Add in force bits */
1265 ret |= lp_force_create_mode(SNUM(conn));
1268 ret &= lp_dir_mask(SNUM(conn));
1269 /* Add in force bits */
1270 ret |= lp_force_dir_mode(SNUM(conn));
1272 case PERM_EXISTING_FILE:
1273 /* Apply mode mask */
1274 ret &= lp_security_mask(SNUM(conn));
1275 /* Add in force bits */
1276 ret |= lp_force_security_mode(SNUM(conn));
1278 case PERM_EXISTING_DIR:
1279 /* Apply mode mask */
1280 ret &= lp_dir_security_mask(SNUM(conn));
1281 /* Add in force bits */
1282 ret |= lp_force_dir_security_mode(SNUM(conn));
1287 return NT_STATUS_OK;
1290 /****************************************************************************
1291 Needed to show the msdfs symlinks as directories. Modifies psbuf
1292 to be a directory if it's a msdfs link.
1293 ****************************************************************************/
1295 static bool check_msdfs_link(connection_struct *conn,
1296 const char *pathname,
1297 SMB_STRUCT_STAT *psbuf)
1299 int saved_errno = errno;
1300 if(lp_host_msdfs() &&
1301 lp_msdfs_root(SNUM(conn)) &&
1302 is_msdfs_link(conn, pathname, psbuf)) {
1304 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1307 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1308 errno = saved_errno;
1311 errno = saved_errno;
1316 /****************************************************************************
1317 Get a level dependent lanman2 dir entry.
1318 ****************************************************************************/
1320 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1321 connection_struct *conn,
1323 const char *path_mask,
1326 int requires_resume_key,
1332 int space_remaining,
1334 bool *got_exact_match,
1335 int *last_entry_off,
1336 struct ea_list *name_list)
1340 SMB_STRUCT_STAT sbuf;
1341 const char *mask = NULL;
1342 char *pathreal = NULL;
1344 char *p, *q, *pdata = *ppdata;
1348 SMB_OFF_T file_size = 0;
1349 uint64_t allocation_size = 0;
1351 struct timespec mdate_ts, adate_ts, create_date_ts;
1352 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1354 char *last_entry_ptr;
1356 uint32 nt_extmode; /* Used for NT connections instead of mode */
1357 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1358 bool check_mangled_names = lp_manglednames(conn->params);
1359 char mangled_name[13]; /* mangled 8.3 name. */
1361 *out_of_space = False;
1362 *got_exact_match = False;
1364 ZERO_STRUCT(mdate_ts);
1365 ZERO_STRUCT(adate_ts);
1366 ZERO_STRUCT(create_date_ts);
1368 if (!conn->dirptr) {
1372 p = strrchr_m(path_mask,'/');
1375 mask = talloc_strdup(ctx,"*.*");
1385 bool ms_dfs_link = False;
1387 /* Needed if we run out of space */
1388 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1389 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1392 * Due to bugs in NT client redirectors we are not using
1393 * resume keys any more - set them to zero.
1394 * Check out the related comments in findfirst/findnext.
1400 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1401 (long)conn->dirptr,curr_dirpos));
1408 * fname may get mangled, dname is never mangled.
1409 * Whenever we're accessing the filesystem we use
1410 * pathreal which is composed from dname.
1416 /* Mangle fname if it's an illegal name. */
1417 if (mangle_must_mangle(dname,conn->params)) {
1418 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1420 continue; /* Error - couldn't mangle. */
1422 fname = talloc_strdup(ctx, mangled_name);
1428 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1429 got_match = mask_match(fname, mask, conn->case_sensitive);
1432 if(!got_match && check_mangled_names &&
1433 !mangle_is_8_3(fname, False, conn->params)) {
1435 * It turns out that NT matches wildcards against
1436 * both long *and* short names. This may explain some
1437 * of the wildcard wierdness from old DOS clients
1438 * that some people have been seeing.... JRA.
1440 /* Force the mangling into 8.3. */
1441 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1443 continue; /* Error - couldn't mangle. */
1446 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1447 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1452 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1453 struct smb_filename *smb_fname = NULL;
1456 if (dont_descend && !isdots) {
1463 pathreal = talloc_asprintf(ctx,
1468 pathreal = talloc_asprintf(ctx,
1479 /* A dirent from dptr_ReadDirName isn't a stream. */
1480 status = create_synthetic_smb_fname(ctx, pathreal,
1483 if (!NT_STATUS_IS_OK(status)) {
1488 if (INFO_LEVEL_IS_UNIX(info_level)) {
1489 if (SMB_VFS_LSTAT(conn, smb_fname) != 0) {
1490 DEBUG(5,("get_lanman2_dir_entry: "
1491 "Couldn't lstat [%s] (%s)\n",
1492 smb_fname_str_dbg(smb_fname),
1494 TALLOC_FREE(smb_fname);
1495 TALLOC_FREE(pathreal);
1499 } else if (!VALID_STAT(smb_fname->st) &&
1500 SMB_VFS_STAT(conn, smb_fname) != 0) {
1501 /* Needed to show the msdfs symlinks as
1505 check_msdfs_link(conn,
1506 smb_fname->base_name,
1509 DEBUG(5,("get_lanman2_dir_entry: "
1510 "Couldn't stat [%s] (%s)\n",
1511 smb_fname_str_dbg(smb_fname),
1513 TALLOC_FREE(smb_fname);
1514 TALLOC_FREE(pathreal);
1521 mode = dos_mode_msdfs(conn, smb_fname);
1523 mode = dos_mode(conn, smb_fname);
1526 if (!dir_check_ftype(conn,mode,dirtype)) {
1527 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1528 TALLOC_FREE(smb_fname);
1529 TALLOC_FREE(pathreal);
1534 if (!(mode & aDIR)) {
1535 file_size = get_file_size_stat(&smb_fname->st);
1538 SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1540 if (ask_sharemode) {
1541 struct timespec write_time_ts;
1542 struct file_id fileid;
1544 ZERO_STRUCT(write_time_ts);
1545 fileid = vfs_file_id_from_sbuf(conn,
1547 get_file_infos(fileid, NULL, &write_time_ts);
1548 if (!null_timespec(write_time_ts)) {
1549 update_stat_ex_mtime(&smb_fname->st,
1554 mdate_ts = smb_fname->st.st_ex_mtime;
1555 adate_ts = smb_fname->st.st_ex_atime;
1556 create_date_ts = smb_fname->st.st_ex_btime;
1558 if (lp_dos_filetime_resolution(SNUM(conn))) {
1559 dos_filetime_timespec(&create_date_ts);
1560 dos_filetime_timespec(&mdate_ts);
1561 dos_filetime_timespec(&adate_ts);
1564 create_date = convert_timespec_to_time_t(create_date_ts);
1565 mdate = convert_timespec_to_time_t(mdate_ts);
1566 adate = convert_timespec_to_time_t(adate_ts);
1568 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",
1569 smb_fname_str_dbg(smb_fname), fname));
1573 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1574 sbuf = smb_fname->st;
1576 TALLOC_FREE(smb_fname);
1586 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1588 switch (info_level) {
1589 case SMB_FIND_INFO_STANDARD:
1590 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1591 if(requires_resume_key) {
1595 srv_put_dos_date2(p,0,create_date);
1596 srv_put_dos_date2(p,4,adate);
1597 srv_put_dos_date2(p,8,mdate);
1598 SIVAL(p,12,(uint32)file_size);
1599 SIVAL(p,16,(uint32)allocation_size);
1603 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1604 p += ucs2_align(base_data, p, 0);
1606 len = srvstr_push(base_data, flags2, p,
1607 fname, PTR_DIFF(end_data, p),
1609 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1611 SCVAL(nameptr, -1, len - 2);
1613 SCVAL(nameptr, -1, 0);
1617 SCVAL(nameptr, -1, len - 1);
1619 SCVAL(nameptr, -1, 0);
1625 case SMB_FIND_EA_SIZE:
1626 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1627 if(requires_resume_key) {
1631 srv_put_dos_date2(p,0,create_date);
1632 srv_put_dos_date2(p,4,adate);
1633 srv_put_dos_date2(p,8,mdate);
1634 SIVAL(p,12,(uint32)file_size);
1635 SIVAL(p,16,(uint32)allocation_size);
1638 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1639 SIVAL(p,22,ea_size); /* Extended attributes */
1643 len = srvstr_push(base_data, flags2,
1644 p, fname, PTR_DIFF(end_data, p),
1645 STR_TERMINATE | STR_NOALIGN);
1646 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1659 SCVAL(nameptr,0,len);
1661 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1664 case SMB_FIND_EA_LIST:
1666 struct ea_list *file_list = NULL;
1669 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1673 if(requires_resume_key) {
1677 srv_put_dos_date2(p,0,create_date);
1678 srv_put_dos_date2(p,4,adate);
1679 srv_put_dos_date2(p,8,mdate);
1680 SIVAL(p,12,(uint32)file_size);
1681 SIVAL(p,16,(uint32)allocation_size);
1683 p += 22; /* p now points to the EA area. */
1685 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1686 name_list = ea_list_union(name_list, file_list, &ea_len);
1688 /* We need to determine if this entry will fit in the space available. */
1689 /* Max string size is 255 bytes. */
1690 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1691 /* Move the dirptr back to prev_dirpos */
1692 dptr_SeekDir(conn->dirptr, prev_dirpos);
1693 *out_of_space = True;
1694 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1695 return False; /* Not finished - just out of space */
1698 /* Push the ea_data followed by the name. */
1699 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1701 len = srvstr_push(base_data, flags2,
1702 p + 1, fname, PTR_DIFF(end_data, p+1),
1703 STR_TERMINATE | STR_NOALIGN);
1704 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1717 SCVAL(nameptr,0,len);
1719 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1723 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1724 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1725 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1727 SIVAL(p,0,reskey); p += 4;
1728 put_long_date_timespec(p,create_date_ts); p += 8;
1729 put_long_date_timespec(p,adate_ts); p += 8;
1730 put_long_date_timespec(p,mdate_ts); p += 8;
1731 put_long_date_timespec(p,mdate_ts); p += 8;
1732 SOFF_T(p,0,file_size); p += 8;
1733 SOFF_T(p,0,allocation_size); p += 8;
1734 SIVAL(p,0,nt_extmode); p += 4;
1735 q = p; p += 4; /* q is placeholder for name length. */
1737 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1738 SIVAL(p,0,ea_size); /* Extended attributes */
1741 /* Clear the short name buffer. This is
1742 * IMPORTANT as not doing so will trigger
1743 * a Win2k client bug. JRA.
1745 if (!was_8_3 && check_mangled_names) {
1746 if (!name_to_8_3(fname,mangled_name,True,
1748 /* Error - mangle failed ! */
1749 memset(mangled_name,'\0',12);
1751 mangled_name[12] = 0;
1752 len = srvstr_push(base_data, flags2,
1753 p+2, mangled_name, 24,
1754 STR_UPPER|STR_UNICODE);
1756 memset(p + 2 + len,'\0',24 - len);
1763 len = srvstr_push(base_data, flags2, p,
1764 fname, PTR_DIFF(end_data, p),
1765 STR_TERMINATE_ASCII);
1768 SIVAL(p,0,0); /* Ensure any padding is null. */
1769 len = PTR_DIFF(p, pdata);
1770 len = (len + 3) & ~3;
1775 case SMB_FIND_FILE_DIRECTORY_INFO:
1776 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1778 SIVAL(p,0,reskey); p += 4;
1779 put_long_date_timespec(p,create_date_ts); p += 8;
1780 put_long_date_timespec(p,adate_ts); p += 8;
1781 put_long_date_timespec(p,mdate_ts); p += 8;
1782 put_long_date_timespec(p,mdate_ts); p += 8;
1783 SOFF_T(p,0,file_size); p += 8;
1784 SOFF_T(p,0,allocation_size); p += 8;
1785 SIVAL(p,0,nt_extmode); p += 4;
1786 len = srvstr_push(base_data, flags2,
1787 p + 4, fname, PTR_DIFF(end_data, p+4),
1788 STR_TERMINATE_ASCII);
1791 SIVAL(p,0,0); /* Ensure any padding is null. */
1792 len = PTR_DIFF(p, pdata);
1793 len = (len + 3) & ~3;
1798 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1799 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1801 SIVAL(p,0,reskey); p += 4;
1802 put_long_date_timespec(p,create_date_ts); p += 8;
1803 put_long_date_timespec(p,adate_ts); p += 8;
1804 put_long_date_timespec(p,mdate_ts); p += 8;
1805 put_long_date_timespec(p,mdate_ts); p += 8;
1806 SOFF_T(p,0,file_size); p += 8;
1807 SOFF_T(p,0,allocation_size); p += 8;
1808 SIVAL(p,0,nt_extmode); p += 4;
1809 q = p; p += 4; /* q is placeholder for name length. */
1811 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1812 SIVAL(p,0,ea_size); /* Extended attributes */
1815 len = srvstr_push(base_data, flags2, p,
1816 fname, PTR_DIFF(end_data, p),
1817 STR_TERMINATE_ASCII);
1821 SIVAL(p,0,0); /* Ensure any padding is null. */
1822 len = PTR_DIFF(p, pdata);
1823 len = (len + 3) & ~3;
1828 case SMB_FIND_FILE_NAMES_INFO:
1829 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1831 SIVAL(p,0,reskey); p += 4;
1833 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1834 acl on a dir (tridge) */
1835 len = srvstr_push(base_data, flags2, p,
1836 fname, PTR_DIFF(end_data, p),
1837 STR_TERMINATE_ASCII);
1840 SIVAL(p,0,0); /* Ensure any padding is null. */
1841 len = PTR_DIFF(p, pdata);
1842 len = (len + 3) & ~3;
1847 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1848 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1850 SIVAL(p,0,reskey); p += 4;
1851 put_long_date_timespec(p,create_date_ts); p += 8;
1852 put_long_date_timespec(p,adate_ts); p += 8;
1853 put_long_date_timespec(p,mdate_ts); p += 8;
1854 put_long_date_timespec(p,mdate_ts); p += 8;
1855 SOFF_T(p,0,file_size); p += 8;
1856 SOFF_T(p,0,allocation_size); p += 8;
1857 SIVAL(p,0,nt_extmode); p += 4;
1858 q = p; p += 4; /* q is placeholder for name length. */
1860 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1861 SIVAL(p,0,ea_size); /* Extended attributes */
1864 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1865 SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */
1866 SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */
1867 len = srvstr_push(base_data, flags2, p,
1868 fname, PTR_DIFF(end_data, p),
1869 STR_TERMINATE_ASCII);
1872 SIVAL(p,0,0); /* Ensure any padding is null. */
1873 len = PTR_DIFF(p, pdata);
1874 len = (len + 3) & ~3;
1879 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1880 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1881 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1883 SIVAL(p,0,reskey); p += 4;
1884 put_long_date_timespec(p,create_date_ts); p += 8;
1885 put_long_date_timespec(p,adate_ts); p += 8;
1886 put_long_date_timespec(p,mdate_ts); p += 8;
1887 put_long_date_timespec(p,mdate_ts); p += 8;
1888 SOFF_T(p,0,file_size); p += 8;
1889 SOFF_T(p,0,allocation_size); p += 8;
1890 SIVAL(p,0,nt_extmode); p += 4;
1891 q = p; p += 4; /* q is placeholder for name length */
1893 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1894 SIVAL(p,0,ea_size); /* Extended attributes */
1897 /* Clear the short name buffer. This is
1898 * IMPORTANT as not doing so will trigger
1899 * a Win2k client bug. JRA.
1901 if (!was_8_3 && check_mangled_names) {
1902 if (!name_to_8_3(fname,mangled_name,True,
1904 /* Error - mangle failed ! */
1905 memset(mangled_name,'\0',12);
1907 mangled_name[12] = 0;
1908 len = srvstr_push(base_data, flags2,
1909 p+2, mangled_name, 24,
1910 STR_UPPER|STR_UNICODE);
1913 memset(p + 2 + len,'\0',24 - len);
1920 SSVAL(p,0,0); p += 2; /* Reserved ? */
1921 SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */
1922 SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */
1923 len = srvstr_push(base_data, flags2, p,
1924 fname, PTR_DIFF(end_data, p),
1925 STR_TERMINATE_ASCII);
1928 SIVAL(p,0,0); /* Ensure any padding is null. */
1929 len = PTR_DIFF(p, pdata);
1930 len = (len + 3) & ~3;
1935 /* CIFS UNIX Extension. */
1937 case SMB_FIND_FILE_UNIX:
1938 case SMB_FIND_FILE_UNIX_INFO2:
1940 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1942 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1944 if (info_level == SMB_FIND_FILE_UNIX) {
1945 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1946 p = store_file_unix_basic(conn, p,
1948 len = srvstr_push(base_data, flags2, p,
1949 fname, PTR_DIFF(end_data, p),
1952 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1953 p = store_file_unix_basic_info2(conn, p,
1957 len = srvstr_push(base_data, flags2, p, fname,
1958 PTR_DIFF(end_data, p), 0);
1959 SIVAL(nameptr, 0, len);
1963 SIVAL(p,0,0); /* Ensure any padding is null. */
1965 len = PTR_DIFF(p, pdata);
1966 len = (len + 3) & ~3;
1967 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1969 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1979 if (PTR_DIFF(p,pdata) > space_remaining) {
1980 /* Move the dirptr back to prev_dirpos */
1981 dptr_SeekDir(conn->dirptr, prev_dirpos);
1982 *out_of_space = True;
1983 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1984 return False; /* Not finished - just out of space */
1987 /* Setup the last entry pointer, as an offset from base_data */
1988 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1989 /* Advance the data pointer to the next slot */
1995 /****************************************************************************
1996 Reply to a TRANS2_FINDFIRST.
1997 ****************************************************************************/
1999 static void call_trans2findfirst(connection_struct *conn,
2000 struct smb_request *req,
2001 char **pparams, int total_params,
2002 char **ppdata, int total_data,
2003 unsigned int max_data_bytes)
2005 /* We must be careful here that we don't return more than the
2006 allowed number of data bytes. If this means returning fewer than
2007 maxentries then so be it. We assume that the redirector has
2008 enough room for the fixed number of parameter bytes it has
2010 struct smb_filename *smb_dname = NULL;
2011 char *params = *pparams;
2012 char *pdata = *ppdata;
2016 uint16 findfirst_flags;
2017 bool close_after_first;
2019 bool requires_resume_key;
2021 char *directory = NULL;
2024 int last_entry_off=0;
2028 bool finished = False;
2029 bool dont_descend = False;
2030 bool out_of_space = False;
2031 int space_remaining;
2032 bool mask_contains_wcard = False;
2033 struct ea_list *ea_list = NULL;
2034 NTSTATUS ntstatus = NT_STATUS_OK;
2035 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2036 TALLOC_CTX *ctx = talloc_tos();
2038 if (total_params < 13) {
2039 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2043 dirtype = SVAL(params,0);
2044 maxentries = SVAL(params,2);
2045 findfirst_flags = SVAL(params,4);
2046 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2047 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2048 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2049 info_level = SVAL(params,6);
2051 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2052 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2053 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2054 info_level, max_data_bytes));
2057 /* W2K3 seems to treat zero as 1. */
2061 switch (info_level) {
2062 case SMB_FIND_INFO_STANDARD:
2063 case SMB_FIND_EA_SIZE:
2064 case SMB_FIND_EA_LIST:
2065 case SMB_FIND_FILE_DIRECTORY_INFO:
2066 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2067 case SMB_FIND_FILE_NAMES_INFO:
2068 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2069 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2070 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2072 case SMB_FIND_FILE_UNIX:
2073 case SMB_FIND_FILE_UNIX_INFO2:
2074 /* Always use filesystem for UNIX mtime query. */
2075 ask_sharemode = false;
2076 if (!lp_unix_extensions()) {
2077 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2082 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2086 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2087 params+12, total_params - 12,
2088 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2089 if (!NT_STATUS_IS_OK(ntstatus)) {
2090 reply_nterror(req, ntstatus);
2094 ntstatus = resolve_dfspath_wcard(ctx, conn,
2095 req->flags2 & FLAGS2_DFS_PATHNAMES,
2098 &mask_contains_wcard);
2099 if (!NT_STATUS_IS_OK(ntstatus)) {
2100 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2101 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2102 ERRSRV, ERRbadpath);
2105 reply_nterror(req, ntstatus);
2109 ntstatus = unix_convert(ctx, conn, directory, &smb_dname,
2110 (UCF_SAVE_LCOMP | UCF_ALLOW_WCARD_LCOMP));
2111 if (!NT_STATUS_IS_OK(ntstatus)) {
2112 reply_nterror(req, ntstatus);
2116 mask = smb_dname->original_lcomp;
2118 directory = smb_dname->base_name;
2120 ntstatus = check_name(conn, directory);
2121 if (!NT_STATUS_IS_OK(ntstatus)) {
2122 reply_nterror(req, ntstatus);
2126 p = strrchr_m(directory,'/');
2128 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2129 if((directory[0] == '.') && (directory[1] == '\0')) {
2130 mask = talloc_strdup(ctx,"*");
2132 reply_nterror(req, NT_STATUS_NO_MEMORY);
2135 mask_contains_wcard = True;
2137 directory = talloc_strdup(talloc_tos(), "./");
2139 reply_nterror(req, NT_STATUS_NO_MEMORY);
2146 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2148 if (info_level == SMB_FIND_EA_LIST) {
2151 if (total_data < 4) {
2152 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2156 ea_size = IVAL(pdata,0);
2157 if (ea_size != total_data) {
2158 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2159 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2160 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2164 if (!lp_ea_support(SNUM(conn))) {
2165 reply_doserror(req, ERRDOS, ERReasnotsupported);
2169 /* Pull out the list of names. */
2170 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2172 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2177 *ppdata = (char *)SMB_REALLOC(
2178 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2179 if(*ppdata == NULL ) {
2180 reply_nterror(req, NT_STATUS_NO_MEMORY);
2184 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2186 /* Realloc the params space */
2187 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2188 if (*pparams == NULL) {
2189 reply_nterror(req, NT_STATUS_NO_MEMORY);
2194 /* Save the wildcard match and attribs we are using on this directory -
2195 needed as lanman2 assumes these are being saved between calls */
2197 ntstatus = dptr_create(conn,
2203 mask_contains_wcard,
2207 if (!NT_STATUS_IS_OK(ntstatus)) {
2208 reply_nterror(req, ntstatus);
2212 dptr_num = dptr_dnum(conn->dirptr);
2213 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2215 /* Initialize per TRANS2_FIND_FIRST operation data */
2216 dptr_init_search_op(conn->dirptr);
2218 /* We don't need to check for VOL here as this is returned by
2219 a different TRANS2 call. */
2221 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2222 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2223 dont_descend = True;
2226 space_remaining = max_data_bytes;
2227 out_of_space = False;
2229 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2230 bool got_exact_match = False;
2232 /* this is a heuristic to avoid seeking the dirptr except when
2233 absolutely necessary. It allows for a filename of about 40 chars */
2234 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2235 out_of_space = True;
2238 finished = !get_lanman2_dir_entry(ctx,
2241 mask,dirtype,info_level,
2242 requires_resume_key,dont_descend,
2245 space_remaining, &out_of_space,
2247 &last_entry_off, ea_list);
2250 if (finished && out_of_space)
2253 if (!finished && !out_of_space)
2257 * As an optimisation if we know we aren't looking
2258 * for a wildcard name (ie. the name matches the wildcard exactly)
2259 * then we can finish on any (first) match.
2260 * This speeds up large directory searches. JRA.
2266 /* Ensure space_remaining never goes -ve. */
2267 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2268 space_remaining = 0;
2269 out_of_space = true;
2271 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2275 /* Check if we can close the dirptr */
2276 if(close_after_first || (finished && close_if_end)) {
2277 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2278 dptr_close(&dptr_num);
2282 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2283 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2284 * the protocol level is less than NT1. Tested with smbclient. JRA.
2285 * This should fix the OS/2 client bug #2335.
2288 if(numentries == 0) {
2289 dptr_close(&dptr_num);
2290 if (Protocol < PROTOCOL_NT1) {
2291 reply_doserror(req, ERRDOS, ERRnofiles);
2294 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2295 ERRDOS, ERRbadfile);
2300 /* At this point pdata points to numentries directory entries. */
2302 /* Set up the return parameter block */
2303 SSVAL(params,0,dptr_num);
2304 SSVAL(params,2,numentries);
2305 SSVAL(params,4,finished);
2306 SSVAL(params,6,0); /* Never an EA error */
2307 SSVAL(params,8,last_entry_off);
2309 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2312 if ((! *directory) && dptr_path(dptr_num)) {
2313 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2315 reply_nterror(req, NT_STATUS_NO_MEMORY);
2319 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2320 smb_fn_name(req->cmd),
2321 mask, directory, dirtype, numentries ) );
2324 * Force a name mangle here to ensure that the
2325 * mask as an 8.3 name is top of the mangled cache.
2326 * The reasons for this are subtle. Don't remove
2327 * this code unless you know what you are doing
2328 * (see PR#13758). JRA.
2331 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2332 char mangled_name[13];
2333 name_to_8_3(mask, mangled_name, True, conn->params);
2336 TALLOC_FREE(smb_dname);
2340 /****************************************************************************
2341 Reply to a TRANS2_FINDNEXT.
2342 ****************************************************************************/
2344 static void call_trans2findnext(connection_struct *conn,
2345 struct smb_request *req,
2346 char **pparams, int total_params,
2347 char **ppdata, int total_data,
2348 unsigned int max_data_bytes)
2350 /* We must be careful here that we don't return more than the
2351 allowed number of data bytes. If this means returning fewer than
2352 maxentries then so be it. We assume that the redirector has
2353 enough room for the fixed number of parameter bytes it has
2355 char *params = *pparams;
2356 char *pdata = *ppdata;
2362 uint16 findnext_flags;
2363 bool close_after_request;
2365 bool requires_resume_key;
2367 bool mask_contains_wcard = False;
2368 char *resume_name = NULL;
2369 const char *mask = NULL;
2370 const char *directory = NULL;
2374 int i, last_entry_off=0;
2375 bool finished = False;
2376 bool dont_descend = False;
2377 bool out_of_space = False;
2378 int space_remaining;
2379 struct ea_list *ea_list = NULL;
2380 NTSTATUS ntstatus = NT_STATUS_OK;
2381 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2382 TALLOC_CTX *ctx = talloc_tos();
2384 if (total_params < 13) {
2385 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2389 dptr_num = SVAL(params,0);
2390 maxentries = SVAL(params,2);
2391 info_level = SVAL(params,4);
2392 resume_key = IVAL(params,6);
2393 findnext_flags = SVAL(params,10);
2394 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2395 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2396 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2397 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2399 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2401 total_params - 12, STR_TERMINATE, &ntstatus,
2402 &mask_contains_wcard);
2403 if (!NT_STATUS_IS_OK(ntstatus)) {
2404 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2405 complain (it thinks we're asking for the directory above the shared
2406 path or an invalid name). Catch this as the resume name is only compared, never used in
2407 a file access. JRA. */
2408 srvstr_pull_talloc(ctx, params, req->flags2,
2409 &resume_name, params+12,
2413 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2414 reply_nterror(req, ntstatus);
2419 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2420 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2421 resume_key = %d resume name = %s continue=%d level = %d\n",
2422 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2423 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2426 /* W2K3 seems to treat zero as 1. */
2430 switch (info_level) {
2431 case SMB_FIND_INFO_STANDARD:
2432 case SMB_FIND_EA_SIZE:
2433 case SMB_FIND_EA_LIST:
2434 case SMB_FIND_FILE_DIRECTORY_INFO:
2435 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2436 case SMB_FIND_FILE_NAMES_INFO:
2437 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2438 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2439 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2441 case SMB_FIND_FILE_UNIX:
2442 case SMB_FIND_FILE_UNIX_INFO2:
2443 /* Always use filesystem for UNIX mtime query. */
2444 ask_sharemode = false;
2445 if (!lp_unix_extensions()) {
2446 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2451 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2455 if (info_level == SMB_FIND_EA_LIST) {
2458 if (total_data < 4) {
2459 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2463 ea_size = IVAL(pdata,0);
2464 if (ea_size != total_data) {
2465 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2466 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2467 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2471 if (!lp_ea_support(SNUM(conn))) {
2472 reply_doserror(req, ERRDOS, ERReasnotsupported);
2476 /* Pull out the list of names. */
2477 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2479 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2484 *ppdata = (char *)SMB_REALLOC(
2485 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2486 if(*ppdata == NULL) {
2487 reply_nterror(req, NT_STATUS_NO_MEMORY);
2492 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2494 /* Realloc the params space */
2495 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2496 if(*pparams == NULL ) {
2497 reply_nterror(req, NT_STATUS_NO_MEMORY);
2503 /* Check that the dptr is valid */
2504 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2505 reply_doserror(req, ERRDOS, ERRnofiles);
2509 string_set(&conn->dirpath,dptr_path(dptr_num));
2511 /* Get the wildcard mask from the dptr */
2512 if((p = dptr_wcard(dptr_num))== NULL) {
2513 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2514 reply_doserror(req, ERRDOS, ERRnofiles);
2519 directory = conn->dirpath;
2521 /* Get the attr mask from the dptr */
2522 dirtype = dptr_attr(dptr_num);
2524 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2525 dptr_num, mask, dirtype,
2527 dptr_TellDir(conn->dirptr)));
2529 /* Initialize per TRANS2_FIND_NEXT operation data */
2530 dptr_init_search_op(conn->dirptr);
2532 /* We don't need to check for VOL here as this is returned by
2533 a different TRANS2 call. */
2535 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2536 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2537 dont_descend = True;
2540 space_remaining = max_data_bytes;
2541 out_of_space = False;
2544 * Seek to the correct position. We no longer use the resume key but
2545 * depend on the last file name instead.
2548 if(*resume_name && !continue_bit) {
2551 long current_pos = 0;
2553 * Remember, name_to_8_3 is called by
2554 * get_lanman2_dir_entry(), so the resume name
2555 * could be mangled. Ensure we check the unmangled name.
2558 if (mangle_is_mangled(resume_name, conn->params)) {
2559 char *new_resume_name = NULL;
2560 mangle_lookup_name_from_8_3(ctx,
2564 if (new_resume_name) {
2565 resume_name = new_resume_name;
2570 * Fix for NT redirector problem triggered by resume key indexes
2571 * changing between directory scans. We now return a resume key of 0
2572 * and instead look for the filename to continue from (also given
2573 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2574 * findfirst/findnext (as is usual) then the directory pointer
2575 * should already be at the correct place.
2578 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2579 } /* end if resume_name && !continue_bit */
2581 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2582 bool got_exact_match = False;
2584 /* this is a heuristic to avoid seeking the dirptr except when
2585 absolutely necessary. It allows for a filename of about 40 chars */
2586 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2587 out_of_space = True;
2590 finished = !get_lanman2_dir_entry(ctx,
2593 mask,dirtype,info_level,
2594 requires_resume_key,dont_descend,
2597 space_remaining, &out_of_space,
2599 &last_entry_off, ea_list);
2602 if (finished && out_of_space)
2605 if (!finished && !out_of_space)
2609 * As an optimisation if we know we aren't looking
2610 * for a wildcard name (ie. the name matches the wildcard exactly)
2611 * then we can finish on any (first) match.
2612 * This speeds up large directory searches. JRA.
2618 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2621 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2622 smb_fn_name(req->cmd),
2623 mask, directory, dirtype, numentries ) );
2625 /* Check if we can close the dirptr */
2626 if(close_after_request || (finished && close_if_end)) {
2627 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2628 dptr_close(&dptr_num); /* This frees up the saved mask */
2631 /* Set up the return parameter block */
2632 SSVAL(params,0,numentries);
2633 SSVAL(params,2,finished);
2634 SSVAL(params,4,0); /* Never an EA error */
2635 SSVAL(params,6,last_entry_off);
2637 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2643 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2645 E_md4hash(lp_servicename(SNUM(conn)),objid);
2649 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2651 SMB_ASSERT(extended_info != NULL);
2653 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2654 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2655 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2656 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2657 #ifdef SAMBA_VERSION_REVISION
2658 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2660 extended_info->samba_subversion = 0;
2661 #ifdef SAMBA_VERSION_RC_RELEASE
2662 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2664 #ifdef SAMBA_VERSION_PRE_RELEASE
2665 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2668 #ifdef SAMBA_VERSION_VENDOR_PATCH
2669 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2671 extended_info->samba_gitcommitdate = 0;
2672 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2673 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2676 memset(extended_info->samba_version_string, 0,
2677 sizeof(extended_info->samba_version_string));
2679 snprintf (extended_info->samba_version_string,
2680 sizeof(extended_info->samba_version_string),
2681 "%s", samba_version_string());
2684 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2685 TALLOC_CTX *mem_ctx,
2686 uint16_t info_level,
2688 unsigned int max_data_bytes,
2692 char *pdata, *end_data;
2693 int data_len = 0, len;
2694 const char *vname = volume_label(SNUM(conn));
2695 int snum = SNUM(conn);
2696 char *fstype = lp_fstype(SNUM(conn));
2697 uint32 additional_flags = 0;
2698 struct smb_filename *smb_fname_dot = NULL;
2703 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2704 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2705 "info level (0x%x) on IPC$.\n",
2706 (unsigned int)info_level));
2707 return NT_STATUS_ACCESS_DENIED;
2711 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2713 status = create_synthetic_smb_fname(talloc_tos(), ".", NULL, NULL,
2715 if (!NT_STATUS_IS_OK(status)) {
2719 if(SMB_VFS_STAT(conn, smb_fname_dot) != 0) {
2720 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2721 TALLOC_FREE(smb_fname_dot);
2722 return map_nt_error_from_unix(errno);
2725 st = smb_fname_dot->st;
2726 TALLOC_FREE(smb_fname_dot);
2728 *ppdata = (char *)SMB_REALLOC(
2729 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2730 if (*ppdata == NULL) {
2731 return NT_STATUS_NO_MEMORY;
2735 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2736 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2738 switch (info_level) {
2739 case SMB_INFO_ALLOCATION:
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 return map_nt_error_from_unix(errno);
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;
2763 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2764 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2765 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2767 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2768 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2769 SIVAL(pdata,l1_cUnit,dsize);
2770 SIVAL(pdata,l1_cUnitAvail,dfree);
2771 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2775 case SMB_INFO_VOLUME:
2776 /* Return volume name */
2778 * Add volume serial number - hash of a combination of
2779 * the called hostname and the service name.
2781 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2783 * Win2k3 and previous mess this up by sending a name length
2784 * one byte short. I believe only older clients (OS/2 Win9x) use
2785 * this call so try fixing this by adding a terminating null to
2786 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2790 pdata+l2_vol_szVolLabel, vname,
2791 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2792 STR_NOALIGN|STR_TERMINATE);
2793 SCVAL(pdata,l2_vol_cch,len);
2794 data_len = l2_vol_szVolLabel + len;
2795 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
2796 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2800 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2801 case SMB_FS_ATTRIBUTE_INFORMATION:
2803 additional_flags = 0;
2804 #if defined(HAVE_SYS_QUOTAS)
2805 additional_flags |= FILE_VOLUME_QUOTAS;
2808 if(lp_nt_acl_support(SNUM(conn))) {
2809 additional_flags |= FILE_PERSISTENT_ACLS;
2812 /* Capabilities are filled in at connection time through STATVFS call */
2813 additional_flags |= conn->fs_capabilities;
2815 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2816 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2817 additional_flags); /* FS ATTRIBUTES */
2819 SIVAL(pdata,4,255); /* Max filename component length */
2820 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2821 and will think we can't do long filenames */
2822 len = srvstr_push(pdata, flags2, pdata+12, fstype,
2823 PTR_DIFF(end_data, pdata+12),
2826 data_len = 12 + len;
2829 case SMB_QUERY_FS_LABEL_INFO:
2830 case SMB_FS_LABEL_INFORMATION:
2831 len = srvstr_push(pdata, flags2, pdata+4, vname,
2832 PTR_DIFF(end_data, pdata+4), 0);
2837 case SMB_QUERY_FS_VOLUME_INFO:
2838 case SMB_FS_VOLUME_INFORMATION:
2841 * Add volume serial number - hash of a combination of
2842 * the called hostname and the service name.
2844 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2845 (str_checksum(get_local_machine_name())<<16));
2847 /* Max label len is 32 characters. */
2848 len = srvstr_push(pdata, flags2, pdata+18, vname,
2849 PTR_DIFF(end_data, pdata+18),
2851 SIVAL(pdata,12,len);
2854 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2855 (int)strlen(vname),vname, lp_servicename(snum)));
2858 case SMB_QUERY_FS_SIZE_INFO:
2859 case SMB_FS_SIZE_INFORMATION:
2861 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2863 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2864 return map_nt_error_from_unix(errno);
2866 block_size = lp_block_size(snum);
2867 if (bsize < block_size) {
2868 uint64_t factor = block_size/bsize;
2873 if (bsize > block_size) {
2874 uint64_t factor = bsize/block_size;
2879 bytes_per_sector = 512;
2880 sectors_per_unit = bsize/bytes_per_sector;
2881 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2882 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2883 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2884 SBIG_UINT(pdata,0,dsize);
2885 SBIG_UINT(pdata,8,dfree);
2886 SIVAL(pdata,16,sectors_per_unit);
2887 SIVAL(pdata,20,bytes_per_sector);
2891 case SMB_FS_FULL_SIZE_INFORMATION:
2893 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2895 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2896 return map_nt_error_from_unix(errno);
2898 block_size = lp_block_size(snum);
2899 if (bsize < block_size) {
2900 uint64_t factor = block_size/bsize;
2905 if (bsize > block_size) {
2906 uint64_t factor = bsize/block_size;
2911 bytes_per_sector = 512;
2912 sectors_per_unit = bsize/bytes_per_sector;
2913 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2914 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2915 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2916 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2917 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2918 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2919 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2920 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2924 case SMB_QUERY_FS_DEVICE_INFO:
2925 case SMB_FS_DEVICE_INFORMATION:
2927 SIVAL(pdata,0,0); /* dev type */
2928 SIVAL(pdata,4,0); /* characteristics */
2931 #ifdef HAVE_SYS_QUOTAS
2932 case SMB_FS_QUOTA_INFORMATION:
2934 * what we have to send --metze:
2936 * Unknown1: 24 NULL bytes
2937 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2938 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2939 * Quota Flags: 2 byte :
2940 * Unknown3: 6 NULL bytes
2944 * details for Quota Flags:
2946 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2947 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2948 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2949 * 0x0001 Enable Quotas: enable quota for this fs
2953 /* we need to fake up a fsp here,
2954 * because its not send in this call
2957 SMB_NTQUOTA_STRUCT quotas;
2960 ZERO_STRUCT(quotas);
2966 if (conn->server_info->utok.uid != sec_initial_uid()) {
2967 DEBUG(0,("set_user_quota: access_denied "
2968 "service [%s] user [%s]\n",
2969 lp_servicename(SNUM(conn)),
2970 conn->server_info->unix_name));
2971 return NT_STATUS_ACCESS_DENIED;
2974 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2975 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2976 return map_nt_error_from_unix(errno);
2981 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
2982 lp_servicename(SNUM(conn))));
2984 /* Unknown1 24 NULL bytes*/
2985 SBIG_UINT(pdata,0,(uint64_t)0);
2986 SBIG_UINT(pdata,8,(uint64_t)0);
2987 SBIG_UINT(pdata,16,(uint64_t)0);
2989 /* Default Soft Quota 8 bytes */
2990 SBIG_UINT(pdata,24,quotas.softlim);
2992 /* Default Hard Quota 8 bytes */
2993 SBIG_UINT(pdata,32,quotas.hardlim);
2995 /* Quota flag 2 bytes */
2996 SSVAL(pdata,40,quotas.qflags);
2998 /* Unknown3 6 NULL bytes */
3004 #endif /* HAVE_SYS_QUOTAS */
3005 case SMB_FS_OBJECTID_INFORMATION:
3007 unsigned char objid[16];
3008 struct smb_extended_info extended_info;
3009 memcpy(pdata,create_volume_objectid(conn, objid),16);
3010 samba_extended_info_version (&extended_info);
3011 SIVAL(pdata,16,extended_info.samba_magic);
3012 SIVAL(pdata,20,extended_info.samba_version);
3013 SIVAL(pdata,24,extended_info.samba_subversion);
3014 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3015 memcpy(pdata+36,extended_info.samba_version_string,28);
3021 * Query the version and capabilities of the CIFS UNIX extensions
3025 case SMB_QUERY_CIFS_UNIX_INFO:
3027 bool large_write = lp_min_receive_file_size() &&
3028 !srv_is_signing_active(smbd_server_conn);
3029 bool large_read = !srv_is_signing_active(smbd_server_conn);
3030 int encrypt_caps = 0;
3032 if (!lp_unix_extensions()) {
3033 return NT_STATUS_INVALID_LEVEL;
3036 switch (conn->encrypt_level) {
3042 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3045 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3046 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3047 large_write = false;
3053 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3054 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3056 /* We have POSIX ACLs, pathname, encryption,
3057 * large read/write, and locking capability. */
3059 SBIG_UINT(pdata,4,((uint64_t)(
3060 CIFS_UNIX_POSIX_ACLS_CAP|
3061 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3062 CIFS_UNIX_FCNTL_LOCKS_CAP|
3063 CIFS_UNIX_EXTATTR_CAP|
3064 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3066 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3068 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3072 case SMB_QUERY_POSIX_FS_INFO:
3075 vfs_statvfs_struct svfs;
3077 if (!lp_unix_extensions()) {
3078 return NT_STATUS_INVALID_LEVEL;
3081 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3085 SIVAL(pdata,0,svfs.OptimalTransferSize);
3086 SIVAL(pdata,4,svfs.BlockSize);
3087 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3088 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3089 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3090 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3091 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3092 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3093 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3095 } else if (rc == EOPNOTSUPP) {
3096 return NT_STATUS_INVALID_LEVEL;
3097 #endif /* EOPNOTSUPP */
3099 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3100 return NT_STATUS_DOS(ERRSRV, ERRerror);
3105 case SMB_QUERY_POSIX_WHOAMI:
3111 if (!lp_unix_extensions()) {
3112 return NT_STATUS_INVALID_LEVEL;
3115 if (max_data_bytes < 40) {
3116 return NT_STATUS_BUFFER_TOO_SMALL;
3119 /* We ARE guest if global_sid_Builtin_Guests is
3120 * in our list of SIDs.
3122 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3123 conn->server_info->ptok)) {
3124 flags |= SMB_WHOAMI_GUEST;
3127 /* We are NOT guest if global_sid_Authenticated_Users
3128 * is in our list of SIDs.
3130 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3131 conn->server_info->ptok)) {
3132 flags &= ~SMB_WHOAMI_GUEST;
3135 /* NOTE: 8 bytes for UID/GID, irrespective of native
3136 * platform size. This matches
3137 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3139 data_len = 4 /* flags */
3146 + 4 /* pad/reserved */
3147 + (conn->server_info->utok.ngroups * 8)
3149 + (conn->server_info->ptok->num_sids *
3153 SIVAL(pdata, 0, flags);
3154 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3156 (uint64_t)conn->server_info->utok.uid);
3157 SBIG_UINT(pdata, 16,
3158 (uint64_t)conn->server_info->utok.gid);
3161 if (data_len >= max_data_bytes) {
3162 /* Potential overflow, skip the GIDs and SIDs. */
3164 SIVAL(pdata, 24, 0); /* num_groups */
3165 SIVAL(pdata, 28, 0); /* num_sids */
3166 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3167 SIVAL(pdata, 36, 0); /* reserved */
3173 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3174 SIVAL(pdata, 28, conn->server_info->num_sids);
3176 /* We walk the SID list twice, but this call is fairly
3177 * infrequent, and I don't expect that it's performance
3178 * sensitive -- jpeach
3180 for (i = 0, sid_bytes = 0;
3181 i < conn->server_info->ptok->num_sids; ++i) {
3182 sid_bytes += ndr_size_dom_sid(
3183 &conn->server_info->ptok->user_sids[i],
3188 /* SID list byte count */
3189 SIVAL(pdata, 32, sid_bytes);
3191 /* 4 bytes pad/reserved - must be zero */
3192 SIVAL(pdata, 36, 0);
3196 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3197 SBIG_UINT(pdata, data_len,
3198 (uint64_t)conn->server_info->utok.groups[i]);
3204 i < conn->server_info->ptok->num_sids; ++i) {
3205 int sid_len = ndr_size_dom_sid(
3206 &conn->server_info->ptok->user_sids[i],
3210 sid_linearize(pdata + data_len, sid_len,
3211 &conn->server_info->ptok->user_sids[i]);
3212 data_len += sid_len;
3218 case SMB_MAC_QUERY_FS_INFO:
3220 * Thursby MAC extension... ONLY on NTFS filesystems
3221 * once we do streams then we don't need this
3223 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3225 SIVAL(pdata,84,0x100); /* Don't support mac... */
3230 return NT_STATUS_INVALID_LEVEL;
3233 *ret_data_len = data_len;
3234 return NT_STATUS_OK;
3237 /****************************************************************************
3238 Reply to a TRANS2_QFSINFO (query filesystem info).
3239 ****************************************************************************/
3241 static void call_trans2qfsinfo(connection_struct *conn,
3242 struct smb_request *req,
3243 char **pparams, int total_params,
3244 char **ppdata, int total_data,
3245 unsigned int max_data_bytes)
3247 char *params = *pparams;
3248 uint16_t info_level;
3252 if (total_params < 2) {
3253 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3257 info_level = SVAL(params,0);
3259 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3260 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3261 DEBUG(0,("call_trans2qfsinfo: encryption required "
3262 "and info level 0x%x sent.\n",
3263 (unsigned int)info_level));
3264 exit_server_cleanly("encryption required "
3270 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3272 status = smbd_do_qfsinfo(conn, req,
3277 if (!NT_STATUS_IS_OK(status)) {
3278 reply_nterror(req, status);
3282 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3285 DEBUG( 4, ( "%s info_level = %d\n",
3286 smb_fn_name(req->cmd), info_level) );
3291 /****************************************************************************
3292 Reply to a TRANS2_SETFSINFO (set filesystem info).
3293 ****************************************************************************/
3295 static void call_trans2setfsinfo(connection_struct *conn,
3296 struct smb_request *req,
3297 char **pparams, int total_params,
3298 char **ppdata, int total_data,
3299 unsigned int max_data_bytes)
3301 char *pdata = *ppdata;
3302 char *params = *pparams;
3305 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3308 if (total_params < 4) {
3309 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3311 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3315 info_level = SVAL(params,2);
3318 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3319 info_level != SMB_SET_CIFS_UNIX_INFO) {
3320 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3321 "info level (0x%x) on IPC$.\n",
3322 (unsigned int)info_level));
3323 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3328 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3329 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3330 DEBUG(0,("call_trans2setfsinfo: encryption required "
3331 "and info level 0x%x sent.\n",
3332 (unsigned int)info_level));
3333 exit_server_cleanly("encryption required "
3339 switch(info_level) {
3340 case SMB_SET_CIFS_UNIX_INFO:
3342 uint16 client_unix_major;
3343 uint16 client_unix_minor;
3344 uint32 client_unix_cap_low;
3345 uint32 client_unix_cap_high;
3347 if (!lp_unix_extensions()) {
3349 NT_STATUS_INVALID_LEVEL);
3353 /* There should be 12 bytes of capabilities set. */
3354 if (total_data < 8) {
3357 NT_STATUS_INVALID_PARAMETER);
3360 client_unix_major = SVAL(pdata,0);
3361 client_unix_minor = SVAL(pdata,2);
3362 client_unix_cap_low = IVAL(pdata,4);
3363 client_unix_cap_high = IVAL(pdata,8);
3364 /* Just print these values for now. */
3365 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3366 cap_low = 0x%x, cap_high = 0x%x\n",
3367 (unsigned int)client_unix_major,
3368 (unsigned int)client_unix_minor,
3369 (unsigned int)client_unix_cap_low,
3370 (unsigned int)client_unix_cap_high ));
3372 /* Here is where we must switch to posix pathname processing... */
3373 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3374 lp_set_posix_pathnames();
3375 mangle_change_to_posix();
3378 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3379 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3380 /* Client that knows how to do posix locks,
3381 * but not posix open/mkdir operations. Set a
3382 * default type for read/write checks. */
3384 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3390 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3393 size_t param_len = 0;
3394 size_t data_len = total_data;
3396 if (!lp_unix_extensions()) {
3399 NT_STATUS_INVALID_LEVEL);
3403 if (lp_smb_encrypt(SNUM(conn)) == false) {
3406 NT_STATUS_NOT_SUPPORTED);
3410 DEBUG( 4,("call_trans2setfsinfo: "
3411 "request transport encryption.\n"));
3413 status = srv_request_encryption_setup(conn,
3414 (unsigned char **)ppdata,
3416 (unsigned char **)pparams,
3419 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3420 !NT_STATUS_IS_OK(status)) {
3421 reply_nterror(req, status);
3425 send_trans2_replies(conn, req,
3432 if (NT_STATUS_IS_OK(status)) {
3433 /* Server-side transport
3434 * encryption is now *on*. */
3435 status = srv_encryption_start(conn);
3436 if (!NT_STATUS_IS_OK(status)) {
3437 exit_server_cleanly(
3438 "Failure in setting "
3439 "up encrypted transport");
3445 case SMB_FS_QUOTA_INFORMATION:
3447 files_struct *fsp = NULL;
3448 SMB_NTQUOTA_STRUCT quotas;
3450 ZERO_STRUCT(quotas);
3453 if ((conn->server_info->utok.uid != sec_initial_uid())
3454 ||!CAN_WRITE(conn)) {
3455 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3456 lp_servicename(SNUM(conn)),
3457 conn->server_info->unix_name));
3458 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3462 /* note: normaly there're 48 bytes,
3463 * but we didn't use the last 6 bytes for now
3466 fsp = file_fsp(req, SVAL(params,0));
3468 if (!check_fsp_ntquota_handle(conn, req,
3470 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3472 req, NT_STATUS_INVALID_HANDLE);
3476 if (total_data < 42) {
3477 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3481 NT_STATUS_INVALID_PARAMETER);
3485 /* unknown_1 24 NULL bytes in pdata*/
3487 /* the soft quotas 8 bytes (uint64_t)*/
3488 quotas.softlim = (uint64_t)IVAL(pdata,24);
3489 #ifdef LARGE_SMB_OFF_T
3490 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3491 #else /* LARGE_SMB_OFF_T */
3492 if ((IVAL(pdata,28) != 0)&&
3493 ((quotas.softlim != 0xFFFFFFFF)||
3494 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3495 /* more than 32 bits? */
3498 NT_STATUS_INVALID_PARAMETER);
3501 #endif /* LARGE_SMB_OFF_T */
3503 /* the hard quotas 8 bytes (uint64_t)*/
3504 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3505 #ifdef LARGE_SMB_OFF_T
3506 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3507 #else /* LARGE_SMB_OFF_T */
3508 if ((IVAL(pdata,36) != 0)&&
3509 ((quotas.hardlim != 0xFFFFFFFF)||
3510 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3511 /* more than 32 bits? */
3514 NT_STATUS_INVALID_PARAMETER);
3517 #endif /* LARGE_SMB_OFF_T */
3519 /* quota_flags 2 bytes **/
3520 quotas.qflags = SVAL(pdata,40);
3522 /* unknown_2 6 NULL bytes follow*/
3524 /* now set the quotas */
3525 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3526 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3527 reply_nterror(req, map_nt_error_from_unix(errno));
3534 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3536 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3542 * sending this reply works fine,
3543 * but I'm not sure it's the same
3544 * like windows do...
3547 reply_outbuf(req, 10, 0);
3550 #if defined(HAVE_POSIX_ACLS)
3551 /****************************************************************************
3552 Utility function to count the number of entries in a POSIX acl.
3553 ****************************************************************************/
3555 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3557 unsigned int ace_count = 0;
3558 int entry_id = SMB_ACL_FIRST_ENTRY;
3559 SMB_ACL_ENTRY_T entry;
3561 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3563 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3564 entry_id = SMB_ACL_NEXT_ENTRY;
3571 /****************************************************************************
3572 Utility function to marshall a POSIX acl into wire format.
3573 ****************************************************************************/
3575 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3577 int entry_id = SMB_ACL_FIRST_ENTRY;
3578 SMB_ACL_ENTRY_T entry;
3580 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3581 SMB_ACL_TAG_T tagtype;
3582 SMB_ACL_PERMSET_T permset;
3583 unsigned char perms = 0;
3584 unsigned int own_grp;
3587 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3588 entry_id = SMB_ACL_NEXT_ENTRY;
3591 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3592 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3596 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3597 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3601 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3602 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3603 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3605 SCVAL(pdata,1,perms);
3608 case SMB_ACL_USER_OBJ:
3609 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3610 own_grp = (unsigned int)pst->st_ex_uid;
3611 SIVAL(pdata,2,own_grp);
3616 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3618 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3621 own_grp = (unsigned int)*puid;
3622 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3623 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3624 SIVAL(pdata,2,own_grp);
3628 case SMB_ACL_GROUP_OBJ:
3629 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3630 own_grp = (unsigned int)pst->st_ex_gid;
3631 SIVAL(pdata,2,own_grp);
3636 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3638 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3641 own_grp = (unsigned int)*pgid;
3642 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3643 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3644 SIVAL(pdata,2,own_grp);
3649 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3650 SIVAL(pdata,2,0xFFFFFFFF);
3651 SIVAL(pdata,6,0xFFFFFFFF);
3654 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3655 SIVAL(pdata,2,0xFFFFFFFF);
3656 SIVAL(pdata,6,0xFFFFFFFF);
3659 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3662 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3669 /****************************************************************************
3670 Store the FILE_UNIX_BASIC info.
3671 ****************************************************************************/
3673 static char *store_file_unix_basic(connection_struct *conn,
3676 const SMB_STRUCT_STAT *psbuf)
3678 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3679 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3681 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3684 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3687 put_long_date_timespec(pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3688 put_long_date_timespec(pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3689 put_long_date_timespec(pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3692 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3696 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3700 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3703 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3707 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3711 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */
3714 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3718 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3725 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3726 * the chflags(2) (or equivalent) flags.
3728 * XXX: this really should be behind the VFS interface. To do this, we would
3729 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3730 * Each VFS module could then implement its own mapping as appropriate for the
3731 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3733 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3737 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3741 { UF_IMMUTABLE, EXT_IMMUTABLE },
3745 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3749 { UF_HIDDEN, EXT_HIDDEN },
3752 /* Do not remove. We need to guarantee that this array has at least one
3753 * entry to build on HP-UX.
3759 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3760 uint32 *smb_fflags, uint32 *smb_fmask)
3764 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3765 *smb_fmask |= info2_flags_map[i].smb_fflag;
3766 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3767 *smb_fflags |= info2_flags_map[i].smb_fflag;
3772 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3773 const uint32 smb_fflags,
3774 const uint32 smb_fmask,
3777 uint32 max_fmask = 0;
3780 *stat_fflags = psbuf->st_ex_flags;
3782 /* For each flags requested in smb_fmask, check the state of the
3783 * corresponding flag in smb_fflags and set or clear the matching
3787 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3788 max_fmask |= info2_flags_map[i].smb_fflag;
3789 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3790 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3791 *stat_fflags |= info2_flags_map[i].stat_fflag;
3793 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3798 /* If smb_fmask is asking to set any bits that are not supported by
3799 * our flag mappings, we should fail.
3801 if ((smb_fmask & max_fmask) != smb_fmask) {
3809 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3810 * of file flags and birth (create) time.
3812 static char *store_file_unix_basic_info2(connection_struct *conn,
3815 const SMB_STRUCT_STAT *psbuf)
3817 uint32 file_flags = 0;
3818 uint32 flags_mask = 0;
3820 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3822 /* Create (birth) time 64 bit */
3823 put_long_date_timespec(pdata, psbuf->st_ex_btime);
3826 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3827 SIVAL(pdata, 0, file_flags); /* flags */
3828 SIVAL(pdata, 4, flags_mask); /* mask */
3834 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3835 const struct stream_struct *streams,
3837 unsigned int max_data_bytes,
3838 unsigned int *data_size)
3841 unsigned int ofs = 0;
3843 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3844 unsigned int next_offset;
3846 smb_ucs2_t *namebuf;
3848 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3849 streams[i].name, &namelen) ||
3852 return NT_STATUS_INVALID_PARAMETER;
3856 * name_buf is now null-terminated, we need to marshall as not
3862 SIVAL(data, ofs+4, namelen);
3863 SOFF_T(data, ofs+8, streams[i].size);
3864 SOFF_T(data, ofs+16, streams[i].alloc_size);
3865 memcpy(data+ofs+24, namebuf, namelen);
3866 TALLOC_FREE(namebuf);
3868 next_offset = ofs + 24 + namelen;
3870 if (i == num_streams-1) {
3871 SIVAL(data, ofs, 0);
3874 unsigned int align = ndr_align_size(next_offset, 8);
3876 memset(data+next_offset, 0, align);
3877 next_offset += align;
3879 SIVAL(data, ofs, next_offset - ofs);
3888 return NT_STATUS_OK;
3891 /****************************************************************************
3892 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3893 ****************************************************************************/
3895 static void call_trans2qpipeinfo(connection_struct *conn,
3896 struct smb_request *req,
3897 unsigned int tran_call,
3898 char **pparams, int total_params,
3899 char **ppdata, int total_data,
3900 unsigned int max_data_bytes)
3902 char *params = *pparams;
3903 char *pdata = *ppdata;
3904 unsigned int data_size = 0;
3905 unsigned int param_size = 2;
3910 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3914 if (total_params < 4) {
3915 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3919 fsp = file_fsp(req, SVAL(params,0));
3920 if (!fsp_is_np(fsp)) {
3921 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3925 info_level = SVAL(params,2);
3927 *pparams = (char *)SMB_REALLOC(*pparams,2);
3928 if (*pparams == NULL) {
3929 reply_nterror(req, NT_STATUS_NO_MEMORY);
3934 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3935 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3936 if (*ppdata == NULL ) {
3937 reply_nterror(req, NT_STATUS_NO_MEMORY);
3942 switch (info_level) {
3943 case SMB_FILE_STANDARD_INFORMATION:
3945 SOFF_T(pdata,0,4096LL);
3952 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3956 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3962 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
3963 TALLOC_CTX *mem_ctx,
3964 uint16_t info_level,
3966 const struct smb_filename *smb_fname,
3967 bool delete_pending,
3968 struct timespec write_time_ts,
3970 struct ea_list *ea_list,
3971 int lock_data_count,
3974 unsigned int max_data_bytes,
3976 unsigned int *pdata_size)
3978 char *pdata = *ppdata;
3979 char *dstart, *dend;
3980 unsigned int data_size;
3981 struct timespec create_time_ts, mtime_ts, atime_ts;
3982 time_t create_time, mtime, atime;
3983 SMB_STRUCT_STAT sbuf;
3990 uint64_t file_size = 0;
3992 uint64_t allocation_size = 0;
3993 uint64_t file_index = 0;
3994 uint32_t access_mask = 0;
3996 sbuf = smb_fname->st;
3998 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3999 return NT_STATUS_INVALID_LEVEL;
4002 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4003 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4004 info_level, max_data_bytes));
4007 mode = dos_mode_msdfs(conn, smb_fname);
4009 mode = dos_mode(conn, smb_fname);
4012 mode = FILE_ATTRIBUTE_NORMAL;
4014 nlink = sbuf.st_ex_nlink;
4016 if (nlink && (mode&aDIR)) {
4020 if ((nlink > 0) && delete_pending) {
4024 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4025 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4026 if (*ppdata == NULL) {
4027 return NT_STATUS_NO_MEMORY;
4031 dend = dstart + data_size - 1;
4033 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4034 update_stat_ex_mtime(&sbuf, write_time_ts);
4037 create_time_ts = sbuf.st_ex_btime;
4038 mtime_ts = sbuf.st_ex_mtime;
4039 atime_ts = sbuf.st_ex_atime;
4041 if (lp_dos_filetime_resolution(SNUM(conn))) {
4042 dos_filetime_timespec(&create_time_ts);
4043 dos_filetime_timespec(&mtime_ts);
4044 dos_filetime_timespec(&atime_ts);
4047 create_time = convert_timespec_to_time_t(create_time_ts);
4048 mtime = convert_timespec_to_time_t(mtime_ts);
4049 atime = convert_timespec_to_time_t(atime_ts);
4051 p = strrchr_m(smb_fname->base_name,'/');
4053 base_name = smb_fname->base_name;
4057 /* NT expects the name to be in an exact form of the *full*
4058 filename. See the trans2 torture test */
4059 if (ISDOT(base_name)) {
4060 dos_fname = talloc_strdup(mem_ctx, "\\");
4062 return NT_STATUS_NO_MEMORY;
4065 dos_fname = talloc_asprintf(mem_ctx,
4067 smb_fname->base_name);
4069 return NT_STATUS_NO_MEMORY;
4071 if (is_ntfs_stream_smb_fname(smb_fname)) {
4072 dos_fname = talloc_asprintf(dos_fname, "%s",
4073 smb_fname->stream_name);
4075 return NT_STATUS_NO_MEMORY;
4079 string_replace(dos_fname, '/', '\\');
4082 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &sbuf);
4085 /* Do we have this path open ? */
4087 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4088 fsp1 = file_find_di_first(fileid);
4089 if (fsp1 && fsp1->initial_allocation_size) {
4090 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
4094 if (!(mode & aDIR)) {
4095 file_size = get_file_size_stat(&sbuf);
4099 pos = fsp->fh->position_information;
4103 access_mask = fsp->access_mask;
4105 /* GENERIC_EXECUTE mapping from Windows */
4106 access_mask = 0x12019F;
4109 /* This should be an index number - looks like
4112 I think this causes us to fail the IFSKIT
4113 BasicFileInformationTest. -tpot */
4114 file_index = ((sbuf.st_ex_ino) & UINT32_MAX); /* FileIndexLow */
4115 file_index |= ((uint64_t)((sbuf.st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
4117 switch (info_level) {
4118 case SMB_INFO_STANDARD:
4119 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4121 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4122 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4123 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4124 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4125 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4126 SSVAL(pdata,l1_attrFile,mode);
4129 case SMB_INFO_QUERY_EA_SIZE:
4131 unsigned int ea_size =
4132 estimate_ea_size(conn, fsp,
4133 smb_fname->base_name);
4134 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4136 srv_put_dos_date2(pdata,0,create_time);
4137 srv_put_dos_date2(pdata,4,atime);
4138 srv_put_dos_date2(pdata,8,mtime); /* write time */
4139 SIVAL(pdata,12,(uint32)file_size);
4140 SIVAL(pdata,16,(uint32)allocation_size);
4141 SSVAL(pdata,20,mode);
4142 SIVAL(pdata,22,ea_size);
4146 case SMB_INFO_IS_NAME_VALID:
4147 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4149 /* os/2 needs this ? really ?*/
4150 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4152 /* This is only reached for qpathinfo */
4156 case SMB_INFO_QUERY_EAS_FROM_LIST:
4158 size_t total_ea_len = 0;
4159 struct ea_list *ea_file_list = NULL;
4161 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4164 get_ea_list_from_file(mem_ctx, conn, fsp,
4165 smb_fname->base_name,
4167 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4169 if (!ea_list || (total_ea_len > data_size)) {
4171 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4175 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4179 case SMB_INFO_QUERY_ALL_EAS:
4181 /* We have data_size bytes to put EA's into. */
4182 size_t total_ea_len = 0;
4184 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4186 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4187 smb_fname->base_name,
4189 if (!ea_list || (total_ea_len > data_size)) {
4191 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4195 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4199 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4201 /* We have data_size bytes to put EA's into. */
4202 size_t total_ea_len = 0;
4203 struct ea_list *ea_file_list = NULL;
4205 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4207 /*TODO: add filtering and index handling */
4210 get_ea_list_from_file(mem_ctx, conn, fsp,
4211 smb_fname->base_name,
4213 if (!ea_file_list) {
4214 return NT_STATUS_NO_EAS_ON_FILE;
4217 status = fill_ea_chained_buffer(mem_ctx,
4221 conn, ea_file_list);
4222 if (!NT_STATUS_IS_OK(status)) {
4228 case SMB_FILE_BASIC_INFORMATION:
4229 case SMB_QUERY_FILE_BASIC_INFO:
4231 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4232 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4233 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4235 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4239 put_long_date_timespec(pdata,create_time_ts);
4240 put_long_date_timespec(pdata+8,atime_ts);
4241 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4242 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4243 SIVAL(pdata,32,mode);
4245 DEBUG(5,("SMB_QFBI - "));
4246 DEBUG(5,("create: %s ", ctime(&create_time)));
4247 DEBUG(5,("access: %s ", ctime(&atime)));
4248 DEBUG(5,("write: %s ", ctime(&mtime)));
4249 DEBUG(5,("change: %s ", ctime(&mtime)));
4250 DEBUG(5,("mode: %x\n", mode));
4253 case SMB_FILE_STANDARD_INFORMATION:
4254 case SMB_QUERY_FILE_STANDARD_INFO:
4256 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4258 SOFF_T(pdata,0,allocation_size);
4259 SOFF_T(pdata,8,file_size);
4260 SIVAL(pdata,16,nlink);
4261 SCVAL(pdata,20,delete_pending?1:0);
4262 SCVAL(pdata,21,(mode&aDIR)?1:0);
4263 SSVAL(pdata,22,0); /* Padding. */
4266 case SMB_FILE_EA_INFORMATION:
4267 case SMB_QUERY_FILE_EA_INFO:
4269 unsigned int ea_size =
4270 estimate_ea_size(conn, fsp, smb_fname->base_name);
4271 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4273 SIVAL(pdata,0,ea_size);
4277 /* Get the 8.3 name - used if NT SMB was negotiated. */
4278 case SMB_QUERY_FILE_ALT_NAME_INFO:
4279 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4282 char mangled_name[13];
4283 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4284 if (!name_to_8_3(base_name,mangled_name,
4285 True,conn->params)) {
4286 return NT_STATUS_NO_MEMORY;
4288 len = srvstr_push(dstart, flags2,
4289 pdata+4, mangled_name,
4290 PTR_DIFF(dend, pdata+4),
4292 data_size = 4 + len;
4297 case SMB_QUERY_FILE_NAME_INFO:
4301 this must be *exactly* right for ACLs on mapped drives to work
4303 len = srvstr_push(dstart, flags2,
4305 PTR_DIFF(dend, pdata+4),
4307 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4308 data_size = 4 + len;
4313 case SMB_FILE_ALLOCATION_INFORMATION:
4314 case SMB_QUERY_FILE_ALLOCATION_INFO:
4315 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4317 SOFF_T(pdata,0,allocation_size);
4320 case SMB_FILE_END_OF_FILE_INFORMATION:
4321 case SMB_QUERY_FILE_END_OF_FILEINFO:
4322 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4324 SOFF_T(pdata,0,file_size);
4327 case SMB_QUERY_FILE_ALL_INFO:
4328 case SMB_FILE_ALL_INFORMATION:
4331 unsigned int ea_size =
4332 estimate_ea_size(conn, fsp, smb_fname->base_name);
4333 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4334 put_long_date_timespec(pdata,create_time_ts);
4335 put_long_date_timespec(pdata+8,atime_ts);
4336 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4337 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4338 SIVAL(pdata,32,mode);
4339 SIVAL(pdata,36,0); /* padding. */
4341 SOFF_T(pdata,0,allocation_size);
4342 SOFF_T(pdata,8,file_size);
4343 SIVAL(pdata,16,nlink);
4344 SCVAL(pdata,20,delete_pending);
4345 SCVAL(pdata,21,(mode&aDIR)?1:0);
4348 SIVAL(pdata,0,ea_size);
4349 pdata += 4; /* EA info */
4350 len = srvstr_push(dstart, flags2,
4352 PTR_DIFF(dend, pdata+4),
4356 data_size = PTR_DIFF(pdata,(*ppdata));
4360 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4363 unsigned int ea_size =
4364 estimate_ea_size(conn, fsp, smb_fname->base_name);
4365 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4366 put_long_date_timespec(pdata+0x00,create_time_ts);
4367 put_long_date_timespec(pdata+0x08,atime_ts);
4368 put_long_date_timespec(pdata+0x10,mtime_ts); /* write time */
4369 put_long_date_timespec(pdata+0x18,mtime_ts); /* change time */
4370 SIVAL(pdata, 0x20, mode);
4371 SIVAL(pdata, 0x24, 0); /* padding. */
4372 SBVAL(pdata, 0x28, allocation_size);
4373 SBVAL(pdata, 0x30, file_size);
4374 SIVAL(pdata, 0x38, nlink);
4375 SCVAL(pdata, 0x3C, delete_pending);
4376 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4377 SSVAL(pdata, 0x3E, 0); /* padding */
4378 SBVAL(pdata, 0x40, file_index);
4379 SIVAL(pdata, 0x48, ea_size);
4380 SIVAL(pdata, 0x4C, access_mask);
4381 SBVAL(pdata, 0x50, pos);
4382 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4383 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4387 len = srvstr_push(dstart, flags2,
4389 PTR_DIFF(dend, pdata+4),
4393 data_size = PTR_DIFF(pdata,(*ppdata));
4396 case SMB_FILE_INTERNAL_INFORMATION:
4398 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4399 SBVAL(pdata, 0, file_index);
4403 case SMB_FILE_ACCESS_INFORMATION:
4404 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4405 SIVAL(pdata, 0, access_mask);
4409 case SMB_FILE_NAME_INFORMATION:
4410 /* Pathname with leading '\'. */
4413 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4414 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4415 SIVAL(pdata,0,byte_len);
4416 data_size = 4 + byte_len;
4420 case SMB_FILE_DISPOSITION_INFORMATION:
4421 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4423 SCVAL(pdata,0,delete_pending);
4426 case SMB_FILE_POSITION_INFORMATION:
4427 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4429 SOFF_T(pdata,0,pos);
4432 case SMB_FILE_MODE_INFORMATION:
4433 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4434 SIVAL(pdata,0,mode);
4438 case SMB_FILE_ALIGNMENT_INFORMATION:
4439 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4440 SIVAL(pdata,0,0); /* No alignment needed. */
4445 * NT4 server just returns "invalid query" to this - if we try
4446 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4449 /* The first statement above is false - verified using Thursby
4450 * client against NT4 -- gcolley.
4452 case SMB_QUERY_FILE_STREAM_INFO:
4453 case SMB_FILE_STREAM_INFORMATION: {
4454 unsigned int num_streams;
4455 struct stream_struct *streams;
4457 DEBUG(10,("smbd_do_qfilepathinfo: "
4458 "SMB_FILE_STREAM_INFORMATION\n"));
4460 if (is_ntfs_stream_smb_fname(smb_fname)) {
4461 return NT_STATUS_INVALID_PARAMETER;
4464 status = SMB_VFS_STREAMINFO(
4465 conn, fsp, smb_fname->base_name, talloc_tos(),
4466 &num_streams, &streams);
4468 if (!NT_STATUS_IS_OK(status)) {
4469 DEBUG(10, ("could not get stream info: %s\n",
4470 nt_errstr(status)));
4474 status = marshall_stream_info(num_streams, streams,
4475 pdata, max_data_bytes,
4478 if (!NT_STATUS_IS_OK(status)) {
4479 DEBUG(10, ("marshall_stream_info failed: %s\n",
4480 nt_errstr(status)));
4484 TALLOC_FREE(streams);
4488 case SMB_QUERY_COMPRESSION_INFO:
4489 case SMB_FILE_COMPRESSION_INFORMATION:
4490 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4491 SOFF_T(pdata,0,file_size);
4492 SIVAL(pdata,8,0); /* ??? */
4493 SIVAL(pdata,12,0); /* ??? */
4497 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4498 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4499 put_long_date_timespec(pdata,create_time_ts);
4500 put_long_date_timespec(pdata+8,atime_ts);
4501 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4502 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4503 SOFF_T(pdata,32,allocation_size);
4504 SOFF_T(pdata,40,file_size);
4505 SIVAL(pdata,48,mode);
4506 SIVAL(pdata,52,0); /* ??? */
4510 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4511 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4512 SIVAL(pdata,0,mode);
4518 * CIFS UNIX Extensions.
4521 case SMB_QUERY_FILE_UNIX_BASIC:
4523 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4524 data_size = PTR_DIFF(pdata,(*ppdata));
4528 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4530 for (i=0; i<100; i++)
4531 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4537 case SMB_QUERY_FILE_UNIX_INFO2:
4539 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4540 data_size = PTR_DIFF(pdata,(*ppdata));
4544 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4546 for (i=0; i<100; i++)
4547 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4553 case SMB_QUERY_FILE_UNIX_LINK:
4556 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4559 return NT_STATUS_NO_MEMORY;
4562 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4564 if(!S_ISLNK(sbuf.st_ex_mode)) {
4565 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4568 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4570 len = SMB_VFS_READLINK(conn,
4571 smb_fname->base_name,
4574 return map_nt_error_from_unix(errno);
4577 len = srvstr_push(dstart, flags2,
4579 PTR_DIFF(dend, pdata),
4582 data_size = PTR_DIFF(pdata,(*ppdata));
4587 #if defined(HAVE_POSIX_ACLS)
4588 case SMB_QUERY_POSIX_ACL:
4590 SMB_ACL_T file_acl = NULL;
4591 SMB_ACL_T def_acl = NULL;
4592 uint16 num_file_acls = 0;
4593 uint16 num_def_acls = 0;
4595 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4596 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4599 SMB_VFS_SYS_ACL_GET_FILE(conn,
4600 smb_fname->base_name,
4601 SMB_ACL_TYPE_ACCESS);
4604 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4605 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4606 "not implemented on "
4607 "filesystem containing %s\n",
4608 smb_fname->base_name));
4609 return NT_STATUS_NOT_IMPLEMENTED;
4612 if (S_ISDIR(sbuf.st_ex_mode)) {
4613 if (fsp && fsp->is_directory) {
4615 SMB_VFS_SYS_ACL_GET_FILE(
4617 fsp->fsp_name->base_name,
4618 SMB_ACL_TYPE_DEFAULT);
4621 SMB_VFS_SYS_ACL_GET_FILE(
4623 smb_fname->base_name,
4624 SMB_ACL_TYPE_DEFAULT);
4626 def_acl = free_empty_sys_acl(conn, def_acl);
4629 num_file_acls = count_acl_entries(conn, file_acl);
4630 num_def_acls = count_acl_entries(conn, def_acl);
4632 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4633 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4635 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4636 SMB_POSIX_ACL_HEADER_SIZE) ));
4638 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4641 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4643 return NT_STATUS_BUFFER_TOO_SMALL;
4646 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4647 SSVAL(pdata,2,num_file_acls);
4648 SSVAL(pdata,4,num_def_acls);
4649 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4651 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4654 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4656 return NT_STATUS_INTERNAL_ERROR;
4658 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4660 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4663 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4665 return NT_STATUS_INTERNAL_ERROR;
4669 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4672 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4674 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4680 case SMB_QUERY_POSIX_LOCK:
4685 enum brl_type lock_type;
4687 /* We need an open file with a real fd for this. */
4688 if (!fsp || fsp->is_directory || fsp->fh->fd == -1) {
4689 return NT_STATUS_INVALID_LEVEL;
4692 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4693 return NT_STATUS_INVALID_PARAMETER;
4696 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4697 case POSIX_LOCK_TYPE_READ:
4698 lock_type = READ_LOCK;
4700 case POSIX_LOCK_TYPE_WRITE:
4701 lock_type = WRITE_LOCK;
4703 case POSIX_LOCK_TYPE_UNLOCK:
4705 /* There's no point in asking for an unlock... */
4706 return NT_STATUS_INVALID_PARAMETER;
4709 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4710 #if defined(HAVE_LONGLONG)
4711 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4712 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4713 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4714 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4715 #else /* HAVE_LONGLONG */
4716 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4717 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4718 #endif /* HAVE_LONGLONG */
4720 status = query_lock(fsp,
4727 if (ERROR_WAS_LOCK_DENIED(status)) {
4728 /* Here we need to report who has it locked... */
4729 data_size = POSIX_LOCK_DATA_SIZE;
4731 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4732 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4733 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4734 #if defined(HAVE_LONGLONG)
4735 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4736 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4737 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4738 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4739 #else /* HAVE_LONGLONG */
4740 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4741 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4742 #endif /* HAVE_LONGLONG */
4744 } else if (NT_STATUS_IS_OK(status)) {
4745 /* For success we just return a copy of what we sent
4746 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4747 data_size = POSIX_LOCK_DATA_SIZE;
4748 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4749 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4757 return NT_STATUS_INVALID_LEVEL;
4760 *pdata_size = data_size;
4761 return NT_STATUS_OK;
4764 /****************************************************************************
4765 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4766 file name or file id).
4767 ****************************************************************************/
4769 static void call_trans2qfilepathinfo(connection_struct *conn,
4770 struct smb_request *req,
4771 unsigned int tran_call,
4772 char **pparams, int total_params,
4773 char **ppdata, int total_data,
4774 unsigned int max_data_bytes)
4776 char *params = *pparams;
4777 char *pdata = *ppdata;
4779 unsigned int data_size = 0;
4780 unsigned int param_size = 2;
4781 struct smb_filename *smb_fname = NULL;
4782 bool delete_pending = False;
4783 struct timespec write_time_ts;
4784 files_struct *fsp = NULL;
4785 struct file_id fileid;
4786 struct ea_list *ea_list = NULL;
4787 int lock_data_count = 0;
4788 char *lock_data = NULL;
4789 bool ms_dfs_link = false;
4790 NTSTATUS status = NT_STATUS_OK;
4793 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4797 ZERO_STRUCT(write_time_ts);
4799 if (tran_call == TRANSACT2_QFILEINFO) {
4800 if (total_params < 4) {
4801 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4806 call_trans2qpipeinfo(conn, req, tran_call,
4807 pparams, total_params,
4813 fsp = file_fsp(req, SVAL(params,0));
4814 info_level = SVAL(params,2);
4816 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
4818 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4819 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4823 /* Initial check for valid fsp ptr. */
4824 if (!check_fsp_open(conn, req, fsp)) {
4828 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
4830 if (!NT_STATUS_IS_OK(status)) {
4831 reply_nterror(req, status);
4835 if(fsp->fake_file_handle) {
4837 * This is actually for the QUOTA_FAKE_FILE --metze
4840 /* We know this name is ok, it's already passed the checks. */
4842 } else if(fsp->is_directory || fsp->fh->fd == -1) {
4844 * This is actually a QFILEINFO on a directory
4845 * handle (returned from an NT SMB). NT5.0 seems
4846 * to do this call. JRA.
4849 if (INFO_LEVEL_IS_UNIX(info_level)) {
4850 /* Always do lstat for UNIX calls. */
4851 if (SMB_VFS_LSTAT(conn, smb_fname)) {
4852 DEBUG(3,("call_trans2qfilepathinfo: "
4853 "SMB_VFS_LSTAT of %s failed "
4855 smb_fname_str_dbg(smb_fname),
4858 map_nt_error_from_unix(errno));
4861 } else if (SMB_VFS_STAT(conn, smb_fname)) {
4862 DEBUG(3,("call_trans2qfilepathinfo: "
4863 "SMB_VFS_STAT of %s failed (%s)\n",
4864 smb_fname_str_dbg(smb_fname),
4867 map_nt_error_from_unix(errno));
4871 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4872 get_file_infos(fileid, &delete_pending, &write_time_ts);
4875 * Original code - this is an open file.
4877 if (!check_fsp(conn, req, fsp)) {
4881 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
4882 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
4883 fsp->fnum, strerror(errno)));
4885 map_nt_error_from_unix(errno));
4888 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4889 get_file_infos(fileid, &delete_pending, &write_time_ts);
4896 if (total_params < 7) {
4897 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4901 info_level = SVAL(params,0);
4903 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
4905 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4906 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4910 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
4912 STR_TERMINATE, &status);
4913 if (!NT_STATUS_IS_OK(status)) {
4914 reply_nterror(req, status);
4918 status = filename_convert(req,
4920 req->flags2 & FLAGS2_DFS_PATHNAMES,
4925 if (!NT_STATUS_IS_OK(status)) {
4926 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4927 reply_botherror(req,
4928 NT_STATUS_PATH_NOT_COVERED,
4929 ERRSRV, ERRbadpath);
4932 reply_nterror(req, status);
4936 /* If this is a stream, check if there is a delete_pending. */
4937 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
4938 && is_ntfs_stream_smb_fname(smb_fname)) {
4939 struct smb_filename *smb_fname_base = NULL;
4941 /* Create an smb_filename with stream_name == NULL. */
4943 create_synthetic_smb_fname(talloc_tos(),
4944 smb_fname->base_name,
4947 if (!NT_STATUS_IS_OK(status)) {
4948 reply_nterror(req, status);
4952 if (INFO_LEVEL_IS_UNIX(info_level)) {
4953 /* Always do lstat for UNIX calls. */
4954 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
4955 DEBUG(3,("call_trans2qfilepathinfo: "
4956 "SMB_VFS_LSTAT of %s failed "
4958 smb_fname_str_dbg(smb_fname_base),
4960 TALLOC_FREE(smb_fname_base);
4962 map_nt_error_from_unix(errno));
4966 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
4967 DEBUG(3,("call_trans2qfilepathinfo: "
4968 "fileinfo of %s failed "
4970 smb_fname_str_dbg(smb_fname_base),
4972 TALLOC_FREE(smb_fname_base);
4974 map_nt_error_from_unix(errno));
4979 fileid = vfs_file_id_from_sbuf(conn,
4980 &smb_fname_base->st);
4981 TALLOC_FREE(smb_fname_base);
4982 get_file_infos(fileid, &delete_pending, NULL);
4983 if (delete_pending) {
4984 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4989 if (INFO_LEVEL_IS_UNIX(info_level)) {
4990 /* Always do lstat for UNIX calls. */
4991 if (SMB_VFS_LSTAT(conn, smb_fname)) {
4992 DEBUG(3,("call_trans2qfilepathinfo: "
4993 "SMB_VFS_LSTAT of %s failed (%s)\n",
4994 smb_fname_str_dbg(smb_fname),
4997 map_nt_error_from_unix(errno));
5001 } else if (!VALID_STAT(smb_fname->st) &&
5002 SMB_VFS_STAT(conn, smb_fname) &&
5003 (info_level != SMB_INFO_IS_NAME_VALID)) {
5004 ms_dfs_link = check_msdfs_link(conn,
5005 smb_fname->base_name,
5009 DEBUG(3,("call_trans2qfilepathinfo: "
5010 "SMB_VFS_STAT of %s failed (%s)\n",
5011 smb_fname_str_dbg(smb_fname),
5014 map_nt_error_from_unix(errno));
5019 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5020 get_file_infos(fileid, &delete_pending, &write_time_ts);
5021 if (delete_pending) {
5022 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5027 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5028 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5029 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5031 /* Pull out any data sent here before we realloc. */
5032 switch (info_level) {
5033 case SMB_INFO_QUERY_EAS_FROM_LIST:
5035 /* Pull any EA list from the data portion. */
5038 if (total_data < 4) {
5040 req, NT_STATUS_INVALID_PARAMETER);
5043 ea_size = IVAL(pdata,0);
5045 if (total_data > 0 && ea_size != total_data) {
5046 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5047 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5049 req, NT_STATUS_INVALID_PARAMETER);
5053 if (!lp_ea_support(SNUM(conn))) {
5054 reply_doserror(req, ERRDOS,
5055 ERReasnotsupported);
5059 /* Pull out the list of names. */
5060 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5063 req, NT_STATUS_INVALID_PARAMETER);
5069 case SMB_QUERY_POSIX_LOCK:
5071 if (fsp == NULL || fsp->fh->fd == -1) {
5072 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5076 if (total_data != POSIX_LOCK_DATA_SIZE) {
5078 req, NT_STATUS_INVALID_PARAMETER);
5082 /* Copy the lock range data. */
5083 lock_data = (char *)TALLOC_MEMDUP(
5084 req, pdata, total_data);
5086 reply_nterror(req, NT_STATUS_NO_MEMORY);
5089 lock_data_count = total_data;
5095 *pparams = (char *)SMB_REALLOC(*pparams,2);
5096 if (*pparams == NULL) {
5097 reply_nterror(req, NT_STATUS_NO_MEMORY);
5104 * draft-leach-cifs-v1-spec-02.txt
5105 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5108 * The requested information is placed in the Data portion of the
5109 * transaction response. For the information levels greater than 0x100,
5110 * the transaction response has 1 parameter word which should be
5111 * ignored by the client.
5113 * However Windows only follows this rule for the IS_NAME_VALID call.
5115 switch (info_level) {
5116 case SMB_INFO_IS_NAME_VALID:
5121 if ((info_level & 0xFF00) == 0xFF00) {
5123 * We use levels that start with 0xFF00
5124 * internally to represent SMB2 specific levels
5126 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5130 status = smbd_do_qfilepathinfo(conn, req, info_level,
5132 delete_pending, write_time_ts,
5133 ms_dfs_link, ea_list,
5134 lock_data_count, lock_data,
5135 req->flags2, max_data_bytes,
5136 ppdata, &data_size);
5137 if (!NT_STATUS_IS_OK(status)) {
5138 reply_nterror(req, status);
5142 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5148 /****************************************************************************
5149 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5151 ****************************************************************************/
5153 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5154 connection_struct *conn,
5155 const struct smb_filename *smb_fname_old,
5156 const struct smb_filename *smb_fname_new)
5158 NTSTATUS status = NT_STATUS_OK;
5160 /* source must already exist. */
5161 if (!VALID_STAT(smb_fname_old->st)) {
5162 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5165 /* Disallow if newname already exists. */
5166 if (VALID_STAT(smb_fname_new->st)) {
5167 return NT_STATUS_OBJECT_NAME_COLLISION;
5170 /* No links from a directory. */
5171 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5172 return NT_STATUS_FILE_IS_A_DIRECTORY;
5175 /* Setting a hardlink to/from a stream isn't currently supported. */
5176 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5177 is_ntfs_stream_smb_fname(smb_fname_new)) {
5178 return NT_STATUS_INVALID_PARAMETER;
5181 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5182 smb_fname_old->base_name, smb_fname_new->base_name));
5184 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5185 smb_fname_new->base_name) != 0) {
5186 status = map_nt_error_from_unix(errno);
5187 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5188 nt_errstr(status), smb_fname_old->base_name,
5189 smb_fname_new->base_name));
5194 /****************************************************************************
5195 Deal with setting the time from any of the setfilepathinfo functions.
5196 ****************************************************************************/
5198 NTSTATUS smb_set_file_time(connection_struct *conn,
5200 const struct smb_filename *smb_fname,
5201 struct smb_file_time *ft,
5202 bool setting_write_time)
5204 struct smb_filename *smb_fname_base = NULL;
5206 FILE_NOTIFY_CHANGE_LAST_ACCESS
5207 |FILE_NOTIFY_CHANGE_LAST_WRITE;
5210 if (!VALID_STAT(smb_fname->st)) {
5211 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5214 /* get some defaults (no modifications) if any info is zero or -1. */
5215 if (null_timespec(ft->atime)) {
5216 ft->atime= smb_fname->st.st_ex_atime;
5217 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5220 if (null_timespec(ft->mtime)) {
5221 ft->mtime = smb_fname->st.st_ex_mtime;
5222 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5225 if (!setting_write_time) {
5226 /* ft->mtime comes from change time, not write time. */
5227 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5230 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5231 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5232 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5233 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5234 if (!null_timespec(ft->create_time)) {
5235 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5236 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5240 * Try and set the times of this file if
5241 * they are different from the current values.
5245 struct timespec mts = smb_fname->st.st_ex_mtime;
5246 struct timespec ats = smb_fname->st.st_ex_atime;
5247 if ((timespec_compare(&ft->atime, &ats) == 0) &&
5248 (timespec_compare(&ft->mtime, &mts) == 0)) {
5249 return NT_STATUS_OK;
5253 if (setting_write_time) {
5255 * This was a Windows setfileinfo on an open file.
5256 * NT does this a lot. We also need to
5257 * set the time here, as it can be read by
5258 * FindFirst/FindNext and with the patch for bug #2045
5259 * in smbd/fileio.c it ensures that this timestamp is
5260 * kept sticky even after a write. We save the request
5261 * away and will set it on file close and after a write. JRA.
5264 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5265 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5268 if (fsp->base_fsp) {
5269 set_sticky_write_time_fsp(fsp->base_fsp,
5272 set_sticky_write_time_fsp(fsp, ft->mtime);
5275 set_sticky_write_time_path(
5276 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5281 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5283 /* Always call ntimes on the base, even if a stream was passed in. */
5284 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5285 NULL, &smb_fname->st,
5287 if (!NT_STATUS_IS_OK(status)) {
5291 if(file_ntimes(conn, smb_fname_base, ft)!=0) {
5292 TALLOC_FREE(smb_fname_base);
5293 return map_nt_error_from_unix(errno);
5295 TALLOC_FREE(smb_fname_base);
5297 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5298 smb_fname->base_name);
5299 return NT_STATUS_OK;
5302 /****************************************************************************
5303 Deal with setting the dosmode from any of the setfilepathinfo functions.
5304 ****************************************************************************/
5306 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5307 const struct smb_filename *smb_fname,
5310 struct smb_filename *smb_fname_base = NULL;
5313 if (!VALID_STAT(smb_fname->st)) {
5314 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5317 /* Always operate on the base_name, even if a stream was passed in. */
5318 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5319 NULL, &smb_fname->st,
5321 if (!NT_STATUS_IS_OK(status)) {
5326 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5333 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5335 /* check the mode isn't different, before changing it */
5336 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5337 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5338 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5339 (unsigned int)dosmode));
5341 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5343 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5345 smb_fname_str_dbg(smb_fname_base),
5347 status = map_nt_error_from_unix(errno);
5351 status = NT_STATUS_OK;
5353 TALLOC_FREE(smb_fname_base);
5357 /****************************************************************************
5358 Deal with setting the size from any of the setfilepathinfo functions.
5359 ****************************************************************************/
5361 static NTSTATUS smb_set_file_size(connection_struct *conn,
5362 struct smb_request *req,
5364 const struct smb_filename *smb_fname,
5365 const SMB_STRUCT_STAT *psbuf,
5368 NTSTATUS status = NT_STATUS_OK;
5369 struct smb_filename *smb_fname_tmp = NULL;
5370 files_struct *new_fsp = NULL;
5372 if (!VALID_STAT(*psbuf)) {
5373 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5376 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5378 if (size == get_file_size_stat(psbuf)) {
5379 return NT_STATUS_OK;
5382 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5383 smb_fname_str_dbg(smb_fname), (double)size));
5385 if (fsp && fsp->fh->fd != -1) {
5386 /* Handle based call. */
5387 if (vfs_set_filelen(fsp, size) == -1) {
5388 return map_nt_error_from_unix(errno);
5390 trigger_write_time_update_immediate(fsp);
5391 return NT_STATUS_OK;
5394 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5395 if (!NT_STATUS_IS_OK(status)) {
5399 smb_fname_tmp->st = *psbuf;
5401 status = SMB_VFS_CREATE_FILE(
5404 0, /* root_dir_fid */
5405 smb_fname_tmp, /* fname */
5406 FILE_WRITE_ATTRIBUTES, /* access_mask */
5407 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5409 FILE_OPEN, /* create_disposition*/
5410 0, /* create_options */
5411 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5412 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5413 0, /* allocation_size */
5416 &new_fsp, /* result */
5419 TALLOC_FREE(smb_fname_tmp);
5421 if (!NT_STATUS_IS_OK(status)) {
5422 /* NB. We check for open_was_deferred in the caller. */
5426 if (vfs_set_filelen(new_fsp, size) == -1) {
5427 status = map_nt_error_from_unix(errno);
5428 close_file(req, new_fsp,NORMAL_CLOSE);
5432 trigger_write_time_update_immediate(new_fsp);
5433 close_file(req, new_fsp,NORMAL_CLOSE);
5434 return NT_STATUS_OK;
5437 /****************************************************************************
5438 Deal with SMB_INFO_SET_EA.
5439 ****************************************************************************/
5441 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5445 const struct smb_filename *smb_fname)
5447 struct ea_list *ea_list = NULL;
5448 TALLOC_CTX *ctx = NULL;
5449 NTSTATUS status = NT_STATUS_OK;
5451 if (total_data < 10) {
5453 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5454 length. They seem to have no effect. Bug #3212. JRA */
5456 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5457 /* We're done. We only get EA info in this call. */
5458 return NT_STATUS_OK;
5461 return NT_STATUS_INVALID_PARAMETER;
5464 if (IVAL(pdata,0) > total_data) {
5465 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5466 IVAL(pdata,0), (unsigned int)total_data));
5467 return NT_STATUS_INVALID_PARAMETER;
5471 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5473 return NT_STATUS_INVALID_PARAMETER;
5475 status = set_ea(conn, fsp, smb_fname, ea_list);
5480 /****************************************************************************
5481 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5482 ****************************************************************************/
5484 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5488 const struct smb_filename *smb_fname)
5490 NTSTATUS status = NT_STATUS_OK;
5491 bool delete_on_close;
5494 if (total_data < 1) {
5495 return NT_STATUS_INVALID_PARAMETER;
5499 return NT_STATUS_INVALID_HANDLE;
5502 delete_on_close = (CVAL(pdata,0) ? True : False);
5503 dosmode = dos_mode(conn, smb_fname);
5505 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5506 "delete_on_close = %u\n",
5507 smb_fname_str_dbg(smb_fname),
5508 (unsigned int)dosmode,
5509 (unsigned int)delete_on_close ));
5511 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5513 if (!NT_STATUS_IS_OK(status)) {
5517 /* The set is across all open files on this dev/inode pair. */
5518 if (!set_delete_on_close(fsp, delete_on_close,
5519 &conn->server_info->utok)) {
5520 return NT_STATUS_ACCESS_DENIED;
5522 return NT_STATUS_OK;
5525 /****************************************************************************
5526 Deal with SMB_FILE_POSITION_INFORMATION.
5527 ****************************************************************************/
5529 static NTSTATUS smb_file_position_information(connection_struct *conn,
5534 uint64_t position_information;
5536 if (total_data < 8) {
5537 return NT_STATUS_INVALID_PARAMETER;
5541 /* Ignore on pathname based set. */
5542 return NT_STATUS_OK;
5545 position_information = (uint64_t)IVAL(pdata,0);
5546 #ifdef LARGE_SMB_OFF_T
5547 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5548 #else /* LARGE_SMB_OFF_T */
5549 if (IVAL(pdata,4) != 0) {
5550 /* more than 32 bits? */
5551 return NT_STATUS_INVALID_PARAMETER;
5553 #endif /* LARGE_SMB_OFF_T */
5555 DEBUG(10,("smb_file_position_information: Set file position "
5556 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5557 (double)position_information));
5558 fsp->fh->position_information = position_information;
5559 return NT_STATUS_OK;
5562 /****************************************************************************
5563 Deal with SMB_FILE_MODE_INFORMATION.
5564 ****************************************************************************/
5566 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5572 if (total_data < 4) {
5573 return NT_STATUS_INVALID_PARAMETER;
5575 mode = IVAL(pdata,0);
5576 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5577 return NT_STATUS_INVALID_PARAMETER;
5579 return NT_STATUS_OK;
5582 /****************************************************************************
5583 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5584 ****************************************************************************/
5586 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5587 struct smb_request *req,
5590 const struct smb_filename *smb_fname)
5592 char *link_target = NULL;
5593 const char *newname = smb_fname->base_name;
5594 NTSTATUS status = NT_STATUS_OK;
5595 TALLOC_CTX *ctx = talloc_tos();
5597 /* Set a symbolic link. */
5598 /* Don't allow this if follow links is false. */
5600 if (total_data == 0) {
5601 return NT_STATUS_INVALID_PARAMETER;
5604 if (!lp_symlinks(SNUM(conn))) {
5605 return NT_STATUS_ACCESS_DENIED;
5608 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5609 total_data, STR_TERMINATE);
5612 return NT_STATUS_INVALID_PARAMETER;
5615 /* !widelinks forces the target path to be within the share. */
5616 /* This means we can interpret the target as a pathname. */
5617 if (!lp_widelinks(SNUM(conn))) {
5618 char *rel_name = NULL;
5619 char *last_dirp = NULL;
5621 if (*link_target == '/') {
5622 /* No absolute paths allowed. */
5623 return NT_STATUS_ACCESS_DENIED;
5625 rel_name = talloc_strdup(ctx,newname);
5627 return NT_STATUS_NO_MEMORY;
5629 last_dirp = strrchr_m(rel_name, '/');
5631 last_dirp[1] = '\0';
5633 rel_name = talloc_strdup(ctx,"./");
5635 return NT_STATUS_NO_MEMORY;
5638 rel_name = talloc_asprintf_append(rel_name,
5642 return NT_STATUS_NO_MEMORY;
5645 status = check_name(conn, rel_name);
5646 if (!NT_STATUS_IS_OK(status)) {
5651 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5652 newname, link_target ));
5654 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5655 return map_nt_error_from_unix(errno);
5658 return NT_STATUS_OK;
5661 /****************************************************************************
5662 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5663 ****************************************************************************/
5665 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5666 struct smb_request *req,
5667 const char *pdata, int total_data,
5668 const struct smb_filename *smb_fname_new)
5670 char *oldname = NULL;
5671 struct smb_filename *smb_fname_old = NULL;
5672 TALLOC_CTX *ctx = talloc_tos();
5673 NTSTATUS status = NT_STATUS_OK;
5675 /* Set a hard link. */
5676 if (total_data == 0) {
5677 return NT_STATUS_INVALID_PARAMETER;
5680 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5681 total_data, STR_TERMINATE, &status);
5682 if (!NT_STATUS_IS_OK(status)) {
5686 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5687 smb_fname_str_dbg(smb_fname_new), oldname));
5689 status = filename_convert(ctx,
5691 req->flags2 & FLAGS2_DFS_PATHNAMES,
5696 if (!NT_STATUS_IS_OK(status)) {
5700 return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
5703 /****************************************************************************
5704 Deal with SMB_FILE_RENAME_INFORMATION.
5705 ****************************************************************************/
5707 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5708 struct smb_request *req,
5712 struct smb_filename *smb_fname_src)
5717 char *newname = NULL;
5718 struct smb_filename *smb_fname_dst = NULL;
5719 bool dest_has_wcard = False;
5720 NTSTATUS status = NT_STATUS_OK;
5722 TALLOC_CTX *ctx = talloc_tos();
5724 if (total_data < 13) {
5725 return NT_STATUS_INVALID_PARAMETER;
5728 overwrite = (CVAL(pdata,0) ? True : False);
5729 root_fid = IVAL(pdata,4);
5730 len = IVAL(pdata,8);
5732 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5733 return NT_STATUS_INVALID_PARAMETER;
5736 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5739 if (!NT_STATUS_IS_OK(status)) {
5743 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5746 status = resolve_dfspath_wcard(ctx, conn,
5747 req->flags2 & FLAGS2_DFS_PATHNAMES,
5751 if (!NT_STATUS_IS_OK(status)) {
5755 /* Check the new name has no '/' characters. */
5756 if (strchr_m(newname, '/')) {
5757 return NT_STATUS_NOT_SUPPORTED;
5760 if (fsp && fsp->base_fsp) {
5761 /* newname must be a stream name. */
5762 if (newname[0] != ':') {
5763 return NT_STATUS_NOT_SUPPORTED;
5766 /* Create an smb_fname to call rename_internals_fsp() with. */
5767 status = create_synthetic_smb_fname(talloc_tos(),
5768 fsp->base_fsp->fsp_name->base_name, newname, NULL,
5770 if (!NT_STATUS_IS_OK(status)) {
5775 * Set the original last component, since
5776 * rename_internals_fsp() requires it.
5778 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
5780 if (smb_fname_dst->original_lcomp == NULL) {
5781 status = NT_STATUS_NO_MEMORY;
5787 * Build up an smb_fname_dst based on the filename passed in.
5788 * We basically just strip off the last component, and put on
5789 * the newname instead.
5791 char *base_name = NULL;
5793 /* newname must *not* be a stream name. */
5794 if (newname[0] == ':') {
5795 return NT_STATUS_NOT_SUPPORTED;
5799 * Strip off the last component (filename) of the path passed
5802 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
5804 return NT_STATUS_NO_MEMORY;
5806 p = strrchr_m(base_name, '/');
5810 base_name = talloc_strdup(ctx, "./");
5812 return NT_STATUS_NO_MEMORY;
5815 /* Append the new name. */
5816 base_name = talloc_asprintf_append(base_name,
5820 return NT_STATUS_NO_MEMORY;
5823 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
5826 UCF_ALLOW_WCARD_LCOMP : 0)));
5828 /* If an error we expect this to be
5829 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5831 if (!NT_STATUS_IS_OK(status)) {
5832 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5836 /* Create an smb_fname to call rename_internals_fsp() */
5837 status = create_synthetic_smb_fname(ctx,
5841 if (!NT_STATUS_IS_OK(status)) {
5848 DEBUG(10,("smb_file_rename_information: "
5849 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5850 fsp->fnum, fsp_str_dbg(fsp),
5851 smb_fname_str_dbg(smb_fname_dst)));
5852 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
5855 DEBUG(10,("smb_file_rename_information: "
5856 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5857 smb_fname_str_dbg(smb_fname_src),
5858 smb_fname_str_dbg(smb_fname_dst)));
5859 status = rename_internals(ctx, conn, req, smb_fname_src,
5860 smb_fname_dst, 0, overwrite, false,
5862 FILE_WRITE_ATTRIBUTES);
5865 TALLOC_FREE(smb_fname_dst);
5869 /****************************************************************************
5870 Deal with SMB_SET_POSIX_ACL.
5871 ****************************************************************************/
5873 #if defined(HAVE_POSIX_ACLS)
5874 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5878 const struct smb_filename *smb_fname)
5880 uint16 posix_acl_version;
5881 uint16 num_file_acls;
5882 uint16 num_def_acls;
5883 bool valid_file_acls = True;
5884 bool valid_def_acls = True;
5886 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5887 return NT_STATUS_INVALID_PARAMETER;
5889 posix_acl_version = SVAL(pdata,0);
5890 num_file_acls = SVAL(pdata,2);
5891 num_def_acls = SVAL(pdata,4);
5893 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5894 valid_file_acls = False;
5898 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5899 valid_def_acls = False;
5903 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5904 return NT_STATUS_INVALID_PARAMETER;
5907 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5908 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5909 return NT_STATUS_INVALID_PARAMETER;
5912 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5913 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
5914 (unsigned int)num_file_acls,
5915 (unsigned int)num_def_acls));
5917 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
5918 smb_fname->base_name, num_file_acls,
5919 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5920 return map_nt_error_from_unix(errno);
5923 if (valid_def_acls && !set_unix_posix_default_acl(conn,
5924 smb_fname->base_name, &smb_fname->st, num_def_acls,
5925 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5926 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5927 return map_nt_error_from_unix(errno);
5929 return NT_STATUS_OK;
5933 /****************************************************************************
5934 Deal with SMB_SET_POSIX_LOCK.
5935 ****************************************************************************/
5937 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5938 struct smb_request *req,
5946 bool blocking_lock = False;
5947 enum brl_type lock_type;
5949 NTSTATUS status = NT_STATUS_OK;
5951 if (fsp == NULL || fsp->fh->fd == -1) {
5952 return NT_STATUS_INVALID_HANDLE;
5955 if (total_data != POSIX_LOCK_DATA_SIZE) {
5956 return NT_STATUS_INVALID_PARAMETER;
5959 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5960 case POSIX_LOCK_TYPE_READ:
5961 lock_type = READ_LOCK;
5963 case POSIX_LOCK_TYPE_WRITE:
5964 /* Return the right POSIX-mappable error code for files opened read-only. */
5965 if (!fsp->can_write) {
5966 return NT_STATUS_INVALID_HANDLE;
5968 lock_type = WRITE_LOCK;
5970 case POSIX_LOCK_TYPE_UNLOCK:
5971 lock_type = UNLOCK_LOCK;
5974 return NT_STATUS_INVALID_PARAMETER;
5977 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5978 blocking_lock = False;
5979 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5980 blocking_lock = True;
5982 return NT_STATUS_INVALID_PARAMETER;
5985 if (!lp_blocking_locks(SNUM(conn))) {
5986 blocking_lock = False;
5989 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5990 #if defined(HAVE_LONGLONG)
5991 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5992 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5993 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5994 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5995 #else /* HAVE_LONGLONG */
5996 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5997 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5998 #endif /* HAVE_LONGLONG */
6000 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6001 "lock_pid = %u, count = %.0f, offset = %.0f\n",
6003 (unsigned int)lock_type,
6004 (unsigned int)lock_pid,
6008 if (lock_type == UNLOCK_LOCK) {
6009 status = do_unlock(smbd_messaging_context(),
6016 uint32 block_smbpid;
6018 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
6030 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6032 * A blocking lock was requested. Package up
6033 * this smb into a queued request and push it
6034 * onto the blocking lock queue.
6036 if(push_blocking_lock_request(br_lck,
6039 -1, /* infinite timeout. */
6047 TALLOC_FREE(br_lck);
6051 TALLOC_FREE(br_lck);
6057 /****************************************************************************
6058 Deal with SMB_INFO_STANDARD.
6059 ****************************************************************************/
6061 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6065 const struct smb_filename *smb_fname)
6067 struct smb_file_time ft;
6070 if (total_data < 12) {
6071 return NT_STATUS_INVALID_PARAMETER;
6075 ft.create_time = interpret_long_date(pdata);
6078 ft.atime = interpret_long_date(pdata + 8);
6081 ft.mtime = interpret_long_date(pdata + 16);
6083 DEBUG(10,("smb_set_info_standard: file %s\n",
6084 smb_fname_str_dbg(smb_fname)));
6086 return smb_set_file_time(conn, fsp, smb_fname, &ft, true);
6089 /****************************************************************************
6090 Deal with SMB_SET_FILE_BASIC_INFO.
6091 ****************************************************************************/
6093 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6097 const struct smb_filename *smb_fname)
6099 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6100 struct timespec write_time;
6101 struct timespec changed_time;
6102 struct smb_file_time ft;
6104 NTSTATUS status = NT_STATUS_OK;
6105 bool setting_write_time = true;
6109 if (total_data < 36) {
6110 return NT_STATUS_INVALID_PARAMETER;
6113 /* Set the attributes */
6114 dosmode = IVAL(pdata,32);
6115 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6116 if (!NT_STATUS_IS_OK(status)) {
6121 ft.atime = interpret_long_date(pdata+8);
6123 write_time = interpret_long_date(pdata+16);
6124 changed_time = interpret_long_date(pdata+24);
6127 ft.mtime = timespec_min(&write_time, &changed_time);
6130 ft.create_time = interpret_long_date(pdata);
6132 if ((timespec_compare(&write_time, &ft.mtime) == 1) &&
6133 !null_timespec(write_time)) {
6134 ft.mtime = write_time;
6137 /* Prefer a defined time to an undefined one. */
6138 if (null_timespec(ft.mtime)) {
6139 if (null_timespec(write_time)) {
6140 ft.mtime = changed_time;
6141 setting_write_time = false;
6143 ft.mtime = write_time;
6147 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6148 smb_fname_str_dbg(smb_fname)));
6150 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6151 setting_write_time);
6154 /****************************************************************************
6155 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6156 ****************************************************************************/
6158 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6159 struct smb_request *req,
6163 struct smb_filename *smb_fname)
6165 uint64_t allocation_size = 0;
6166 NTSTATUS status = NT_STATUS_OK;
6167 files_struct *new_fsp = NULL;
6169 if (!VALID_STAT(smb_fname->st)) {
6170 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6173 if (total_data < 8) {
6174 return NT_STATUS_INVALID_PARAMETER;
6177 allocation_size = (uint64_t)IVAL(pdata,0);
6178 #ifdef LARGE_SMB_OFF_T
6179 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6180 #else /* LARGE_SMB_OFF_T */
6181 if (IVAL(pdata,4) != 0) {
6182 /* more than 32 bits? */
6183 return NT_STATUS_INVALID_PARAMETER;
6185 #endif /* LARGE_SMB_OFF_T */
6187 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6188 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6189 (double)allocation_size));
6191 if (allocation_size) {
6192 allocation_size = smb_roundup(conn, allocation_size);
6195 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6196 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6197 (double)allocation_size));
6199 if (fsp && fsp->fh->fd != -1) {
6200 /* Open file handle. */
6201 /* Only change if needed. */
6202 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6203 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6204 return map_nt_error_from_unix(errno);
6207 /* But always update the time. */
6209 * This is equivalent to a write. Ensure it's seen immediately
6210 * if there are no pending writes.
6212 trigger_write_time_update_immediate(fsp);
6213 return NT_STATUS_OK;
6216 /* Pathname or stat or directory file. */
6217 status = SMB_VFS_CREATE_FILE(
6220 0, /* root_dir_fid */
6221 smb_fname, /* fname */
6222 FILE_WRITE_DATA, /* access_mask */
6223 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6225 FILE_OPEN, /* create_disposition*/
6226 0, /* create_options */
6227 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6228 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6229 0, /* allocation_size */
6232 &new_fsp, /* result */
6235 if (!NT_STATUS_IS_OK(status)) {
6236 /* NB. We check for open_was_deferred in the caller. */
6240 /* Only change if needed. */
6241 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6242 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6243 status = map_nt_error_from_unix(errno);
6244 close_file(req, new_fsp, NORMAL_CLOSE);
6249 /* Changing the allocation size should set the last mod time. */
6251 * This is equivalent to a write. Ensure it's seen immediately
6252 * if there are no pending writes.
6254 trigger_write_time_update_immediate(new_fsp);
6256 close_file(req, new_fsp, NORMAL_CLOSE);
6257 return NT_STATUS_OK;
6260 /****************************************************************************
6261 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6262 ****************************************************************************/
6264 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6265 struct smb_request *req,
6269 const struct smb_filename *smb_fname)
6273 if (total_data < 8) {
6274 return NT_STATUS_INVALID_PARAMETER;
6277 size = IVAL(pdata,0);
6278 #ifdef LARGE_SMB_OFF_T
6279 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6280 #else /* LARGE_SMB_OFF_T */
6281 if (IVAL(pdata,4) != 0) {
6282 /* more than 32 bits? */
6283 return NT_STATUS_INVALID_PARAMETER;
6285 #endif /* LARGE_SMB_OFF_T */
6286 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6287 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6290 return smb_set_file_size(conn, req,
6297 /****************************************************************************
6298 Allow a UNIX info mknod.
6299 ****************************************************************************/
6301 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6304 const struct smb_filename *smb_fname)
6306 uint32 file_type = IVAL(pdata,56);
6307 #if defined(HAVE_MAKEDEV)
6308 uint32 dev_major = IVAL(pdata,60);
6309 uint32 dev_minor = IVAL(pdata,68);
6311 SMB_DEV_T dev = (SMB_DEV_T)0;
6312 uint32 raw_unixmode = IVAL(pdata,84);
6316 if (total_data < 100) {
6317 return NT_STATUS_INVALID_PARAMETER;
6320 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6321 PERM_NEW_FILE, &unixmode);
6322 if (!NT_STATUS_IS_OK(status)) {
6326 #if defined(HAVE_MAKEDEV)
6327 dev = makedev(dev_major, dev_minor);
6330 switch (file_type) {
6331 #if defined(S_IFIFO)
6332 case UNIX_TYPE_FIFO:
6333 unixmode |= S_IFIFO;
6336 #if defined(S_IFSOCK)
6337 case UNIX_TYPE_SOCKET:
6338 unixmode |= S_IFSOCK;
6341 #if defined(S_IFCHR)
6342 case UNIX_TYPE_CHARDEV:
6343 unixmode |= S_IFCHR;
6346 #if defined(S_IFBLK)
6347 case UNIX_TYPE_BLKDEV:
6348 unixmode |= S_IFBLK;
6352 return NT_STATUS_INVALID_PARAMETER;
6355 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6356 "%.0f mode 0%o for file %s\n", (double)dev,
6357 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6359 /* Ok - do the mknod. */
6360 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6361 return map_nt_error_from_unix(errno);
6364 /* If any of the other "set" calls fail we
6365 * don't want to end up with a half-constructed mknod.
6368 if (lp_inherit_perms(SNUM(conn))) {
6370 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6372 return NT_STATUS_NO_MEMORY;
6374 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6376 TALLOC_FREE(parent);
6379 return NT_STATUS_OK;
6382 /****************************************************************************
6383 Deal with SMB_SET_FILE_UNIX_BASIC.
6384 ****************************************************************************/
6386 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6387 struct smb_request *req,
6391 const struct smb_filename *smb_fname)
6393 struct smb_file_time ft;
6394 uint32 raw_unixmode;
6397 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6398 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6399 NTSTATUS status = NT_STATUS_OK;
6400 bool delete_on_fail = False;
6401 enum perm_type ptype;
6402 files_struct *all_fsps = NULL;
6403 bool modify_mtime = true;
6405 SMB_STRUCT_STAT sbuf;
6409 if (total_data < 100) {
6410 return NT_STATUS_INVALID_PARAMETER;
6413 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6414 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6415 size=IVAL(pdata,0); /* first 8 Bytes are size */
6416 #ifdef LARGE_SMB_OFF_T
6417 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6418 #else /* LARGE_SMB_OFF_T */
6419 if (IVAL(pdata,4) != 0) {
6420 /* more than 32 bits? */
6421 return NT_STATUS_INVALID_PARAMETER;
6423 #endif /* LARGE_SMB_OFF_T */
6426 ft.atime = interpret_long_date(pdata+24); /* access_time */
6427 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6428 set_owner = (uid_t)IVAL(pdata,40);
6429 set_grp = (gid_t)IVAL(pdata,48);
6430 raw_unixmode = IVAL(pdata,84);
6432 if (VALID_STAT(smb_fname->st)) {
6433 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6434 ptype = PERM_EXISTING_DIR;
6436 ptype = PERM_EXISTING_FILE;
6439 ptype = PERM_NEW_FILE;
6442 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6444 if (!NT_STATUS_IS_OK(status)) {
6448 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6449 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6450 smb_fname_str_dbg(smb_fname), (double)size,
6451 (unsigned int)set_owner, (unsigned int)set_grp,
6452 (int)raw_unixmode));
6454 sbuf = smb_fname->st;
6456 if (!VALID_STAT(sbuf)) {
6457 struct smb_filename *smb_fname_tmp = NULL;
6459 * The only valid use of this is to create character and block
6460 * devices, and named pipes. This is deprecated (IMHO) and
6461 * a new info level should be used for mknod. JRA.
6464 status = smb_unix_mknod(conn,
6468 if (!NT_STATUS_IS_OK(status)) {
6472 status = copy_smb_filename(talloc_tos(), smb_fname,
6474 if (!NT_STATUS_IS_OK(status)) {
6478 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6479 status = map_nt_error_from_unix(errno);
6480 TALLOC_FREE(smb_fname_tmp);
6481 SMB_VFS_UNLINK(conn, smb_fname);
6485 sbuf = smb_fname_tmp->st;
6486 TALLOC_FREE(smb_fname_tmp);
6488 /* Ensure we don't try and change anything else. */
6489 raw_unixmode = SMB_MODE_NO_CHANGE;
6490 size = get_file_size_stat(&sbuf);
6491 ft.atime = sbuf.st_ex_atime;
6492 ft.mtime = sbuf.st_ex_mtime;
6494 * We continue here as we might want to change the
6497 delete_on_fail = True;
6501 /* Horrible backwards compatibility hack as an old server bug
6502 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6506 size = get_file_size_stat(&sbuf);
6511 * Deal with the UNIX specific mode set.
6514 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6515 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6516 "setting mode 0%o for file %s\n",
6517 (unsigned int)unixmode,
6518 smb_fname_str_dbg(smb_fname)));
6519 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6520 return map_nt_error_from_unix(errno);
6525 * Deal with the UNIX specific uid set.
6528 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6529 (sbuf.st_ex_uid != set_owner)) {
6532 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6533 "changing owner %u for path %s\n",
6534 (unsigned int)set_owner,
6535 smb_fname_str_dbg(smb_fname)));
6537 if (S_ISLNK(sbuf.st_ex_mode)) {
6538 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6539 set_owner, (gid_t)-1);
6541 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6542 set_owner, (gid_t)-1);
6546 status = map_nt_error_from_unix(errno);
6547 if (delete_on_fail) {
6548 SMB_VFS_UNLINK(conn, smb_fname);
6555 * Deal with the UNIX specific gid set.
6558 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6559 (sbuf.st_ex_gid != set_grp)) {
6560 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6561 "changing group %u for file %s\n",
6562 (unsigned int)set_owner,
6563 smb_fname_str_dbg(smb_fname)));
6564 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6566 status = map_nt_error_from_unix(errno);
6567 if (delete_on_fail) {
6568 SMB_VFS_UNLINK(conn, smb_fname);
6574 /* Deal with any size changes. */
6576 status = smb_set_file_size(conn, req,
6581 if (!NT_STATUS_IS_OK(status)) {
6585 /* Deal with any time changes. */
6586 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6587 /* No change, don't cancel anything. */
6591 id = vfs_file_id_from_sbuf(conn, &sbuf);
6592 for(all_fsps = file_find_di_first(id); all_fsps;
6593 all_fsps = file_find_di_next(all_fsps)) {
6595 * We're setting the time explicitly for UNIX.
6596 * Cancel any pending changes over all handles.
6598 all_fsps->update_write_time_on_close = false;
6599 TALLOC_FREE(all_fsps->update_write_time_event);
6603 * Override the "setting_write_time"
6604 * parameter here as it almost does what
6605 * we need. Just remember if we modified
6606 * mtime and send the notify ourselves.
6608 if (null_timespec(ft.mtime)) {
6609 modify_mtime = false;
6612 status = smb_set_file_time(conn,
6618 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6619 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6624 /****************************************************************************
6625 Deal with SMB_SET_FILE_UNIX_INFO2.
6626 ****************************************************************************/
6628 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6629 struct smb_request *req,
6633 const struct smb_filename *smb_fname)
6639 if (total_data < 116) {
6640 return NT_STATUS_INVALID_PARAMETER;
6643 /* Start by setting all the fields that are common between UNIX_BASIC
6646 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6648 if (!NT_STATUS_IS_OK(status)) {
6652 smb_fflags = IVAL(pdata, 108);
6653 smb_fmask = IVAL(pdata, 112);
6655 /* NB: We should only attempt to alter the file flags if the client
6656 * sends a non-zero mask.
6658 if (smb_fmask != 0) {
6659 int stat_fflags = 0;
6661 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6662 smb_fmask, &stat_fflags)) {
6663 /* Client asked to alter a flag we don't understand. */
6664 return NT_STATUS_INVALID_PARAMETER;
6667 if (fsp && fsp->fh->fd != -1) {
6668 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6669 return NT_STATUS_NOT_SUPPORTED;
6671 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
6672 stat_fflags) != 0) {
6673 return map_nt_error_from_unix(errno);
6678 /* XXX: need to add support for changing the create_time here. You
6679 * can do this for paths on Darwin with setattrlist(2). The right way
6680 * to hook this up is probably by extending the VFS utimes interface.
6683 return NT_STATUS_OK;
6686 /****************************************************************************
6687 Create a directory with POSIX semantics.
6688 ****************************************************************************/
6690 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6691 struct smb_request *req,
6694 struct smb_filename *smb_fname,
6695 int *pdata_return_size)
6697 NTSTATUS status = NT_STATUS_OK;
6698 uint32 raw_unixmode = 0;
6699 uint32 mod_unixmode = 0;
6700 mode_t unixmode = (mode_t)0;
6701 files_struct *fsp = NULL;
6702 uint16 info_level_return = 0;
6704 char *pdata = *ppdata;
6706 if (total_data < 18) {
6707 return NT_STATUS_INVALID_PARAMETER;
6710 raw_unixmode = IVAL(pdata,8);
6711 /* Next 4 bytes are not yet defined. */
6713 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6714 PERM_NEW_DIR, &unixmode);
6715 if (!NT_STATUS_IS_OK(status)) {
6719 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6721 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6722 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
6724 status = SMB_VFS_CREATE_FILE(
6727 0, /* root_dir_fid */
6728 smb_fname, /* fname */
6729 FILE_READ_ATTRIBUTES, /* access_mask */
6730 FILE_SHARE_NONE, /* share_access */
6731 FILE_CREATE, /* create_disposition*/
6732 FILE_DIRECTORY_FILE, /* create_options */
6733 mod_unixmode, /* file_attributes */
6734 0, /* oplock_request */
6735 0, /* allocation_size */
6741 if (NT_STATUS_IS_OK(status)) {
6742 close_file(req, fsp, NORMAL_CLOSE);
6745 info_level_return = SVAL(pdata,16);
6747 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6748 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6749 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6750 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6752 *pdata_return_size = 12;
6755 /* Realloc the data size */
6756 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6757 if (*ppdata == NULL) {
6758 *pdata_return_size = 0;
6759 return NT_STATUS_NO_MEMORY;
6763 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6764 SSVAL(pdata,2,0); /* No fnum. */
6765 SIVAL(pdata,4,info); /* Was directory created. */
6767 switch (info_level_return) {
6768 case SMB_QUERY_FILE_UNIX_BASIC:
6769 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6770 SSVAL(pdata,10,0); /* Padding. */
6771 store_file_unix_basic(conn, pdata + 12, fsp,
6774 case SMB_QUERY_FILE_UNIX_INFO2:
6775 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6776 SSVAL(pdata,10,0); /* Padding. */
6777 store_file_unix_basic_info2(conn, pdata + 12, fsp,
6781 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6782 SSVAL(pdata,10,0); /* Padding. */
6789 /****************************************************************************
6790 Open/Create a file with POSIX semantics.
6791 ****************************************************************************/
6793 static NTSTATUS smb_posix_open(connection_struct *conn,
6794 struct smb_request *req,
6797 struct smb_filename *smb_fname,
6798 int *pdata_return_size)
6800 bool extended_oplock_granted = False;
6801 char *pdata = *ppdata;
6803 uint32 wire_open_mode = 0;
6804 uint32 raw_unixmode = 0;
6805 uint32 mod_unixmode = 0;
6806 uint32 create_disp = 0;
6807 uint32 access_mask = 0;
6808 uint32 create_options = 0;
6809 NTSTATUS status = NT_STATUS_OK;
6810 mode_t unixmode = (mode_t)0;
6811 files_struct *fsp = NULL;
6812 int oplock_request = 0;
6814 uint16 info_level_return = 0;
6816 if (total_data < 18) {
6817 return NT_STATUS_INVALID_PARAMETER;
6820 flags = IVAL(pdata,0);
6821 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6822 if (oplock_request) {
6823 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6826 wire_open_mode = IVAL(pdata,4);
6828 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6829 return smb_posix_mkdir(conn, req,
6836 switch (wire_open_mode & SMB_ACCMODE) {
6838 access_mask = FILE_READ_DATA;
6841 access_mask = FILE_WRITE_DATA;
6844 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6847 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6848 (unsigned int)wire_open_mode ));
6849 return NT_STATUS_INVALID_PARAMETER;
6852 wire_open_mode &= ~SMB_ACCMODE;
6854 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6855 create_disp = FILE_CREATE;
6856 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6857 create_disp = FILE_OVERWRITE_IF;
6858 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6859 create_disp = FILE_OPEN_IF;
6860 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6861 create_disp = FILE_OPEN;
6863 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6864 (unsigned int)wire_open_mode ));
6865 return NT_STATUS_INVALID_PARAMETER;
6868 raw_unixmode = IVAL(pdata,8);
6869 /* Next 4 bytes are not yet defined. */
6871 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6872 (VALID_STAT(smb_fname->st) ?
6873 PERM_EXISTING_FILE : PERM_NEW_FILE),
6876 if (!NT_STATUS_IS_OK(status)) {
6880 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6882 if (wire_open_mode & SMB_O_SYNC) {
6883 create_options |= FILE_WRITE_THROUGH;
6885 if (wire_open_mode & SMB_O_APPEND) {
6886 access_mask |= FILE_APPEND_DATA;
6888 if (wire_open_mode & SMB_O_DIRECT) {
6889 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6892 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6893 smb_fname_str_dbg(smb_fname),
6894 (unsigned int)wire_open_mode,
6895 (unsigned int)unixmode ));
6897 status = SMB_VFS_CREATE_FILE(
6900 0, /* root_dir_fid */
6901 smb_fname, /* fname */
6902 access_mask, /* access_mask */
6903 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6905 create_disp, /* create_disposition*/
6906 FILE_NON_DIRECTORY_FILE, /* create_options */
6907 mod_unixmode, /* file_attributes */
6908 oplock_request, /* oplock_request */
6909 0, /* allocation_size */
6915 if (!NT_STATUS_IS_OK(status)) {
6919 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6920 extended_oplock_granted = True;
6923 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6924 extended_oplock_granted = True;
6927 info_level_return = SVAL(pdata,16);
6929 /* Allocate the correct return size. */
6931 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6932 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6933 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6934 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6936 *pdata_return_size = 12;
6939 /* Realloc the data size */
6940 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6941 if (*ppdata == NULL) {
6942 close_file(req, fsp, ERROR_CLOSE);
6943 *pdata_return_size = 0;
6944 return NT_STATUS_NO_MEMORY;
6948 if (extended_oplock_granted) {
6949 if (flags & REQUEST_BATCH_OPLOCK) {
6950 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6952 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6954 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6955 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6957 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6960 SSVAL(pdata,2,fsp->fnum);
6961 SIVAL(pdata,4,info); /* Was file created etc. */
6963 switch (info_level_return) {
6964 case SMB_QUERY_FILE_UNIX_BASIC:
6965 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6966 SSVAL(pdata,10,0); /* padding. */
6967 store_file_unix_basic(conn, pdata + 12, fsp,
6970 case SMB_QUERY_FILE_UNIX_INFO2:
6971 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6972 SSVAL(pdata,10,0); /* padding. */
6973 store_file_unix_basic_info2(conn, pdata + 12, fsp,
6977 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6978 SSVAL(pdata,10,0); /* padding. */
6981 return NT_STATUS_OK;
6984 /****************************************************************************
6985 Delete a file with POSIX semantics.
6986 ****************************************************************************/
6988 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6989 struct smb_request *req,
6992 struct smb_filename *smb_fname)
6994 NTSTATUS status = NT_STATUS_OK;
6995 files_struct *fsp = NULL;
6999 int create_options = 0;
7001 struct share_mode_lock *lck = NULL;
7003 if (total_data < 2) {
7004 return NT_STATUS_INVALID_PARAMETER;
7007 flags = SVAL(pdata,0);
7009 if (!VALID_STAT(smb_fname->st)) {
7010 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7013 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7014 !VALID_STAT_OF_DIR(smb_fname->st)) {
7015 return NT_STATUS_NOT_A_DIRECTORY;
7018 DEBUG(10,("smb_posix_unlink: %s %s\n",
7019 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7020 smb_fname_str_dbg(smb_fname)));
7022 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7023 create_options |= FILE_DIRECTORY_FILE;
7026 status = SMB_VFS_CREATE_FILE(
7029 0, /* root_dir_fid */
7030 smb_fname, /* fname */
7031 DELETE_ACCESS, /* access_mask */
7032 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7034 FILE_OPEN, /* create_disposition*/
7035 create_options, /* create_options */
7036 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7037 0, /* oplock_request */
7038 0, /* allocation_size */
7044 if (!NT_STATUS_IS_OK(status)) {
7049 * Don't lie to client. If we can't really delete due to
7050 * non-POSIX opens return SHARING_VIOLATION.
7053 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7056 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7057 "lock for file %s\n", fsp_str_dbg(fsp)));
7058 close_file(req, fsp, NORMAL_CLOSE);
7059 return NT_STATUS_INVALID_PARAMETER;
7063 * See if others still have the file open. If this is the case, then
7064 * don't delete. If all opens are POSIX delete we can set the delete
7065 * on close disposition.
7067 for (i=0; i<lck->num_share_modes; i++) {
7068 struct share_mode_entry *e = &lck->share_modes[i];
7069 if (is_valid_share_mode_entry(e)) {
7070 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7073 /* Fail with sharing violation. */
7074 close_file(req, fsp, NORMAL_CLOSE);
7076 return NT_STATUS_SHARING_VIOLATION;
7081 * Set the delete on close.
7083 status = smb_set_file_disposition_info(conn,
7089 if (!NT_STATUS_IS_OK(status)) {
7090 close_file(req, fsp, NORMAL_CLOSE);
7095 return close_file(req, fsp, NORMAL_CLOSE);
7098 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7099 struct smb_request *req,
7100 TALLOC_CTX *mem_ctx,
7101 uint16_t info_level,
7103 struct smb_filename *smb_fname,
7104 char **ppdata, int total_data,
7107 char *pdata = *ppdata;
7108 NTSTATUS status = NT_STATUS_OK;
7109 int data_return_size = 0;
7113 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7114 return NT_STATUS_INVALID_LEVEL;
7117 if (!CAN_WRITE(conn)) {
7118 /* Allow POSIX opens. The open path will deny
7119 * any non-readonly opens. */
7120 if (info_level != SMB_POSIX_PATH_OPEN) {
7121 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7125 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7126 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7127 fsp ? fsp->fnum : -1, info_level, total_data));
7129 switch (info_level) {
7131 case SMB_INFO_STANDARD:
7133 status = smb_set_info_standard(conn,
7141 case SMB_INFO_SET_EA:
7143 status = smb_info_set_ea(conn,
7151 case SMB_SET_FILE_BASIC_INFO:
7152 case SMB_FILE_BASIC_INFORMATION:
7154 status = smb_set_file_basic_info(conn,
7162 case SMB_FILE_ALLOCATION_INFORMATION:
7163 case SMB_SET_FILE_ALLOCATION_INFO:
7165 status = smb_set_file_allocation_info(conn, req,
7173 case SMB_FILE_END_OF_FILE_INFORMATION:
7174 case SMB_SET_FILE_END_OF_FILE_INFO:
7176 status = smb_set_file_end_of_file_info(conn, req,
7184 case SMB_FILE_DISPOSITION_INFORMATION:
7185 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7188 /* JRA - We used to just ignore this on a path ?
7189 * Shouldn't this be invalid level on a pathname
7192 if (tran_call != TRANSACT2_SETFILEINFO) {
7193 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7196 status = smb_set_file_disposition_info(conn,
7204 case SMB_FILE_POSITION_INFORMATION:
7206 status = smb_file_position_information(conn,
7213 /* From tridge Samba4 :
7214 * MODE_INFORMATION in setfileinfo (I have no
7215 * idea what "mode information" on a file is - it takes a value of 0,
7216 * 2, 4 or 6. What could it be?).
7219 case SMB_FILE_MODE_INFORMATION:
7221 status = smb_file_mode_information(conn,
7228 * CIFS UNIX extensions.
7231 case SMB_SET_FILE_UNIX_BASIC:
7233 status = smb_set_file_unix_basic(conn, req,
7241 case SMB_SET_FILE_UNIX_INFO2:
7243 status = smb_set_file_unix_info2(conn, req,
7251 case SMB_SET_FILE_UNIX_LINK:
7254 /* We must have a pathname for this. */
7255 return NT_STATUS_INVALID_LEVEL;
7257 status = smb_set_file_unix_link(conn, req, pdata,
7258 total_data, smb_fname);
7262 case SMB_SET_FILE_UNIX_HLINK:
7265 /* We must have a pathname for this. */
7266 return NT_STATUS_INVALID_LEVEL;
7268 status = smb_set_file_unix_hlink(conn, req,
7274 case SMB_FILE_RENAME_INFORMATION:
7276 status = smb_file_rename_information(conn, req,
7282 #if defined(HAVE_POSIX_ACLS)
7283 case SMB_SET_POSIX_ACL:
7285 status = smb_set_posix_acl(conn,
7294 case SMB_SET_POSIX_LOCK:
7297 return NT_STATUS_INVALID_LEVEL;
7299 status = smb_set_posix_lock(conn, req,
7300 pdata, total_data, fsp);
7304 case SMB_POSIX_PATH_OPEN:
7307 /* We must have a pathname for this. */
7308 return NT_STATUS_INVALID_LEVEL;
7311 status = smb_posix_open(conn, req,
7319 case SMB_POSIX_PATH_UNLINK:
7322 /* We must have a pathname for this. */
7323 return NT_STATUS_INVALID_LEVEL;
7326 status = smb_posix_unlink(conn, req,
7334 return NT_STATUS_INVALID_LEVEL;
7337 if (!NT_STATUS_IS_OK(status)) {
7341 *ret_data_size = data_return_size;
7342 return NT_STATUS_OK;
7345 /****************************************************************************
7346 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7347 ****************************************************************************/
7349 static void call_trans2setfilepathinfo(connection_struct *conn,
7350 struct smb_request *req,
7351 unsigned int tran_call,
7352 char **pparams, int total_params,
7353 char **ppdata, int total_data,
7354 unsigned int max_data_bytes)
7356 char *params = *pparams;
7357 char *pdata = *ppdata;
7359 struct smb_filename *smb_fname = NULL;
7360 files_struct *fsp = NULL;
7361 NTSTATUS status = NT_STATUS_OK;
7362 int data_return_size = 0;
7365 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7369 if (tran_call == TRANSACT2_SETFILEINFO) {
7370 if (total_params < 4) {
7371 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7375 fsp = file_fsp(req, SVAL(params,0));
7376 /* Basic check for non-null fsp. */
7377 if (!check_fsp_open(conn, req, fsp)) {
7380 info_level = SVAL(params,2);
7382 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7384 if (!NT_STATUS_IS_OK(status)) {
7385 reply_nterror(req, status);
7389 if(fsp->is_directory || fsp->fh->fd == -1) {
7391 * This is actually a SETFILEINFO on a directory
7392 * handle (returned from an NT SMB). NT5.0 seems
7393 * to do this call. JRA.
7395 if (INFO_LEVEL_IS_UNIX(info_level)) {
7396 /* Always do lstat for UNIX calls. */
7397 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7398 DEBUG(3,("call_trans2setfilepathinfo: "
7399 "SMB_VFS_LSTAT of %s failed "
7401 smb_fname_str_dbg(smb_fname),
7403 reply_nterror(req, map_nt_error_from_unix(errno));
7407 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7408 DEBUG(3,("call_trans2setfilepathinfo: "
7409 "fileinfo of %s failed (%s)\n",
7410 smb_fname_str_dbg(smb_fname),
7412 reply_nterror(req, map_nt_error_from_unix(errno));
7416 } else if (fsp->print_file) {
7418 * Doing a DELETE_ON_CLOSE should cancel a print job.
7420 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7421 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
7423 DEBUG(3,("call_trans2setfilepathinfo: "
7424 "Cancelling print job (%s)\n",
7428 send_trans2_replies(conn, req, params, 2,
7433 reply_doserror(req, ERRDOS, ERRbadpath);
7438 * Original code - this is an open file.
7440 if (!check_fsp(conn, req, fsp)) {
7444 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7445 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7446 "of fnum %d failed (%s)\n", fsp->fnum,
7448 reply_nterror(req, map_nt_error_from_unix(errno));
7456 if (total_params < 7) {
7457 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7461 info_level = SVAL(params,0);
7462 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
7463 total_params - 6, STR_TERMINATE,
7465 if (!NT_STATUS_IS_OK(status)) {
7466 reply_nterror(req, status);
7470 status = filename_convert(req, conn,
7471 req->flags2 & FLAGS2_DFS_PATHNAMES,
7476 if (!NT_STATUS_IS_OK(status)) {
7477 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7478 reply_botherror(req,
7479 NT_STATUS_PATH_NOT_COVERED,
7480 ERRSRV, ERRbadpath);
7483 reply_nterror(req, status);
7487 if (INFO_LEVEL_IS_UNIX(info_level)) {
7489 * For CIFS UNIX extensions the target name may not exist.
7492 /* Always do lstat for UNIX calls. */
7493 SMB_VFS_LSTAT(conn, smb_fname);
7495 } else if (!VALID_STAT(smb_fname->st) &&
7496 SMB_VFS_STAT(conn, smb_fname)) {
7497 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7499 smb_fname_str_dbg(smb_fname),
7501 reply_nterror(req, map_nt_error_from_unix(errno));
7506 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7507 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
7508 fsp ? fsp->fnum : -1, info_level,total_data));
7510 /* Realloc the parameter size */
7511 *pparams = (char *)SMB_REALLOC(*pparams,2);
7512 if (*pparams == NULL) {
7513 reply_nterror(req, NT_STATUS_NO_MEMORY);
7520 status = smbd_do_setfilepathinfo(conn, req, req,
7526 if (!NT_STATUS_IS_OK(status)) {
7527 if (open_was_deferred(req->mid)) {
7528 /* We have re-scheduled this call. */
7531 if (blocking_lock_was_deferred(req->mid)) {
7532 /* We have re-scheduled this call. */
7535 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7536 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7537 ERRSRV, ERRbadpath);
7540 if (info_level == SMB_POSIX_PATH_OPEN) {
7541 reply_openerror(req, status);
7545 reply_nterror(req, status);
7549 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7555 /****************************************************************************
7556 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7557 ****************************************************************************/
7559 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7560 char **pparams, int total_params,
7561 char **ppdata, int total_data,
7562 unsigned int max_data_bytes)
7564 struct smb_filename *smb_dname = NULL;
7565 char *params = *pparams;
7566 char *pdata = *ppdata;
7567 char *directory = NULL;
7568 NTSTATUS status = NT_STATUS_OK;
7569 struct ea_list *ea_list = NULL;
7570 TALLOC_CTX *ctx = talloc_tos();
7572 if (!CAN_WRITE(conn)) {
7573 reply_doserror(req, ERRSRV, ERRaccess);
7577 if (total_params < 5) {
7578 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7582 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7583 total_params - 4, STR_TERMINATE,
7585 if (!NT_STATUS_IS_OK(status)) {
7586 reply_nterror(req, status);
7590 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7592 status = filename_convert(ctx,
7594 req->flags2 & FLAGS2_DFS_PATHNAMES,
7600 if (!NT_STATUS_IS_OK(status)) {
7601 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7602 reply_botherror(req,
7603 NT_STATUS_PATH_NOT_COVERED,
7604 ERRSRV, ERRbadpath);
7607 reply_nterror(req, status);
7611 /* Any data in this call is an EA list. */
7612 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7613 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7618 * OS/2 workplace shell seems to send SET_EA requests of "null"
7619 * length (4 bytes containing IVAL 4).
7620 * They seem to have no effect. Bug #3212. JRA.
7623 if (total_data != 4) {
7624 if (total_data < 10) {
7625 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7629 if (IVAL(pdata,0) > total_data) {
7630 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7631 IVAL(pdata,0), (unsigned int)total_data));
7632 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7636 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7639 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7643 /* If total_data == 4 Windows doesn't care what values
7644 * are placed in that field, it just ignores them.
7645 * The System i QNTC IBM SMB client puts bad values here,
7646 * so ignore them. */
7648 status = create_directory(conn, req, smb_dname);
7650 if (!NT_STATUS_IS_OK(status)) {
7651 reply_nterror(req, status);
7655 /* Try and set any given EA. */
7657 status = set_ea(conn, NULL, smb_dname, ea_list);
7658 if (!NT_STATUS_IS_OK(status)) {
7659 reply_nterror(req, status);
7664 /* Realloc the parameter and data sizes */
7665 *pparams = (char *)SMB_REALLOC(*pparams,2);
7666 if(*pparams == NULL) {
7667 reply_nterror(req, NT_STATUS_NO_MEMORY);
7674 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7677 TALLOC_FREE(smb_dname);
7681 /****************************************************************************
7682 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7683 We don't actually do this - we just send a null response.
7684 ****************************************************************************/
7686 static void call_trans2findnotifyfirst(connection_struct *conn,
7687 struct smb_request *req,
7688 char **pparams, int total_params,
7689 char **ppdata, int total_data,
7690 unsigned int max_data_bytes)
7692 char *params = *pparams;
7695 if (total_params < 6) {
7696 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7700 info_level = SVAL(params,4);
7701 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7703 switch (info_level) {
7708 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7712 /* Realloc the parameter and data sizes */
7713 *pparams = (char *)SMB_REALLOC(*pparams,6);
7714 if (*pparams == NULL) {
7715 reply_nterror(req, NT_STATUS_NO_MEMORY);
7720 SSVAL(params,0,fnf_handle);
7721 SSVAL(params,2,0); /* No changes */
7722 SSVAL(params,4,0); /* No EA errors */
7729 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7734 /****************************************************************************
7735 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7736 changes). Currently this does nothing.
7737 ****************************************************************************/
7739 static void call_trans2findnotifynext(connection_struct *conn,
7740 struct smb_request *req,
7741 char **pparams, int total_params,
7742 char **ppdata, int total_data,
7743 unsigned int max_data_bytes)
7745 char *params = *pparams;
7747 DEBUG(3,("call_trans2findnotifynext\n"));
7749 /* Realloc the parameter and data sizes */
7750 *pparams = (char *)SMB_REALLOC(*pparams,4);
7751 if (*pparams == NULL) {
7752 reply_nterror(req, NT_STATUS_NO_MEMORY);
7757 SSVAL(params,0,0); /* No changes */
7758 SSVAL(params,2,0); /* No EA errors */
7760 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7765 /****************************************************************************
7766 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7767 ****************************************************************************/
7769 static void call_trans2getdfsreferral(connection_struct *conn,
7770 struct smb_request *req,
7771 char **pparams, int total_params,
7772 char **ppdata, int total_data,
7773 unsigned int max_data_bytes)
7775 char *params = *pparams;
7776 char *pathname = NULL;
7778 int max_referral_level;
7779 NTSTATUS status = NT_STATUS_OK;
7780 TALLOC_CTX *ctx = talloc_tos();
7782 DEBUG(10,("call_trans2getdfsreferral\n"));
7784 if (total_params < 3) {
7785 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7789 max_referral_level = SVAL(params,0);
7791 if(!lp_host_msdfs()) {
7792 reply_doserror(req, ERRDOS, ERRbadfunc);
7796 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7797 total_params - 2, STR_TERMINATE);
7799 reply_nterror(req, NT_STATUS_NOT_FOUND);
7802 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7803 ppdata,&status)) < 0) {
7804 reply_nterror(req, status);
7808 SSVAL(req->inbuf, smb_flg2,
7809 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7810 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7815 #define LMCAT_SPL 0x53
7816 #define LMFUNC_GETJOBID 0x60
7818 /****************************************************************************
7819 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7820 ****************************************************************************/
7822 static void call_trans2ioctl(connection_struct *conn,
7823 struct smb_request *req,
7824 char **pparams, int total_params,
7825 char **ppdata, int total_data,
7826 unsigned int max_data_bytes)
7828 char *pdata = *ppdata;
7829 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7831 /* check for an invalid fid before proceeding */
7834 reply_doserror(req, ERRDOS, ERRbadfid);
7838 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7839 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7840 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7841 if (*ppdata == NULL) {
7842 reply_nterror(req, NT_STATUS_NO_MEMORY);
7847 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7848 CAN ACCEPT THIS IN UNICODE. JRA. */
7850 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7851 srvstr_push(pdata, req->flags2, pdata + 2,
7852 global_myname(), 15,
7853 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7854 srvstr_push(pdata, req->flags2, pdata+18,
7855 lp_servicename(SNUM(conn)), 13,
7856 STR_ASCII|STR_TERMINATE); /* Service name */
7857 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7862 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7863 reply_doserror(req, ERRSRV, ERRerror);
7866 /****************************************************************************
7867 Reply to a SMBfindclose (stop trans2 directory search).
7868 ****************************************************************************/
7870 void reply_findclose(struct smb_request *req)
7874 START_PROFILE(SMBfindclose);
7877 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7878 END_PROFILE(SMBfindclose);
7882 dptr_num = SVALS(req->vwv+0, 0);
7884 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7886 dptr_close(&dptr_num);
7888 reply_outbuf(req, 0, 0);
7890 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7892 END_PROFILE(SMBfindclose);
7896 /****************************************************************************
7897 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7898 ****************************************************************************/
7900 void reply_findnclose(struct smb_request *req)
7904 START_PROFILE(SMBfindnclose);
7907 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7908 END_PROFILE(SMBfindnclose);
7912 dptr_num = SVAL(req->vwv+0, 0);
7914 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7916 /* We never give out valid handles for a
7917 findnotifyfirst - so any dptr_num is ok here.
7920 reply_outbuf(req, 0, 0);
7922 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7924 END_PROFILE(SMBfindnclose);
7928 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7929 struct trans_state *state)
7931 if (Protocol >= PROTOCOL_NT1) {
7932 req->flags2 |= 0x40; /* IS_LONG_NAME */
7933 SSVAL(req->inbuf,smb_flg2,req->flags2);
7936 if (conn->encrypt_level == Required && !req->encrypted) {
7937 if (state->call != TRANSACT2_QFSINFO &&
7938 state->call != TRANSACT2_SETFSINFO) {
7939 DEBUG(0,("handle_trans2: encryption required "
7941 (unsigned int)state->call));
7942 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7947 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
7949 /* Now we must call the relevant TRANS2 function */
7950 switch(state->call) {
7951 case TRANSACT2_OPEN:
7953 START_PROFILE(Trans2_open);
7954 call_trans2open(conn, req,
7955 &state->param, state->total_param,
7956 &state->data, state->total_data,
7957 state->max_data_return);
7958 END_PROFILE(Trans2_open);
7962 case TRANSACT2_FINDFIRST:
7964 START_PROFILE(Trans2_findfirst);
7965 call_trans2findfirst(conn, req,
7966 &state->param, state->total_param,
7967 &state->data, state->total_data,
7968 state->max_data_return);
7969 END_PROFILE(Trans2_findfirst);
7973 case TRANSACT2_FINDNEXT:
7975 START_PROFILE(Trans2_findnext);
7976 call_trans2findnext(conn, req,
7977 &state->param, state->total_param,
7978 &state->data, state->total_data,
7979 state->max_data_return);
7980 END_PROFILE(Trans2_findnext);
7984 case TRANSACT2_QFSINFO:
7986 START_PROFILE(Trans2_qfsinfo);
7987 call_trans2qfsinfo(conn, req,
7988 &state->param, state->total_param,
7989 &state->data, state->total_data,
7990 state->max_data_return);
7991 END_PROFILE(Trans2_qfsinfo);
7995 case TRANSACT2_SETFSINFO:
7997 START_PROFILE(Trans2_setfsinfo);
7998 call_trans2setfsinfo(conn, req,
7999 &state->param, state->total_param,
8000 &state->data, state->total_data,
8001 state->max_data_return);
8002 END_PROFILE(Trans2_setfsinfo);
8006 case TRANSACT2_QPATHINFO:
8007 case TRANSACT2_QFILEINFO:
8009 START_PROFILE(Trans2_qpathinfo);
8010 call_trans2qfilepathinfo(conn, req, state->call,
8011 &state->param, state->total_param,
8012 &state->data, state->total_data,
8013 state->max_data_return);
8014 END_PROFILE(Trans2_qpathinfo);
8018 case TRANSACT2_SETPATHINFO:
8019 case TRANSACT2_SETFILEINFO:
8021 START_PROFILE(Trans2_setpathinfo);
8022 call_trans2setfilepathinfo(conn, req, state->call,
8023 &state->param, state->total_param,
8024 &state->data, state->total_data,
8025 state->max_data_return);
8026 END_PROFILE(Trans2_setpathinfo);
8030 case TRANSACT2_FINDNOTIFYFIRST:
8032 START_PROFILE(Trans2_findnotifyfirst);
8033 call_trans2findnotifyfirst(conn, req,
8034 &state->param, state->total_param,
8035 &state->data, state->total_data,
8036 state->max_data_return);
8037 END_PROFILE(Trans2_findnotifyfirst);
8041 case TRANSACT2_FINDNOTIFYNEXT:
8043 START_PROFILE(Trans2_findnotifynext);
8044 call_trans2findnotifynext(conn, req,
8045 &state->param, state->total_param,
8046 &state->data, state->total_data,
8047 state->max_data_return);
8048 END_PROFILE(Trans2_findnotifynext);
8052 case TRANSACT2_MKDIR:
8054 START_PROFILE(Trans2_mkdir);
8055 call_trans2mkdir(conn, req,
8056 &state->param, state->total_param,
8057 &state->data, state->total_data,
8058 state->max_data_return);
8059 END_PROFILE(Trans2_mkdir);
8063 case TRANSACT2_GET_DFS_REFERRAL:
8065 START_PROFILE(Trans2_get_dfs_referral);
8066 call_trans2getdfsreferral(conn, req,
8067 &state->param, state->total_param,
8068 &state->data, state->total_data,
8069 state->max_data_return);
8070 END_PROFILE(Trans2_get_dfs_referral);
8074 case TRANSACT2_IOCTL:
8076 START_PROFILE(Trans2_ioctl);
8077 call_trans2ioctl(conn, req,
8078 &state->param, state->total_param,
8079 &state->data, state->total_data,
8080 state->max_data_return);
8081 END_PROFILE(Trans2_ioctl);
8086 /* Error in request */
8087 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8088 reply_doserror(req, ERRSRV,ERRerror);
8092 /****************************************************************************
8093 Reply to a SMBtrans2.
8094 ****************************************************************************/
8096 void reply_trans2(struct smb_request *req)
8098 connection_struct *conn = req->conn;
8103 unsigned int tran_call;
8104 struct trans_state *state;
8107 START_PROFILE(SMBtrans2);
8109 if (req->wct < 14) {
8110 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8111 END_PROFILE(SMBtrans2);
8115 dsoff = SVAL(req->vwv+12, 0);
8116 dscnt = SVAL(req->vwv+11, 0);
8117 psoff = SVAL(req->vwv+10, 0);
8118 pscnt = SVAL(req->vwv+9, 0);
8119 tran_call = SVAL(req->vwv+14, 0);
8121 result = allow_new_trans(conn->pending_trans, req->mid);
8122 if (!NT_STATUS_IS_OK(result)) {
8123 DEBUG(2, ("Got invalid trans2 request: %s\n",
8124 nt_errstr(result)));
8125 reply_nterror(req, result);
8126 END_PROFILE(SMBtrans2);
8131 switch (tran_call) {
8132 /* List the allowed trans2 calls on IPC$ */
8133 case TRANSACT2_OPEN:
8134 case TRANSACT2_GET_DFS_REFERRAL:
8135 case TRANSACT2_QFILEINFO:
8136 case TRANSACT2_QFSINFO:
8137 case TRANSACT2_SETFSINFO:
8140 reply_doserror(req, ERRSRV, ERRaccess);
8141 END_PROFILE(SMBtrans2);
8146 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8147 DEBUG(0, ("talloc failed\n"));
8148 reply_nterror(req, NT_STATUS_NO_MEMORY);
8149 END_PROFILE(SMBtrans2);
8153 state->cmd = SMBtrans2;
8155 state->mid = req->mid;
8156 state->vuid = req->vuid;
8157 state->setup_count = SVAL(req->vwv+13, 0);
8158 state->setup = NULL;
8159 state->total_param = SVAL(req->vwv+0, 0);
8160 state->param = NULL;
8161 state->total_data = SVAL(req->vwv+1, 0);
8163 state->max_param_return = SVAL(req->vwv+2, 0);
8164 state->max_data_return = SVAL(req->vwv+3, 0);
8165 state->max_setup_return = SVAL(req->vwv+4, 0);
8166 state->close_on_completion = BITSETW(req->vwv+5, 0);
8167 state->one_way = BITSETW(req->vwv+5, 1);
8169 state->call = tran_call;
8171 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8172 is so as a sanity check */
8173 if (state->setup_count != 1) {
8175 * Need to have rc=0 for ioctl to get job id for OS/2.
8176 * Network printing will fail if function is not successful.
8177 * Similar function in reply.c will be used if protocol
8178 * is LANMAN1.0 instead of LM1.2X002.
8179 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8180 * outbuf doesn't have to be set(only job id is used).
8182 if ( (state->setup_count == 4)
8183 && (tran_call == TRANSACT2_IOCTL)
8184 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8185 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8186 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8188 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8189 DEBUG(2,("Transaction is %d\n",tran_call));
8191 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8192 END_PROFILE(SMBtrans2);
8197 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8200 if (state->total_data) {
8202 if (trans_oob(state->total_data, 0, dscnt)
8203 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8207 /* Can't use talloc here, the core routines do realloc on the
8208 * params and data. */
8209 state->data = (char *)SMB_MALLOC(state->total_data);
8210 if (state->data == NULL) {
8211 DEBUG(0,("reply_trans2: data malloc fail for %u "
8212 "bytes !\n", (unsigned int)state->total_data));
8214 reply_nterror(req, NT_STATUS_NO_MEMORY);
8215 END_PROFILE(SMBtrans2);
8219 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8222 if (state->total_param) {
8224 if (trans_oob(state->total_param, 0, pscnt)
8225 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8229 /* Can't use talloc here, the core routines do realloc on the
8230 * params and data. */
8231 state->param = (char *)SMB_MALLOC(state->total_param);
8232 if (state->param == NULL) {
8233 DEBUG(0,("reply_trans: param malloc fail for %u "
8234 "bytes !\n", (unsigned int)state->total_param));
8235 SAFE_FREE(state->data);
8237 reply_nterror(req, NT_STATUS_NO_MEMORY);
8238 END_PROFILE(SMBtrans2);
8242 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8245 state->received_data = dscnt;
8246 state->received_param = pscnt;
8248 if ((state->received_param == state->total_param) &&
8249 (state->received_data == state->total_data)) {
8251 handle_trans2(conn, req, state);
8253 SAFE_FREE(state->data);
8254 SAFE_FREE(state->param);
8256 END_PROFILE(SMBtrans2);
8260 DLIST_ADD(conn->pending_trans, state);
8262 /* We need to send an interim response then receive the rest
8263 of the parameter/data bytes */
8264 reply_outbuf(req, 0, 0);
8265 show_msg((char *)req->outbuf);
8266 END_PROFILE(SMBtrans2);
8271 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8272 SAFE_FREE(state->data);
8273 SAFE_FREE(state->param);
8275 END_PROFILE(SMBtrans2);
8276 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8280 /****************************************************************************
8281 Reply to a SMBtranss2
8282 ****************************************************************************/
8284 void reply_transs2(struct smb_request *req)
8286 connection_struct *conn = req->conn;
8287 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8288 struct trans_state *state;
8290 START_PROFILE(SMBtranss2);
8292 show_msg((char *)req->inbuf);
8295 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8296 END_PROFILE(SMBtranss2);
8300 for (state = conn->pending_trans; state != NULL;
8301 state = state->next) {
8302 if (state->mid == req->mid) {
8307 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8308 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8309 END_PROFILE(SMBtranss2);
8313 /* Revise state->total_param and state->total_data in case they have
8314 changed downwards */
8316 if (SVAL(req->vwv+0, 0) < state->total_param)
8317 state->total_param = SVAL(req->vwv+0, 0);
8318 if (SVAL(req->vwv+1, 0) < state->total_data)
8319 state->total_data = SVAL(req->vwv+1, 0);
8321 pcnt = SVAL(req->vwv+2, 0);
8322 poff = SVAL(req->vwv+3, 0);
8323 pdisp = SVAL(req->vwv+4, 0);
8325 dcnt = SVAL(req->vwv+5, 0);
8326 doff = SVAL(req->vwv+6, 0);
8327 ddisp = SVAL(req->vwv+7, 0);
8329 state->received_param += pcnt;
8330 state->received_data += dcnt;
8332 if ((state->received_data > state->total_data) ||
8333 (state->received_param > state->total_param))
8337 if (trans_oob(state->total_param, pdisp, pcnt)
8338 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8341 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8345 if (trans_oob(state->total_data, ddisp, dcnt)
8346 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8349 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8352 if ((state->received_param < state->total_param) ||
8353 (state->received_data < state->total_data)) {
8354 END_PROFILE(SMBtranss2);
8358 handle_trans2(conn, req, state);
8360 DLIST_REMOVE(conn->pending_trans, state);
8361 SAFE_FREE(state->data);
8362 SAFE_FREE(state->param);
8365 END_PROFILE(SMBtranss2);
8370 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8371 DLIST_REMOVE(conn->pending_trans, state);
8372 SAFE_FREE(state->data);
8373 SAFE_FREE(state->param);
8375 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8376 END_PROFILE(SMBtranss2);