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,
1028 if (!NT_STATUS_IS_OK(status)) {
1029 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1030 reply_botherror(req,
1031 NT_STATUS_PATH_NOT_COVERED,
1032 ERRSRV, ERRbadpath);
1035 reply_nterror(req, status);
1039 if (open_ofun == 0) {
1040 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1044 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, open_ofun,
1045 &access_mask, &share_mode,
1046 &create_disposition,
1048 reply_doserror(req, ERRDOS, ERRbadaccess);
1052 /* Any data in this call is an EA list. */
1053 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
1054 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1058 if (total_data != 4) {
1059 if (total_data < 10) {
1060 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1064 if (IVAL(pdata,0) > total_data) {
1065 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1066 IVAL(pdata,0), (unsigned int)total_data));
1067 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1071 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1074 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1077 } else if (IVAL(pdata,0) != 4) {
1078 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1082 status = SMB_VFS_CREATE_FILE(
1085 0, /* root_dir_fid */
1086 smb_fname, /* fname */
1087 access_mask, /* access_mask */
1088 share_mode, /* share_access */
1089 create_disposition, /* create_disposition*/
1090 create_options, /* create_options */
1091 open_attr, /* file_attributes */
1092 oplock_request, /* oplock_request */
1093 open_size, /* allocation_size */
1095 ea_list, /* ea_list */
1097 &smb_action); /* psbuf */
1099 if (!NT_STATUS_IS_OK(status)) {
1100 if (open_was_deferred(req->mid)) {
1101 /* We have re-scheduled this call. */
1104 reply_openerror(req, status);
1108 size = get_file_size_stat(&smb_fname->st);
1109 fattr = dos_mode(conn, smb_fname);
1110 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1111 inode = smb_fname->st.st_ex_ino;
1113 close_file(req, fsp, ERROR_CLOSE);
1114 reply_doserror(req, ERRDOS,ERRnoaccess);
1118 /* Realloc the size of parameters and data we will return */
1119 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1120 if(*pparams == NULL ) {
1121 reply_nterror(req, NT_STATUS_NO_MEMORY);
1126 SSVAL(params,0,fsp->fnum);
1127 SSVAL(params,2,fattr);
1128 srv_put_dos_date2(params,4, mtime);
1129 SIVAL(params,8, (uint32)size);
1130 SSVAL(params,12,deny_mode);
1131 SSVAL(params,14,0); /* open_type - file or directory. */
1132 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1134 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1135 smb_action |= EXTENDED_OPLOCK_GRANTED;
1138 SSVAL(params,18,smb_action);
1141 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1143 SIVAL(params,20,inode);
1144 SSVAL(params,24,0); /* Padding. */
1146 uint32 ea_size = estimate_ea_size(conn, fsp,
1147 fsp->fsp_name->base_name);
1148 SIVAL(params, 26, ea_size);
1150 SIVAL(params, 26, 0);
1153 /* Send the required number of replies */
1154 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1156 TALLOC_FREE(smb_fname);
1159 /*********************************************************
1160 Routine to check if a given string matches exactly.
1161 as a special case a mask of "." does NOT match. That
1162 is required for correct wildcard semantics
1163 Case can be significant or not.
1164 **********************************************************/
1166 static bool exact_match(connection_struct *conn,
1170 if (mask[0] == '.' && mask[1] == 0)
1172 if (dptr_has_wild(conn->dirptr)) {
1175 if (conn->case_sensitive)
1176 return strcmp(str,mask)==0;
1178 return StrCaseCmp(str,mask) == 0;
1181 /****************************************************************************
1182 Return the filetype for UNIX extensions.
1183 ****************************************************************************/
1185 static uint32 unix_filetype(mode_t mode)
1188 return UNIX_TYPE_FILE;
1189 else if(S_ISDIR(mode))
1190 return UNIX_TYPE_DIR;
1192 else if(S_ISLNK(mode))
1193 return UNIX_TYPE_SYMLINK;
1196 else if(S_ISCHR(mode))
1197 return UNIX_TYPE_CHARDEV;
1200 else if(S_ISBLK(mode))
1201 return UNIX_TYPE_BLKDEV;
1204 else if(S_ISFIFO(mode))
1205 return UNIX_TYPE_FIFO;
1208 else if(S_ISSOCK(mode))
1209 return UNIX_TYPE_SOCKET;
1212 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1213 return UNIX_TYPE_UNKNOWN;
1216 /****************************************************************************
1217 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1218 ****************************************************************************/
1220 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1222 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1223 const SMB_STRUCT_STAT *psbuf,
1225 enum perm_type ptype,
1230 if (perms == SMB_MODE_NO_CHANGE) {
1231 if (!VALID_STAT(*psbuf)) {
1232 return NT_STATUS_INVALID_PARAMETER;
1234 *ret_perms = psbuf->st_ex_mode;
1235 return NT_STATUS_OK;
1239 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1240 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1241 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1242 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1243 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1244 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1245 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1246 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1247 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1249 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1252 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1255 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1260 /* Apply mode mask */
1261 ret &= lp_create_mask(SNUM(conn));
1262 /* Add in force bits */
1263 ret |= lp_force_create_mode(SNUM(conn));
1266 ret &= lp_dir_mask(SNUM(conn));
1267 /* Add in force bits */
1268 ret |= lp_force_dir_mode(SNUM(conn));
1270 case PERM_EXISTING_FILE:
1271 /* Apply mode mask */
1272 ret &= lp_security_mask(SNUM(conn));
1273 /* Add in force bits */
1274 ret |= lp_force_security_mode(SNUM(conn));
1276 case PERM_EXISTING_DIR:
1277 /* Apply mode mask */
1278 ret &= lp_dir_security_mask(SNUM(conn));
1279 /* Add in force bits */
1280 ret |= lp_force_dir_security_mode(SNUM(conn));
1285 return NT_STATUS_OK;
1288 /****************************************************************************
1289 Needed to show the msdfs symlinks as directories. Modifies psbuf
1290 to be a directory if it's a msdfs link.
1291 ****************************************************************************/
1293 static bool check_msdfs_link(connection_struct *conn,
1294 const char *pathname,
1295 SMB_STRUCT_STAT *psbuf)
1297 int saved_errno = errno;
1298 if(lp_host_msdfs() &&
1299 lp_msdfs_root(SNUM(conn)) &&
1300 is_msdfs_link(conn, pathname, psbuf)) {
1302 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1305 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1306 errno = saved_errno;
1309 errno = saved_errno;
1314 /****************************************************************************
1315 Get a level dependent lanman2 dir entry.
1316 ****************************************************************************/
1318 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1319 connection_struct *conn,
1321 const char *path_mask,
1324 int requires_resume_key,
1330 int space_remaining,
1332 bool *got_exact_match,
1333 int *last_entry_off,
1334 struct ea_list *name_list)
1338 SMB_STRUCT_STAT sbuf;
1339 const char *mask = NULL;
1340 char *pathreal = NULL;
1342 char *p, *q, *pdata = *ppdata;
1346 SMB_OFF_T file_size = 0;
1347 uint64_t allocation_size = 0;
1349 struct timespec mdate_ts, adate_ts, create_date_ts;
1350 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1352 char *last_entry_ptr;
1354 uint32 nt_extmode; /* Used for NT connections instead of mode */
1355 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1356 bool check_mangled_names = lp_manglednames(conn->params);
1357 char mangled_name[13]; /* mangled 8.3 name. */
1359 *out_of_space = False;
1360 *got_exact_match = False;
1362 ZERO_STRUCT(mdate_ts);
1363 ZERO_STRUCT(adate_ts);
1364 ZERO_STRUCT(create_date_ts);
1366 if (!conn->dirptr) {
1370 p = strrchr_m(path_mask,'/');
1373 mask = talloc_strdup(ctx,"*.*");
1383 bool ms_dfs_link = False;
1385 /* Needed if we run out of space */
1386 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1387 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1390 * Due to bugs in NT client redirectors we are not using
1391 * resume keys any more - set them to zero.
1392 * Check out the related comments in findfirst/findnext.
1398 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1399 (long)conn->dirptr,curr_dirpos));
1406 * fname may get mangled, dname is never mangled.
1407 * Whenever we're accessing the filesystem we use
1408 * pathreal which is composed from dname.
1414 /* Mangle fname if it's an illegal name. */
1415 if (mangle_must_mangle(dname,conn->params)) {
1416 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1418 continue; /* Error - couldn't mangle. */
1420 fname = talloc_strdup(ctx, mangled_name);
1426 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1427 got_match = mask_match(fname, mask, conn->case_sensitive);
1430 if(!got_match && check_mangled_names &&
1431 !mangle_is_8_3(fname, False, conn->params)) {
1433 * It turns out that NT matches wildcards against
1434 * both long *and* short names. This may explain some
1435 * of the wildcard wierdness from old DOS clients
1436 * that some people have been seeing.... JRA.
1438 /* Force the mangling into 8.3. */
1439 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1441 continue; /* Error - couldn't mangle. */
1444 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1445 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1450 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1451 struct smb_filename *smb_fname = NULL;
1454 if (dont_descend && !isdots) {
1461 pathreal = talloc_asprintf(ctx,
1466 pathreal = talloc_asprintf(ctx,
1477 /* A dirent from dptr_ReadDirName isn't a stream. */
1478 status = create_synthetic_smb_fname(ctx, pathreal,
1481 if (!NT_STATUS_IS_OK(status)) {
1486 if (INFO_LEVEL_IS_UNIX(info_level)) {
1487 if (SMB_VFS_LSTAT(conn, smb_fname) != 0) {
1488 DEBUG(5,("get_lanman2_dir_entry: "
1489 "Couldn't lstat [%s] (%s)\n",
1490 smb_fname_str_dbg(smb_fname),
1492 TALLOC_FREE(smb_fname);
1493 TALLOC_FREE(pathreal);
1497 } else if (!VALID_STAT(smb_fname->st) &&
1498 SMB_VFS_STAT(conn, smb_fname) != 0) {
1499 /* Needed to show the msdfs symlinks as
1503 check_msdfs_link(conn,
1504 smb_fname->base_name,
1507 DEBUG(5,("get_lanman2_dir_entry: "
1508 "Couldn't stat [%s] (%s)\n",
1509 smb_fname_str_dbg(smb_fname),
1511 TALLOC_FREE(smb_fname);
1512 TALLOC_FREE(pathreal);
1519 mode = dos_mode_msdfs(conn, smb_fname);
1521 mode = dos_mode(conn, smb_fname);
1524 if (!dir_check_ftype(conn,mode,dirtype)) {
1525 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1526 TALLOC_FREE(smb_fname);
1527 TALLOC_FREE(pathreal);
1532 if (!(mode & aDIR)) {
1533 file_size = get_file_size_stat(&smb_fname->st);
1536 SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1538 if (ask_sharemode) {
1539 struct timespec write_time_ts;
1540 struct file_id fileid;
1542 ZERO_STRUCT(write_time_ts);
1543 fileid = vfs_file_id_from_sbuf(conn,
1545 get_file_infos(fileid, NULL, &write_time_ts);
1546 if (!null_timespec(write_time_ts)) {
1547 update_stat_ex_mtime(&smb_fname->st,
1552 mdate_ts = smb_fname->st.st_ex_mtime;
1553 adate_ts = smb_fname->st.st_ex_atime;
1554 create_date_ts = smb_fname->st.st_ex_btime;
1556 if (lp_dos_filetime_resolution(SNUM(conn))) {
1557 dos_filetime_timespec(&create_date_ts);
1558 dos_filetime_timespec(&mdate_ts);
1559 dos_filetime_timespec(&adate_ts);
1562 create_date = convert_timespec_to_time_t(create_date_ts);
1563 mdate = convert_timespec_to_time_t(mdate_ts);
1564 adate = convert_timespec_to_time_t(adate_ts);
1566 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",
1567 smb_fname_str_dbg(smb_fname), fname));
1571 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1572 sbuf = smb_fname->st;
1574 TALLOC_FREE(smb_fname);
1584 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1586 switch (info_level) {
1587 case SMB_FIND_INFO_STANDARD:
1588 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1589 if(requires_resume_key) {
1593 srv_put_dos_date2(p,0,create_date);
1594 srv_put_dos_date2(p,4,adate);
1595 srv_put_dos_date2(p,8,mdate);
1596 SIVAL(p,12,(uint32)file_size);
1597 SIVAL(p,16,(uint32)allocation_size);
1601 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1602 p += ucs2_align(base_data, p, 0);
1604 len = srvstr_push(base_data, flags2, p,
1605 fname, PTR_DIFF(end_data, p),
1607 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1609 SCVAL(nameptr, -1, len - 2);
1611 SCVAL(nameptr, -1, 0);
1615 SCVAL(nameptr, -1, len - 1);
1617 SCVAL(nameptr, -1, 0);
1623 case SMB_FIND_EA_SIZE:
1624 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1625 if(requires_resume_key) {
1629 srv_put_dos_date2(p,0,create_date);
1630 srv_put_dos_date2(p,4,adate);
1631 srv_put_dos_date2(p,8,mdate);
1632 SIVAL(p,12,(uint32)file_size);
1633 SIVAL(p,16,(uint32)allocation_size);
1636 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1637 SIVAL(p,22,ea_size); /* Extended attributes */
1641 len = srvstr_push(base_data, flags2,
1642 p, fname, PTR_DIFF(end_data, p),
1643 STR_TERMINATE | STR_NOALIGN);
1644 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1657 SCVAL(nameptr,0,len);
1659 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1662 case SMB_FIND_EA_LIST:
1664 struct ea_list *file_list = NULL;
1667 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1671 if(requires_resume_key) {
1675 srv_put_dos_date2(p,0,create_date);
1676 srv_put_dos_date2(p,4,adate);
1677 srv_put_dos_date2(p,8,mdate);
1678 SIVAL(p,12,(uint32)file_size);
1679 SIVAL(p,16,(uint32)allocation_size);
1681 p += 22; /* p now points to the EA area. */
1683 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1684 name_list = ea_list_union(name_list, file_list, &ea_len);
1686 /* We need to determine if this entry will fit in the space available. */
1687 /* Max string size is 255 bytes. */
1688 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1689 /* Move the dirptr back to prev_dirpos */
1690 dptr_SeekDir(conn->dirptr, prev_dirpos);
1691 *out_of_space = True;
1692 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1693 return False; /* Not finished - just out of space */
1696 /* Push the ea_data followed by the name. */
1697 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1699 len = srvstr_push(base_data, flags2,
1700 p + 1, fname, PTR_DIFF(end_data, p+1),
1701 STR_TERMINATE | STR_NOALIGN);
1702 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1715 SCVAL(nameptr,0,len);
1717 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1721 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1722 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1723 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1725 SIVAL(p,0,reskey); p += 4;
1726 put_long_date_timespec(p,create_date_ts); p += 8;
1727 put_long_date_timespec(p,adate_ts); p += 8;
1728 put_long_date_timespec(p,mdate_ts); p += 8;
1729 put_long_date_timespec(p,mdate_ts); p += 8;
1730 SOFF_T(p,0,file_size); p += 8;
1731 SOFF_T(p,0,allocation_size); p += 8;
1732 SIVAL(p,0,nt_extmode); p += 4;
1733 q = p; p += 4; /* q is placeholder for name length. */
1735 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1736 SIVAL(p,0,ea_size); /* Extended attributes */
1739 /* Clear the short name buffer. This is
1740 * IMPORTANT as not doing so will trigger
1741 * a Win2k client bug. JRA.
1743 if (!was_8_3 && check_mangled_names) {
1744 if (!name_to_8_3(fname,mangled_name,True,
1746 /* Error - mangle failed ! */
1747 memset(mangled_name,'\0',12);
1749 mangled_name[12] = 0;
1750 len = srvstr_push(base_data, flags2,
1751 p+2, mangled_name, 24,
1752 STR_UPPER|STR_UNICODE);
1754 memset(p + 2 + len,'\0',24 - len);
1761 len = srvstr_push(base_data, flags2, p,
1762 fname, PTR_DIFF(end_data, p),
1763 STR_TERMINATE_ASCII);
1766 SIVAL(p,0,0); /* Ensure any padding is null. */
1767 len = PTR_DIFF(p, pdata);
1768 len = (len + 3) & ~3;
1773 case SMB_FIND_FILE_DIRECTORY_INFO:
1774 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1776 SIVAL(p,0,reskey); p += 4;
1777 put_long_date_timespec(p,create_date_ts); p += 8;
1778 put_long_date_timespec(p,adate_ts); p += 8;
1779 put_long_date_timespec(p,mdate_ts); p += 8;
1780 put_long_date_timespec(p,mdate_ts); p += 8;
1781 SOFF_T(p,0,file_size); p += 8;
1782 SOFF_T(p,0,allocation_size); p += 8;
1783 SIVAL(p,0,nt_extmode); p += 4;
1784 len = srvstr_push(base_data, flags2,
1785 p + 4, fname, PTR_DIFF(end_data, p+4),
1786 STR_TERMINATE_ASCII);
1789 SIVAL(p,0,0); /* Ensure any padding is null. */
1790 len = PTR_DIFF(p, pdata);
1791 len = (len + 3) & ~3;
1796 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1797 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1799 SIVAL(p,0,reskey); p += 4;
1800 put_long_date_timespec(p,create_date_ts); p += 8;
1801 put_long_date_timespec(p,adate_ts); p += 8;
1802 put_long_date_timespec(p,mdate_ts); p += 8;
1803 put_long_date_timespec(p,mdate_ts); p += 8;
1804 SOFF_T(p,0,file_size); p += 8;
1805 SOFF_T(p,0,allocation_size); p += 8;
1806 SIVAL(p,0,nt_extmode); p += 4;
1807 q = p; p += 4; /* q is placeholder for name length. */
1809 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1810 SIVAL(p,0,ea_size); /* Extended attributes */
1813 len = srvstr_push(base_data, flags2, p,
1814 fname, PTR_DIFF(end_data, p),
1815 STR_TERMINATE_ASCII);
1819 SIVAL(p,0,0); /* Ensure any padding is null. */
1820 len = PTR_DIFF(p, pdata);
1821 len = (len + 3) & ~3;
1826 case SMB_FIND_FILE_NAMES_INFO:
1827 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1829 SIVAL(p,0,reskey); p += 4;
1831 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1832 acl on a dir (tridge) */
1833 len = srvstr_push(base_data, flags2, p,
1834 fname, PTR_DIFF(end_data, p),
1835 STR_TERMINATE_ASCII);
1838 SIVAL(p,0,0); /* Ensure any padding is null. */
1839 len = PTR_DIFF(p, pdata);
1840 len = (len + 3) & ~3;
1845 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1846 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1848 SIVAL(p,0,reskey); p += 4;
1849 put_long_date_timespec(p,create_date_ts); p += 8;
1850 put_long_date_timespec(p,adate_ts); p += 8;
1851 put_long_date_timespec(p,mdate_ts); p += 8;
1852 put_long_date_timespec(p,mdate_ts); p += 8;
1853 SOFF_T(p,0,file_size); p += 8;
1854 SOFF_T(p,0,allocation_size); p += 8;
1855 SIVAL(p,0,nt_extmode); p += 4;
1856 q = p; p += 4; /* q is placeholder for name length. */
1858 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1859 SIVAL(p,0,ea_size); /* Extended attributes */
1862 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1863 SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */
1864 SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */
1865 len = srvstr_push(base_data, flags2, p,
1866 fname, PTR_DIFF(end_data, p),
1867 STR_TERMINATE_ASCII);
1870 SIVAL(p,0,0); /* Ensure any padding is null. */
1871 len = PTR_DIFF(p, pdata);
1872 len = (len + 3) & ~3;
1877 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1878 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1879 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1881 SIVAL(p,0,reskey); p += 4;
1882 put_long_date_timespec(p,create_date_ts); p += 8;
1883 put_long_date_timespec(p,adate_ts); p += 8;
1884 put_long_date_timespec(p,mdate_ts); p += 8;
1885 put_long_date_timespec(p,mdate_ts); p += 8;
1886 SOFF_T(p,0,file_size); p += 8;
1887 SOFF_T(p,0,allocation_size); p += 8;
1888 SIVAL(p,0,nt_extmode); p += 4;
1889 q = p; p += 4; /* q is placeholder for name length */
1891 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1892 SIVAL(p,0,ea_size); /* Extended attributes */
1895 /* Clear the short name buffer. This is
1896 * IMPORTANT as not doing so will trigger
1897 * a Win2k client bug. JRA.
1899 if (!was_8_3 && check_mangled_names) {
1900 if (!name_to_8_3(fname,mangled_name,True,
1902 /* Error - mangle failed ! */
1903 memset(mangled_name,'\0',12);
1905 mangled_name[12] = 0;
1906 len = srvstr_push(base_data, flags2,
1907 p+2, mangled_name, 24,
1908 STR_UPPER|STR_UNICODE);
1911 memset(p + 2 + len,'\0',24 - len);
1918 SSVAL(p,0,0); p += 2; /* Reserved ? */
1919 SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */
1920 SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */
1921 len = srvstr_push(base_data, flags2, p,
1922 fname, PTR_DIFF(end_data, p),
1923 STR_TERMINATE_ASCII);
1926 SIVAL(p,0,0); /* Ensure any padding is null. */
1927 len = PTR_DIFF(p, pdata);
1928 len = (len + 3) & ~3;
1933 /* CIFS UNIX Extension. */
1935 case SMB_FIND_FILE_UNIX:
1936 case SMB_FIND_FILE_UNIX_INFO2:
1938 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1940 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1942 if (info_level == SMB_FIND_FILE_UNIX) {
1943 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1944 p = store_file_unix_basic(conn, p,
1946 len = srvstr_push(base_data, flags2, p,
1947 fname, PTR_DIFF(end_data, p),
1950 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1951 p = store_file_unix_basic_info2(conn, p,
1955 len = srvstr_push(base_data, flags2, p, fname,
1956 PTR_DIFF(end_data, p), 0);
1957 SIVAL(nameptr, 0, len);
1961 SIVAL(p,0,0); /* Ensure any padding is null. */
1963 len = PTR_DIFF(p, pdata);
1964 len = (len + 3) & ~3;
1965 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1967 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1977 if (PTR_DIFF(p,pdata) > space_remaining) {
1978 /* Move the dirptr back to prev_dirpos */
1979 dptr_SeekDir(conn->dirptr, prev_dirpos);
1980 *out_of_space = True;
1981 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1982 return False; /* Not finished - just out of space */
1985 /* Setup the last entry pointer, as an offset from base_data */
1986 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1987 /* Advance the data pointer to the next slot */
1993 /****************************************************************************
1994 Reply to a TRANS2_FINDFIRST.
1995 ****************************************************************************/
1997 static void call_trans2findfirst(connection_struct *conn,
1998 struct smb_request *req,
1999 char **pparams, int total_params,
2000 char **ppdata, int total_data,
2001 unsigned int max_data_bytes)
2003 /* We must be careful here that we don't return more than the
2004 allowed number of data bytes. If this means returning fewer than
2005 maxentries then so be it. We assume that the redirector has
2006 enough room for the fixed number of parameter bytes it has
2008 struct smb_filename *smb_dname = NULL;
2009 char *params = *pparams;
2010 char *pdata = *ppdata;
2014 uint16 findfirst_flags;
2015 bool close_after_first;
2017 bool requires_resume_key;
2019 char *directory = NULL;
2022 int last_entry_off=0;
2026 bool finished = False;
2027 bool dont_descend = False;
2028 bool out_of_space = False;
2029 int space_remaining;
2030 bool mask_contains_wcard = False;
2031 struct ea_list *ea_list = NULL;
2032 NTSTATUS ntstatus = NT_STATUS_OK;
2033 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2034 TALLOC_CTX *ctx = talloc_tos();
2036 if (total_params < 13) {
2037 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2041 dirtype = SVAL(params,0);
2042 maxentries = SVAL(params,2);
2043 findfirst_flags = SVAL(params,4);
2044 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2045 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2046 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2047 info_level = SVAL(params,6);
2049 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2050 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2051 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2052 info_level, max_data_bytes));
2055 /* W2K3 seems to treat zero as 1. */
2059 switch (info_level) {
2060 case SMB_FIND_INFO_STANDARD:
2061 case SMB_FIND_EA_SIZE:
2062 case SMB_FIND_EA_LIST:
2063 case SMB_FIND_FILE_DIRECTORY_INFO:
2064 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2065 case SMB_FIND_FILE_NAMES_INFO:
2066 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2067 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2068 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2070 case SMB_FIND_FILE_UNIX:
2071 case SMB_FIND_FILE_UNIX_INFO2:
2072 /* Always use filesystem for UNIX mtime query. */
2073 ask_sharemode = false;
2074 if (!lp_unix_extensions()) {
2075 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2080 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2084 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2085 params+12, total_params - 12,
2086 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2087 if (!NT_STATUS_IS_OK(ntstatus)) {
2088 reply_nterror(req, ntstatus);
2092 ntstatus = resolve_dfspath_wcard(ctx, conn,
2093 req->flags2 & FLAGS2_DFS_PATHNAMES,
2096 &mask_contains_wcard);
2097 if (!NT_STATUS_IS_OK(ntstatus)) {
2098 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2099 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2100 ERRSRV, ERRbadpath);
2103 reply_nterror(req, ntstatus);
2107 ntstatus = unix_convert(ctx, conn, directory, &smb_dname,
2108 (UCF_SAVE_LCOMP | UCF_ALLOW_WCARD_LCOMP));
2109 if (!NT_STATUS_IS_OK(ntstatus)) {
2110 reply_nterror(req, ntstatus);
2114 mask = smb_dname->original_lcomp;
2116 directory = smb_dname->base_name;
2118 ntstatus = check_name(conn, directory);
2119 if (!NT_STATUS_IS_OK(ntstatus)) {
2120 reply_nterror(req, ntstatus);
2124 p = strrchr_m(directory,'/');
2126 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2127 if((directory[0] == '.') && (directory[1] == '\0')) {
2128 mask = talloc_strdup(ctx,"*");
2130 reply_nterror(req, NT_STATUS_NO_MEMORY);
2133 mask_contains_wcard = True;
2135 directory = talloc_strdup(talloc_tos(), "./");
2137 reply_nterror(req, NT_STATUS_NO_MEMORY);
2144 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2146 if (info_level == SMB_FIND_EA_LIST) {
2149 if (total_data < 4) {
2150 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2154 ea_size = IVAL(pdata,0);
2155 if (ea_size != total_data) {
2156 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2157 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2158 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2162 if (!lp_ea_support(SNUM(conn))) {
2163 reply_doserror(req, ERRDOS, ERReasnotsupported);
2167 /* Pull out the list of names. */
2168 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2170 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2175 *ppdata = (char *)SMB_REALLOC(
2176 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2177 if(*ppdata == NULL ) {
2178 reply_nterror(req, NT_STATUS_NO_MEMORY);
2182 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2184 /* Realloc the params space */
2185 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2186 if (*pparams == NULL) {
2187 reply_nterror(req, NT_STATUS_NO_MEMORY);
2192 /* Save the wildcard match and attribs we are using on this directory -
2193 needed as lanman2 assumes these are being saved between calls */
2195 ntstatus = dptr_create(conn,
2201 mask_contains_wcard,
2205 if (!NT_STATUS_IS_OK(ntstatus)) {
2206 reply_nterror(req, ntstatus);
2210 dptr_num = dptr_dnum(conn->dirptr);
2211 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2213 /* Initialize per TRANS2_FIND_FIRST operation data */
2214 dptr_init_search_op(conn->dirptr);
2216 /* We don't need to check for VOL here as this is returned by
2217 a different TRANS2 call. */
2219 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2220 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2221 dont_descend = True;
2224 space_remaining = max_data_bytes;
2225 out_of_space = False;
2227 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2228 bool got_exact_match = False;
2230 /* this is a heuristic to avoid seeking the dirptr except when
2231 absolutely necessary. It allows for a filename of about 40 chars */
2232 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2233 out_of_space = True;
2236 finished = !get_lanman2_dir_entry(ctx,
2239 mask,dirtype,info_level,
2240 requires_resume_key,dont_descend,
2243 space_remaining, &out_of_space,
2245 &last_entry_off, ea_list);
2248 if (finished && out_of_space)
2251 if (!finished && !out_of_space)
2255 * As an optimisation if we know we aren't looking
2256 * for a wildcard name (ie. the name matches the wildcard exactly)
2257 * then we can finish on any (first) match.
2258 * This speeds up large directory searches. JRA.
2264 /* Ensure space_remaining never goes -ve. */
2265 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2266 space_remaining = 0;
2267 out_of_space = true;
2269 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2273 /* Check if we can close the dirptr */
2274 if(close_after_first || (finished && close_if_end)) {
2275 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2276 dptr_close(&dptr_num);
2280 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2281 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2282 * the protocol level is less than NT1. Tested with smbclient. JRA.
2283 * This should fix the OS/2 client bug #2335.
2286 if(numentries == 0) {
2287 dptr_close(&dptr_num);
2288 if (Protocol < PROTOCOL_NT1) {
2289 reply_doserror(req, ERRDOS, ERRnofiles);
2292 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2293 ERRDOS, ERRbadfile);
2298 /* At this point pdata points to numentries directory entries. */
2300 /* Set up the return parameter block */
2301 SSVAL(params,0,dptr_num);
2302 SSVAL(params,2,numentries);
2303 SSVAL(params,4,finished);
2304 SSVAL(params,6,0); /* Never an EA error */
2305 SSVAL(params,8,last_entry_off);
2307 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2310 if ((! *directory) && dptr_path(dptr_num)) {
2311 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2313 reply_nterror(req, NT_STATUS_NO_MEMORY);
2317 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2318 smb_fn_name(req->cmd),
2319 mask, directory, dirtype, numentries ) );
2322 * Force a name mangle here to ensure that the
2323 * mask as an 8.3 name is top of the mangled cache.
2324 * The reasons for this are subtle. Don't remove
2325 * this code unless you know what you are doing
2326 * (see PR#13758). JRA.
2329 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2330 char mangled_name[13];
2331 name_to_8_3(mask, mangled_name, True, conn->params);
2334 TALLOC_FREE(smb_dname);
2338 /****************************************************************************
2339 Reply to a TRANS2_FINDNEXT.
2340 ****************************************************************************/
2342 static void call_trans2findnext(connection_struct *conn,
2343 struct smb_request *req,
2344 char **pparams, int total_params,
2345 char **ppdata, int total_data,
2346 unsigned int max_data_bytes)
2348 /* We must be careful here that we don't return more than the
2349 allowed number of data bytes. If this means returning fewer than
2350 maxentries then so be it. We assume that the redirector has
2351 enough room for the fixed number of parameter bytes it has
2353 char *params = *pparams;
2354 char *pdata = *ppdata;
2360 uint16 findnext_flags;
2361 bool close_after_request;
2363 bool requires_resume_key;
2365 bool mask_contains_wcard = False;
2366 char *resume_name = NULL;
2367 const char *mask = NULL;
2368 const char *directory = NULL;
2372 int i, last_entry_off=0;
2373 bool finished = False;
2374 bool dont_descend = False;
2375 bool out_of_space = False;
2376 int space_remaining;
2377 struct ea_list *ea_list = NULL;
2378 NTSTATUS ntstatus = NT_STATUS_OK;
2379 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2380 TALLOC_CTX *ctx = talloc_tos();
2382 if (total_params < 13) {
2383 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2387 dptr_num = SVAL(params,0);
2388 maxentries = SVAL(params,2);
2389 info_level = SVAL(params,4);
2390 resume_key = IVAL(params,6);
2391 findnext_flags = SVAL(params,10);
2392 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2393 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2394 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2395 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2397 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2399 total_params - 12, STR_TERMINATE, &ntstatus,
2400 &mask_contains_wcard);
2401 if (!NT_STATUS_IS_OK(ntstatus)) {
2402 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2403 complain (it thinks we're asking for the directory above the shared
2404 path or an invalid name). Catch this as the resume name is only compared, never used in
2405 a file access. JRA. */
2406 srvstr_pull_talloc(ctx, params, req->flags2,
2407 &resume_name, params+12,
2411 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2412 reply_nterror(req, ntstatus);
2417 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2418 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2419 resume_key = %d resume name = %s continue=%d level = %d\n",
2420 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2421 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2424 /* W2K3 seems to treat zero as 1. */
2428 switch (info_level) {
2429 case SMB_FIND_INFO_STANDARD:
2430 case SMB_FIND_EA_SIZE:
2431 case SMB_FIND_EA_LIST:
2432 case SMB_FIND_FILE_DIRECTORY_INFO:
2433 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2434 case SMB_FIND_FILE_NAMES_INFO:
2435 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2436 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2437 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2439 case SMB_FIND_FILE_UNIX:
2440 case SMB_FIND_FILE_UNIX_INFO2:
2441 /* Always use filesystem for UNIX mtime query. */
2442 ask_sharemode = false;
2443 if (!lp_unix_extensions()) {
2444 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2449 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2453 if (info_level == SMB_FIND_EA_LIST) {
2456 if (total_data < 4) {
2457 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2461 ea_size = IVAL(pdata,0);
2462 if (ea_size != total_data) {
2463 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2464 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2465 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2469 if (!lp_ea_support(SNUM(conn))) {
2470 reply_doserror(req, ERRDOS, ERReasnotsupported);
2474 /* Pull out the list of names. */
2475 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2477 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2482 *ppdata = (char *)SMB_REALLOC(
2483 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2484 if(*ppdata == NULL) {
2485 reply_nterror(req, NT_STATUS_NO_MEMORY);
2490 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2492 /* Realloc the params space */
2493 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2494 if(*pparams == NULL ) {
2495 reply_nterror(req, NT_STATUS_NO_MEMORY);
2501 /* Check that the dptr is valid */
2502 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2503 reply_doserror(req, ERRDOS, ERRnofiles);
2507 string_set(&conn->dirpath,dptr_path(dptr_num));
2509 /* Get the wildcard mask from the dptr */
2510 if((p = dptr_wcard(dptr_num))== NULL) {
2511 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2512 reply_doserror(req, ERRDOS, ERRnofiles);
2517 directory = conn->dirpath;
2519 /* Get the attr mask from the dptr */
2520 dirtype = dptr_attr(dptr_num);
2522 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2523 dptr_num, mask, dirtype,
2525 dptr_TellDir(conn->dirptr)));
2527 /* Initialize per TRANS2_FIND_NEXT operation data */
2528 dptr_init_search_op(conn->dirptr);
2530 /* We don't need to check for VOL here as this is returned by
2531 a different TRANS2 call. */
2533 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2534 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2535 dont_descend = True;
2538 space_remaining = max_data_bytes;
2539 out_of_space = False;
2542 * Seek to the correct position. We no longer use the resume key but
2543 * depend on the last file name instead.
2546 if(*resume_name && !continue_bit) {
2549 long current_pos = 0;
2551 * Remember, name_to_8_3 is called by
2552 * get_lanman2_dir_entry(), so the resume name
2553 * could be mangled. Ensure we check the unmangled name.
2556 if (mangle_is_mangled(resume_name, conn->params)) {
2557 char *new_resume_name = NULL;
2558 mangle_lookup_name_from_8_3(ctx,
2562 if (new_resume_name) {
2563 resume_name = new_resume_name;
2568 * Fix for NT redirector problem triggered by resume key indexes
2569 * changing between directory scans. We now return a resume key of 0
2570 * and instead look for the filename to continue from (also given
2571 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2572 * findfirst/findnext (as is usual) then the directory pointer
2573 * should already be at the correct place.
2576 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2577 } /* end if resume_name && !continue_bit */
2579 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2580 bool got_exact_match = False;
2582 /* this is a heuristic to avoid seeking the dirptr except when
2583 absolutely necessary. It allows for a filename of about 40 chars */
2584 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2585 out_of_space = True;
2588 finished = !get_lanman2_dir_entry(ctx,
2591 mask,dirtype,info_level,
2592 requires_resume_key,dont_descend,
2595 space_remaining, &out_of_space,
2597 &last_entry_off, ea_list);
2600 if (finished && out_of_space)
2603 if (!finished && !out_of_space)
2607 * As an optimisation if we know we aren't looking
2608 * for a wildcard name (ie. the name matches the wildcard exactly)
2609 * then we can finish on any (first) match.
2610 * This speeds up large directory searches. JRA.
2616 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2619 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2620 smb_fn_name(req->cmd),
2621 mask, directory, dirtype, numentries ) );
2623 /* Check if we can close the dirptr */
2624 if(close_after_request || (finished && close_if_end)) {
2625 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2626 dptr_close(&dptr_num); /* This frees up the saved mask */
2629 /* Set up the return parameter block */
2630 SSVAL(params,0,numentries);
2631 SSVAL(params,2,finished);
2632 SSVAL(params,4,0); /* Never an EA error */
2633 SSVAL(params,6,last_entry_off);
2635 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2641 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2643 E_md4hash(lp_servicename(SNUM(conn)),objid);
2647 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2649 SMB_ASSERT(extended_info != NULL);
2651 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2652 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2653 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2654 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2655 #ifdef SAMBA_VERSION_REVISION
2656 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2658 extended_info->samba_subversion = 0;
2659 #ifdef SAMBA_VERSION_RC_RELEASE
2660 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2662 #ifdef SAMBA_VERSION_PRE_RELEASE
2663 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2666 #ifdef SAMBA_VERSION_VENDOR_PATCH
2667 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2669 extended_info->samba_gitcommitdate = 0;
2670 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2671 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2674 memset(extended_info->samba_version_string, 0,
2675 sizeof(extended_info->samba_version_string));
2677 snprintf (extended_info->samba_version_string,
2678 sizeof(extended_info->samba_version_string),
2679 "%s", samba_version_string());
2682 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2683 TALLOC_CTX *mem_ctx,
2684 uint16_t info_level,
2686 unsigned int max_data_bytes,
2690 char *pdata, *end_data;
2691 int data_len = 0, len;
2692 const char *vname = volume_label(SNUM(conn));
2693 int snum = SNUM(conn);
2694 char *fstype = lp_fstype(SNUM(conn));
2695 uint32 additional_flags = 0;
2696 struct smb_filename *smb_fname_dot = NULL;
2701 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2702 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2703 "info level (0x%x) on IPC$.\n",
2704 (unsigned int)info_level));
2705 return NT_STATUS_ACCESS_DENIED;
2709 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2711 status = create_synthetic_smb_fname(talloc_tos(), ".", NULL, NULL,
2713 if (!NT_STATUS_IS_OK(status)) {
2717 if(SMB_VFS_STAT(conn, smb_fname_dot) != 0) {
2718 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2719 TALLOC_FREE(smb_fname_dot);
2720 return map_nt_error_from_unix(errno);
2723 st = smb_fname_dot->st;
2724 TALLOC_FREE(smb_fname_dot);
2726 *ppdata = (char *)SMB_REALLOC(
2727 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2728 if (*ppdata == NULL) {
2729 return NT_STATUS_NO_MEMORY;
2733 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2734 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2736 switch (info_level) {
2737 case SMB_INFO_ALLOCATION:
2739 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2741 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2742 return map_nt_error_from_unix(errno);
2745 block_size = lp_block_size(snum);
2746 if (bsize < block_size) {
2747 uint64_t factor = block_size/bsize;
2752 if (bsize > block_size) {
2753 uint64_t factor = bsize/block_size;
2758 bytes_per_sector = 512;
2759 sectors_per_unit = bsize/bytes_per_sector;
2761 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2762 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2763 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2765 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2766 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2767 SIVAL(pdata,l1_cUnit,dsize);
2768 SIVAL(pdata,l1_cUnitAvail,dfree);
2769 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2773 case SMB_INFO_VOLUME:
2774 /* Return volume name */
2776 * Add volume serial number - hash of a combination of
2777 * the called hostname and the service name.
2779 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2781 * Win2k3 and previous mess this up by sending a name length
2782 * one byte short. I believe only older clients (OS/2 Win9x) use
2783 * this call so try fixing this by adding a terminating null to
2784 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2788 pdata+l2_vol_szVolLabel, vname,
2789 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2790 STR_NOALIGN|STR_TERMINATE);
2791 SCVAL(pdata,l2_vol_cch,len);
2792 data_len = l2_vol_szVolLabel + len;
2793 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
2794 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2798 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2799 case SMB_FS_ATTRIBUTE_INFORMATION:
2801 additional_flags = 0;
2802 #if defined(HAVE_SYS_QUOTAS)
2803 additional_flags |= FILE_VOLUME_QUOTAS;
2806 if(lp_nt_acl_support(SNUM(conn))) {
2807 additional_flags |= FILE_PERSISTENT_ACLS;
2810 /* Capabilities are filled in at connection time through STATVFS call */
2811 additional_flags |= conn->fs_capabilities;
2813 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2814 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2815 additional_flags); /* FS ATTRIBUTES */
2817 SIVAL(pdata,4,255); /* Max filename component length */
2818 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2819 and will think we can't do long filenames */
2820 len = srvstr_push(pdata, flags2, pdata+12, fstype,
2821 PTR_DIFF(end_data, pdata+12),
2824 data_len = 12 + len;
2827 case SMB_QUERY_FS_LABEL_INFO:
2828 case SMB_FS_LABEL_INFORMATION:
2829 len = srvstr_push(pdata, flags2, pdata+4, vname,
2830 PTR_DIFF(end_data, pdata+4), 0);
2835 case SMB_QUERY_FS_VOLUME_INFO:
2836 case SMB_FS_VOLUME_INFORMATION:
2839 * Add volume serial number - hash of a combination of
2840 * the called hostname and the service name.
2842 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2843 (str_checksum(get_local_machine_name())<<16));
2845 /* Max label len is 32 characters. */
2846 len = srvstr_push(pdata, flags2, pdata+18, vname,
2847 PTR_DIFF(end_data, pdata+18),
2849 SIVAL(pdata,12,len);
2852 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2853 (int)strlen(vname),vname, lp_servicename(snum)));
2856 case SMB_QUERY_FS_SIZE_INFO:
2857 case SMB_FS_SIZE_INFORMATION:
2859 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2861 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2862 return map_nt_error_from_unix(errno);
2864 block_size = lp_block_size(snum);
2865 if (bsize < block_size) {
2866 uint64_t factor = block_size/bsize;
2871 if (bsize > block_size) {
2872 uint64_t factor = bsize/block_size;
2877 bytes_per_sector = 512;
2878 sectors_per_unit = bsize/bytes_per_sector;
2879 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2880 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2881 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2882 SBIG_UINT(pdata,0,dsize);
2883 SBIG_UINT(pdata,8,dfree);
2884 SIVAL(pdata,16,sectors_per_unit);
2885 SIVAL(pdata,20,bytes_per_sector);
2889 case SMB_FS_FULL_SIZE_INFORMATION:
2891 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2893 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2894 return map_nt_error_from_unix(errno);
2896 block_size = lp_block_size(snum);
2897 if (bsize < block_size) {
2898 uint64_t factor = block_size/bsize;
2903 if (bsize > block_size) {
2904 uint64_t factor = bsize/block_size;
2909 bytes_per_sector = 512;
2910 sectors_per_unit = bsize/bytes_per_sector;
2911 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2912 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2913 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2914 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2915 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2916 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2917 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2918 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2922 case SMB_QUERY_FS_DEVICE_INFO:
2923 case SMB_FS_DEVICE_INFORMATION:
2925 SIVAL(pdata,0,0); /* dev type */
2926 SIVAL(pdata,4,0); /* characteristics */
2929 #ifdef HAVE_SYS_QUOTAS
2930 case SMB_FS_QUOTA_INFORMATION:
2932 * what we have to send --metze:
2934 * Unknown1: 24 NULL bytes
2935 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2936 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2937 * Quota Flags: 2 byte :
2938 * Unknown3: 6 NULL bytes
2942 * details for Quota Flags:
2944 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2945 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2946 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2947 * 0x0001 Enable Quotas: enable quota for this fs
2951 /* we need to fake up a fsp here,
2952 * because its not send in this call
2955 SMB_NTQUOTA_STRUCT quotas;
2958 ZERO_STRUCT(quotas);
2964 if (conn->server_info->utok.uid != sec_initial_uid()) {
2965 DEBUG(0,("set_user_quota: access_denied "
2966 "service [%s] user [%s]\n",
2967 lp_servicename(SNUM(conn)),
2968 conn->server_info->unix_name));
2969 return NT_STATUS_ACCESS_DENIED;
2972 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2973 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2974 return map_nt_error_from_unix(errno);
2979 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
2980 lp_servicename(SNUM(conn))));
2982 /* Unknown1 24 NULL bytes*/
2983 SBIG_UINT(pdata,0,(uint64_t)0);
2984 SBIG_UINT(pdata,8,(uint64_t)0);
2985 SBIG_UINT(pdata,16,(uint64_t)0);
2987 /* Default Soft Quota 8 bytes */
2988 SBIG_UINT(pdata,24,quotas.softlim);
2990 /* Default Hard Quota 8 bytes */
2991 SBIG_UINT(pdata,32,quotas.hardlim);
2993 /* Quota flag 2 bytes */
2994 SSVAL(pdata,40,quotas.qflags);
2996 /* Unknown3 6 NULL bytes */
3002 #endif /* HAVE_SYS_QUOTAS */
3003 case SMB_FS_OBJECTID_INFORMATION:
3005 unsigned char objid[16];
3006 struct smb_extended_info extended_info;
3007 memcpy(pdata,create_volume_objectid(conn, objid),16);
3008 samba_extended_info_version (&extended_info);
3009 SIVAL(pdata,16,extended_info.samba_magic);
3010 SIVAL(pdata,20,extended_info.samba_version);
3011 SIVAL(pdata,24,extended_info.samba_subversion);
3012 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3013 memcpy(pdata+36,extended_info.samba_version_string,28);
3019 * Query the version and capabilities of the CIFS UNIX extensions
3023 case SMB_QUERY_CIFS_UNIX_INFO:
3025 bool large_write = lp_min_receive_file_size() &&
3026 !srv_is_signing_active(smbd_server_conn);
3027 bool large_read = !srv_is_signing_active(smbd_server_conn);
3028 int encrypt_caps = 0;
3030 if (!lp_unix_extensions()) {
3031 return NT_STATUS_INVALID_LEVEL;
3034 switch (conn->encrypt_level) {
3040 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3043 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3044 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3045 large_write = false;
3051 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3052 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3054 /* We have POSIX ACLs, pathname, encryption,
3055 * large read/write, and locking capability. */
3057 SBIG_UINT(pdata,4,((uint64_t)(
3058 CIFS_UNIX_POSIX_ACLS_CAP|
3059 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3060 CIFS_UNIX_FCNTL_LOCKS_CAP|
3061 CIFS_UNIX_EXTATTR_CAP|
3062 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3064 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3066 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3070 case SMB_QUERY_POSIX_FS_INFO:
3073 vfs_statvfs_struct svfs;
3075 if (!lp_unix_extensions()) {
3076 return NT_STATUS_INVALID_LEVEL;
3079 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3083 SIVAL(pdata,0,svfs.OptimalTransferSize);
3084 SIVAL(pdata,4,svfs.BlockSize);
3085 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3086 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3087 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3088 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3089 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3090 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3091 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3093 } else if (rc == EOPNOTSUPP) {
3094 return NT_STATUS_INVALID_LEVEL;
3095 #endif /* EOPNOTSUPP */
3097 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3098 return NT_STATUS_DOS(ERRSRV, ERRerror);
3103 case SMB_QUERY_POSIX_WHOAMI:
3109 if (!lp_unix_extensions()) {
3110 return NT_STATUS_INVALID_LEVEL;
3113 if (max_data_bytes < 40) {
3114 return NT_STATUS_BUFFER_TOO_SMALL;
3117 /* We ARE guest if global_sid_Builtin_Guests is
3118 * in our list of SIDs.
3120 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3121 conn->server_info->ptok)) {
3122 flags |= SMB_WHOAMI_GUEST;
3125 /* We are NOT guest if global_sid_Authenticated_Users
3126 * is in our list of SIDs.
3128 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3129 conn->server_info->ptok)) {
3130 flags &= ~SMB_WHOAMI_GUEST;
3133 /* NOTE: 8 bytes for UID/GID, irrespective of native
3134 * platform size. This matches
3135 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3137 data_len = 4 /* flags */
3144 + 4 /* pad/reserved */
3145 + (conn->server_info->utok.ngroups * 8)
3147 + (conn->server_info->ptok->num_sids *
3151 SIVAL(pdata, 0, flags);
3152 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3154 (uint64_t)conn->server_info->utok.uid);
3155 SBIG_UINT(pdata, 16,
3156 (uint64_t)conn->server_info->utok.gid);
3159 if (data_len >= max_data_bytes) {
3160 /* Potential overflow, skip the GIDs and SIDs. */
3162 SIVAL(pdata, 24, 0); /* num_groups */
3163 SIVAL(pdata, 28, 0); /* num_sids */
3164 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3165 SIVAL(pdata, 36, 0); /* reserved */
3171 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3172 SIVAL(pdata, 28, conn->server_info->num_sids);
3174 /* We walk the SID list twice, but this call is fairly
3175 * infrequent, and I don't expect that it's performance
3176 * sensitive -- jpeach
3178 for (i = 0, sid_bytes = 0;
3179 i < conn->server_info->ptok->num_sids; ++i) {
3180 sid_bytes += ndr_size_dom_sid(
3181 &conn->server_info->ptok->user_sids[i],
3186 /* SID list byte count */
3187 SIVAL(pdata, 32, sid_bytes);
3189 /* 4 bytes pad/reserved - must be zero */
3190 SIVAL(pdata, 36, 0);
3194 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3195 SBIG_UINT(pdata, data_len,
3196 (uint64_t)conn->server_info->utok.groups[i]);
3202 i < conn->server_info->ptok->num_sids; ++i) {
3203 int sid_len = ndr_size_dom_sid(
3204 &conn->server_info->ptok->user_sids[i],
3208 sid_linearize(pdata + data_len, sid_len,
3209 &conn->server_info->ptok->user_sids[i]);
3210 data_len += sid_len;
3216 case SMB_MAC_QUERY_FS_INFO:
3218 * Thursby MAC extension... ONLY on NTFS filesystems
3219 * once we do streams then we don't need this
3221 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3223 SIVAL(pdata,84,0x100); /* Don't support mac... */
3228 return NT_STATUS_INVALID_LEVEL;
3231 *ret_data_len = data_len;
3232 return NT_STATUS_OK;
3235 /****************************************************************************
3236 Reply to a TRANS2_QFSINFO (query filesystem info).
3237 ****************************************************************************/
3239 static void call_trans2qfsinfo(connection_struct *conn,
3240 struct smb_request *req,
3241 char **pparams, int total_params,
3242 char **ppdata, int total_data,
3243 unsigned int max_data_bytes)
3245 char *params = *pparams;
3246 uint16_t info_level;
3250 if (total_params < 2) {
3251 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3255 info_level = SVAL(params,0);
3257 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3258 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3259 DEBUG(0,("call_trans2qfsinfo: encryption required "
3260 "and info level 0x%x sent.\n",
3261 (unsigned int)info_level));
3262 exit_server_cleanly("encryption required "
3268 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3270 status = smbd_do_qfsinfo(conn, req,
3275 if (!NT_STATUS_IS_OK(status)) {
3276 reply_nterror(req, status);
3280 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3283 DEBUG( 4, ( "%s info_level = %d\n",
3284 smb_fn_name(req->cmd), info_level) );
3289 /****************************************************************************
3290 Reply to a TRANS2_SETFSINFO (set filesystem info).
3291 ****************************************************************************/
3293 static void call_trans2setfsinfo(connection_struct *conn,
3294 struct smb_request *req,
3295 char **pparams, int total_params,
3296 char **ppdata, int total_data,
3297 unsigned int max_data_bytes)
3299 char *pdata = *ppdata;
3300 char *params = *pparams;
3303 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3306 if (total_params < 4) {
3307 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3309 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3313 info_level = SVAL(params,2);
3316 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3317 info_level != SMB_SET_CIFS_UNIX_INFO) {
3318 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3319 "info level (0x%x) on IPC$.\n",
3320 (unsigned int)info_level));
3321 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3326 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3327 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3328 DEBUG(0,("call_trans2setfsinfo: encryption required "
3329 "and info level 0x%x sent.\n",
3330 (unsigned int)info_level));
3331 exit_server_cleanly("encryption required "
3337 switch(info_level) {
3338 case SMB_SET_CIFS_UNIX_INFO:
3340 uint16 client_unix_major;
3341 uint16 client_unix_minor;
3342 uint32 client_unix_cap_low;
3343 uint32 client_unix_cap_high;
3345 if (!lp_unix_extensions()) {
3347 NT_STATUS_INVALID_LEVEL);
3351 /* There should be 12 bytes of capabilities set. */
3352 if (total_data < 8) {
3355 NT_STATUS_INVALID_PARAMETER);
3358 client_unix_major = SVAL(pdata,0);
3359 client_unix_minor = SVAL(pdata,2);
3360 client_unix_cap_low = IVAL(pdata,4);
3361 client_unix_cap_high = IVAL(pdata,8);
3362 /* Just print these values for now. */
3363 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3364 cap_low = 0x%x, cap_high = 0x%x\n",
3365 (unsigned int)client_unix_major,
3366 (unsigned int)client_unix_minor,
3367 (unsigned int)client_unix_cap_low,
3368 (unsigned int)client_unix_cap_high ));
3370 /* Here is where we must switch to posix pathname processing... */
3371 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3372 lp_set_posix_pathnames();
3373 mangle_change_to_posix();
3376 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3377 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3378 /* Client that knows how to do posix locks,
3379 * but not posix open/mkdir operations. Set a
3380 * default type for read/write checks. */
3382 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3388 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3391 size_t param_len = 0;
3392 size_t data_len = total_data;
3394 if (!lp_unix_extensions()) {
3397 NT_STATUS_INVALID_LEVEL);
3401 if (lp_smb_encrypt(SNUM(conn)) == false) {
3404 NT_STATUS_NOT_SUPPORTED);
3408 DEBUG( 4,("call_trans2setfsinfo: "
3409 "request transport encryption.\n"));
3411 status = srv_request_encryption_setup(conn,
3412 (unsigned char **)ppdata,
3414 (unsigned char **)pparams,
3417 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3418 !NT_STATUS_IS_OK(status)) {
3419 reply_nterror(req, status);
3423 send_trans2_replies(conn, req,
3430 if (NT_STATUS_IS_OK(status)) {
3431 /* Server-side transport
3432 * encryption is now *on*. */
3433 status = srv_encryption_start(conn);
3434 if (!NT_STATUS_IS_OK(status)) {
3435 exit_server_cleanly(
3436 "Failure in setting "
3437 "up encrypted transport");
3443 case SMB_FS_QUOTA_INFORMATION:
3445 files_struct *fsp = NULL;
3446 SMB_NTQUOTA_STRUCT quotas;
3448 ZERO_STRUCT(quotas);
3451 if ((conn->server_info->utok.uid != sec_initial_uid())
3452 ||!CAN_WRITE(conn)) {
3453 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3454 lp_servicename(SNUM(conn)),
3455 conn->server_info->unix_name));
3456 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3460 /* note: normaly there're 48 bytes,
3461 * but we didn't use the last 6 bytes for now
3464 fsp = file_fsp(req, SVAL(params,0));
3466 if (!check_fsp_ntquota_handle(conn, req,
3468 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3470 req, NT_STATUS_INVALID_HANDLE);
3474 if (total_data < 42) {
3475 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3479 NT_STATUS_INVALID_PARAMETER);
3483 /* unknown_1 24 NULL bytes in pdata*/
3485 /* the soft quotas 8 bytes (uint64_t)*/
3486 quotas.softlim = (uint64_t)IVAL(pdata,24);
3487 #ifdef LARGE_SMB_OFF_T
3488 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3489 #else /* LARGE_SMB_OFF_T */
3490 if ((IVAL(pdata,28) != 0)&&
3491 ((quotas.softlim != 0xFFFFFFFF)||
3492 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3493 /* more than 32 bits? */
3496 NT_STATUS_INVALID_PARAMETER);
3499 #endif /* LARGE_SMB_OFF_T */
3501 /* the hard quotas 8 bytes (uint64_t)*/
3502 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3503 #ifdef LARGE_SMB_OFF_T
3504 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3505 #else /* LARGE_SMB_OFF_T */
3506 if ((IVAL(pdata,36) != 0)&&
3507 ((quotas.hardlim != 0xFFFFFFFF)||
3508 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3509 /* more than 32 bits? */
3512 NT_STATUS_INVALID_PARAMETER);
3515 #endif /* LARGE_SMB_OFF_T */
3517 /* quota_flags 2 bytes **/
3518 quotas.qflags = SVAL(pdata,40);
3520 /* unknown_2 6 NULL bytes follow*/
3522 /* now set the quotas */
3523 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3524 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3525 reply_nterror(req, map_nt_error_from_unix(errno));
3532 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3534 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3540 * sending this reply works fine,
3541 * but I'm not sure it's the same
3542 * like windows do...
3545 reply_outbuf(req, 10, 0);
3548 #if defined(HAVE_POSIX_ACLS)
3549 /****************************************************************************
3550 Utility function to count the number of entries in a POSIX acl.
3551 ****************************************************************************/
3553 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3555 unsigned int ace_count = 0;
3556 int entry_id = SMB_ACL_FIRST_ENTRY;
3557 SMB_ACL_ENTRY_T entry;
3559 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3561 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3562 entry_id = SMB_ACL_NEXT_ENTRY;
3569 /****************************************************************************
3570 Utility function to marshall a POSIX acl into wire format.
3571 ****************************************************************************/
3573 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3575 int entry_id = SMB_ACL_FIRST_ENTRY;
3576 SMB_ACL_ENTRY_T entry;
3578 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3579 SMB_ACL_TAG_T tagtype;
3580 SMB_ACL_PERMSET_T permset;
3581 unsigned char perms = 0;
3582 unsigned int own_grp;
3585 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3586 entry_id = SMB_ACL_NEXT_ENTRY;
3589 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3590 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3594 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3595 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3599 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3600 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3601 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3603 SCVAL(pdata,1,perms);
3606 case SMB_ACL_USER_OBJ:
3607 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3608 own_grp = (unsigned int)pst->st_ex_uid;
3609 SIVAL(pdata,2,own_grp);
3614 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3616 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3619 own_grp = (unsigned int)*puid;
3620 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3621 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3622 SIVAL(pdata,2,own_grp);
3626 case SMB_ACL_GROUP_OBJ:
3627 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3628 own_grp = (unsigned int)pst->st_ex_gid;
3629 SIVAL(pdata,2,own_grp);
3634 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3636 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3639 own_grp = (unsigned int)*pgid;
3640 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3641 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3642 SIVAL(pdata,2,own_grp);
3647 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3648 SIVAL(pdata,2,0xFFFFFFFF);
3649 SIVAL(pdata,6,0xFFFFFFFF);
3652 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3653 SIVAL(pdata,2,0xFFFFFFFF);
3654 SIVAL(pdata,6,0xFFFFFFFF);
3657 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3660 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3667 /****************************************************************************
3668 Store the FILE_UNIX_BASIC info.
3669 ****************************************************************************/
3671 static char *store_file_unix_basic(connection_struct *conn,
3674 const SMB_STRUCT_STAT *psbuf)
3676 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3677 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3679 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3682 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3685 put_long_date_timespec(pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3686 put_long_date_timespec(pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3687 put_long_date_timespec(pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3690 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3694 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3698 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3701 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3705 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3709 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */
3712 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3716 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3723 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3724 * the chflags(2) (or equivalent) flags.
3726 * XXX: this really should be behind the VFS interface. To do this, we would
3727 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3728 * Each VFS module could then implement its own mapping as appropriate for the
3729 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3731 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3735 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3739 { UF_IMMUTABLE, EXT_IMMUTABLE },
3743 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3747 { UF_HIDDEN, EXT_HIDDEN },
3750 /* Do not remove. We need to guarantee that this array has at least one
3751 * entry to build on HP-UX.
3757 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3758 uint32 *smb_fflags, uint32 *smb_fmask)
3762 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3763 *smb_fmask |= info2_flags_map[i].smb_fflag;
3764 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3765 *smb_fflags |= info2_flags_map[i].smb_fflag;
3770 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3771 const uint32 smb_fflags,
3772 const uint32 smb_fmask,
3775 uint32 max_fmask = 0;
3778 *stat_fflags = psbuf->st_ex_flags;
3780 /* For each flags requested in smb_fmask, check the state of the
3781 * corresponding flag in smb_fflags and set or clear the matching
3785 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3786 max_fmask |= info2_flags_map[i].smb_fflag;
3787 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3788 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3789 *stat_fflags |= info2_flags_map[i].stat_fflag;
3791 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3796 /* If smb_fmask is asking to set any bits that are not supported by
3797 * our flag mappings, we should fail.
3799 if ((smb_fmask & max_fmask) != smb_fmask) {
3807 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3808 * of file flags and birth (create) time.
3810 static char *store_file_unix_basic_info2(connection_struct *conn,
3813 const SMB_STRUCT_STAT *psbuf)
3815 uint32 file_flags = 0;
3816 uint32 flags_mask = 0;
3818 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3820 /* Create (birth) time 64 bit */
3821 put_long_date_timespec(pdata, psbuf->st_ex_btime);
3824 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3825 SIVAL(pdata, 0, file_flags); /* flags */
3826 SIVAL(pdata, 4, flags_mask); /* mask */
3832 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3833 const struct stream_struct *streams,
3835 unsigned int max_data_bytes,
3836 unsigned int *data_size)
3839 unsigned int ofs = 0;
3841 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3842 unsigned int next_offset;
3844 smb_ucs2_t *namebuf;
3846 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3847 streams[i].name, &namelen) ||
3850 return NT_STATUS_INVALID_PARAMETER;
3854 * name_buf is now null-terminated, we need to marshall as not
3860 SIVAL(data, ofs+4, namelen);
3861 SOFF_T(data, ofs+8, streams[i].size);
3862 SOFF_T(data, ofs+16, streams[i].alloc_size);
3863 memcpy(data+ofs+24, namebuf, namelen);
3864 TALLOC_FREE(namebuf);
3866 next_offset = ofs + 24 + namelen;
3868 if (i == num_streams-1) {
3869 SIVAL(data, ofs, 0);
3872 unsigned int align = ndr_align_size(next_offset, 8);
3874 memset(data+next_offset, 0, align);
3875 next_offset += align;
3877 SIVAL(data, ofs, next_offset - ofs);
3886 return NT_STATUS_OK;
3889 /****************************************************************************
3890 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3891 ****************************************************************************/
3893 static void call_trans2qpipeinfo(connection_struct *conn,
3894 struct smb_request *req,
3895 unsigned int tran_call,
3896 char **pparams, int total_params,
3897 char **ppdata, int total_data,
3898 unsigned int max_data_bytes)
3900 char *params = *pparams;
3901 char *pdata = *ppdata;
3902 unsigned int data_size = 0;
3903 unsigned int param_size = 2;
3908 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3912 if (total_params < 4) {
3913 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3917 fsp = file_fsp(req, SVAL(params,0));
3918 if (!fsp_is_np(fsp)) {
3919 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3923 info_level = SVAL(params,2);
3925 *pparams = (char *)SMB_REALLOC(*pparams,2);
3926 if (*pparams == NULL) {
3927 reply_nterror(req, NT_STATUS_NO_MEMORY);
3932 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3933 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3934 if (*ppdata == NULL ) {
3935 reply_nterror(req, NT_STATUS_NO_MEMORY);
3940 switch (info_level) {
3941 case SMB_FILE_STANDARD_INFORMATION:
3943 SOFF_T(pdata,0,4096LL);
3950 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3954 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3960 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
3961 TALLOC_CTX *mem_ctx,
3962 uint16_t info_level,
3964 const struct smb_filename *smb_fname,
3965 bool delete_pending,
3966 struct timespec write_time_ts,
3968 struct ea_list *ea_list,
3969 int lock_data_count,
3972 unsigned int max_data_bytes,
3974 unsigned int *pdata_size)
3976 char *pdata = *ppdata;
3977 char *dstart, *dend;
3978 unsigned int data_size;
3979 struct timespec create_time_ts, mtime_ts, atime_ts;
3980 time_t create_time, mtime, atime;
3981 SMB_STRUCT_STAT sbuf;
3989 uint64_t file_size = 0;
3991 uint64_t allocation_size = 0;
3992 uint64_t file_index = 0;
3993 uint32_t access_mask = 0;
3995 sbuf = smb_fname->st;
3997 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3998 return NT_STATUS_INVALID_LEVEL;
4001 status = get_full_smb_filename(mem_ctx, smb_fname, &fname);
4002 if (!NT_STATUS_IS_OK(status)) {
4006 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4007 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4008 info_level, max_data_bytes));
4011 mode = dos_mode_msdfs(conn, smb_fname);
4013 mode = dos_mode(conn, smb_fname);
4016 mode = FILE_ATTRIBUTE_NORMAL;
4018 nlink = sbuf.st_ex_nlink;
4020 if (nlink && (mode&aDIR)) {
4024 if ((nlink > 0) && delete_pending) {
4028 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4029 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4030 if (*ppdata == NULL) {
4031 return NT_STATUS_NO_MEMORY;
4035 dend = dstart + data_size - 1;
4037 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4038 update_stat_ex_mtime(&sbuf, write_time_ts);
4041 create_time_ts = sbuf.st_ex_btime;
4042 mtime_ts = sbuf.st_ex_mtime;
4043 atime_ts = sbuf.st_ex_atime;
4045 if (lp_dos_filetime_resolution(SNUM(conn))) {
4046 dos_filetime_timespec(&create_time_ts);
4047 dos_filetime_timespec(&mtime_ts);
4048 dos_filetime_timespec(&atime_ts);
4051 create_time = convert_timespec_to_time_t(create_time_ts);
4052 mtime = convert_timespec_to_time_t(mtime_ts);
4053 atime = convert_timespec_to_time_t(atime_ts);
4055 p = strrchr_m(smb_fname->base_name,'/');
4057 base_name = smb_fname->base_name;
4061 /* NT expects the name to be in an exact form of the *full*
4062 filename. See the trans2 torture test */
4063 if (ISDOT(base_name)) {
4064 dos_fname = talloc_strdup(mem_ctx, "\\");
4066 return NT_STATUS_NO_MEMORY;
4069 dos_fname = talloc_asprintf(mem_ctx,
4073 return NT_STATUS_NO_MEMORY;
4075 string_replace(dos_fname, '/', '\\');
4078 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &sbuf);
4081 /* Do we have this path open ? */
4083 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4084 fsp1 = file_find_di_first(fileid);
4085 if (fsp1 && fsp1->initial_allocation_size) {
4086 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
4090 if (!(mode & aDIR)) {
4091 file_size = get_file_size_stat(&sbuf);
4095 pos = fsp->fh->position_information;
4099 access_mask = fsp->access_mask;
4101 /* GENERIC_EXECUTE mapping from Windows */
4102 access_mask = 0x12019F;
4105 /* This should be an index number - looks like
4108 I think this causes us to fail the IFSKIT
4109 BasicFileInformationTest. -tpot */
4110 file_index = ((sbuf.st_ex_ino) & UINT32_MAX); /* FileIndexLow */
4111 file_index |= ((uint64_t)((sbuf.st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
4113 switch (info_level) {
4114 case SMB_INFO_STANDARD:
4115 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4117 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4118 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4119 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4120 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4121 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4122 SSVAL(pdata,l1_attrFile,mode);
4125 case SMB_INFO_QUERY_EA_SIZE:
4127 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4128 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4130 srv_put_dos_date2(pdata,0,create_time);
4131 srv_put_dos_date2(pdata,4,atime);
4132 srv_put_dos_date2(pdata,8,mtime); /* write time */
4133 SIVAL(pdata,12,(uint32)file_size);
4134 SIVAL(pdata,16,(uint32)allocation_size);
4135 SSVAL(pdata,20,mode);
4136 SIVAL(pdata,22,ea_size);
4140 case SMB_INFO_IS_NAME_VALID:
4141 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4143 /* os/2 needs this ? really ?*/
4144 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4146 /* This is only reached for qpathinfo */
4150 case SMB_INFO_QUERY_EAS_FROM_LIST:
4152 size_t total_ea_len = 0;
4153 struct ea_list *ea_file_list = NULL;
4155 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4157 ea_file_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
4158 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4160 if (!ea_list || (total_ea_len > data_size)) {
4162 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4166 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4170 case SMB_INFO_QUERY_ALL_EAS:
4172 /* We have data_size bytes to put EA's into. */
4173 size_t total_ea_len = 0;
4175 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4177 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
4178 if (!ea_list || (total_ea_len > data_size)) {
4180 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4184 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4188 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4190 /* We have data_size bytes to put EA's into. */
4191 size_t total_ea_len = 0;
4192 struct ea_list *ea_file_list = NULL;
4194 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4196 /*TODO: add filtering and index handling */
4198 ea_file_list = get_ea_list_from_file(mem_ctx,
4202 if (!ea_file_list) {
4203 return NT_STATUS_NO_EAS_ON_FILE;
4206 status = fill_ea_chained_buffer(mem_ctx,
4210 conn, ea_file_list);
4211 if (!NT_STATUS_IS_OK(status)) {
4217 case SMB_FILE_BASIC_INFORMATION:
4218 case SMB_QUERY_FILE_BASIC_INFO:
4220 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4221 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4222 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4224 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4228 put_long_date_timespec(pdata,create_time_ts);
4229 put_long_date_timespec(pdata+8,atime_ts);
4230 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4231 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4232 SIVAL(pdata,32,mode);
4234 DEBUG(5,("SMB_QFBI - "));
4235 DEBUG(5,("create: %s ", ctime(&create_time)));
4236 DEBUG(5,("access: %s ", ctime(&atime)));
4237 DEBUG(5,("write: %s ", ctime(&mtime)));
4238 DEBUG(5,("change: %s ", ctime(&mtime)));
4239 DEBUG(5,("mode: %x\n", mode));
4242 case SMB_FILE_STANDARD_INFORMATION:
4243 case SMB_QUERY_FILE_STANDARD_INFO:
4245 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4247 SOFF_T(pdata,0,allocation_size);
4248 SOFF_T(pdata,8,file_size);
4249 SIVAL(pdata,16,nlink);
4250 SCVAL(pdata,20,delete_pending?1:0);
4251 SCVAL(pdata,21,(mode&aDIR)?1:0);
4252 SSVAL(pdata,22,0); /* Padding. */
4255 case SMB_FILE_EA_INFORMATION:
4256 case SMB_QUERY_FILE_EA_INFO:
4258 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4259 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4261 SIVAL(pdata,0,ea_size);
4265 /* Get the 8.3 name - used if NT SMB was negotiated. */
4266 case SMB_QUERY_FILE_ALT_NAME_INFO:
4267 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4270 char mangled_name[13];
4271 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4272 if (!name_to_8_3(base_name,mangled_name,
4273 True,conn->params)) {
4274 return NT_STATUS_NO_MEMORY;
4276 len = srvstr_push(dstart, flags2,
4277 pdata+4, mangled_name,
4278 PTR_DIFF(dend, pdata+4),
4280 data_size = 4 + len;
4285 case SMB_QUERY_FILE_NAME_INFO:
4289 this must be *exactly* right for ACLs on mapped drives to work
4291 len = srvstr_push(dstart, flags2,
4293 PTR_DIFF(dend, pdata+4),
4295 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4296 data_size = 4 + len;
4301 case SMB_FILE_ALLOCATION_INFORMATION:
4302 case SMB_QUERY_FILE_ALLOCATION_INFO:
4303 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4305 SOFF_T(pdata,0,allocation_size);
4308 case SMB_FILE_END_OF_FILE_INFORMATION:
4309 case SMB_QUERY_FILE_END_OF_FILEINFO:
4310 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4312 SOFF_T(pdata,0,file_size);
4315 case SMB_QUERY_FILE_ALL_INFO:
4316 case SMB_FILE_ALL_INFORMATION:
4319 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4320 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4321 put_long_date_timespec(pdata,create_time_ts);
4322 put_long_date_timespec(pdata+8,atime_ts);
4323 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4324 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4325 SIVAL(pdata,32,mode);
4326 SIVAL(pdata,36,0); /* padding. */
4328 SOFF_T(pdata,0,allocation_size);
4329 SOFF_T(pdata,8,file_size);
4330 SIVAL(pdata,16,nlink);
4331 SCVAL(pdata,20,delete_pending);
4332 SCVAL(pdata,21,(mode&aDIR)?1:0);
4335 SIVAL(pdata,0,ea_size);
4336 pdata += 4; /* EA info */
4337 len = srvstr_push(dstart, flags2,
4339 PTR_DIFF(dend, pdata+4),
4343 data_size = PTR_DIFF(pdata,(*ppdata));
4347 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4350 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4351 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4352 put_long_date_timespec(pdata+0x00,create_time_ts);
4353 put_long_date_timespec(pdata+0x08,atime_ts);
4354 put_long_date_timespec(pdata+0x10,mtime_ts); /* write time */
4355 put_long_date_timespec(pdata+0x18,mtime_ts); /* change time */
4356 SIVAL(pdata, 0x20, mode);
4357 SIVAL(pdata, 0x24, 0); /* padding. */
4358 SBVAL(pdata, 0x28, allocation_size);
4359 SBVAL(pdata, 0x30, file_size);
4360 SIVAL(pdata, 0x38, nlink);
4361 SCVAL(pdata, 0x3C, delete_pending);
4362 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4363 SSVAL(pdata, 0x3E, 0); /* padding */
4364 SBVAL(pdata, 0x40, file_index);
4365 SIVAL(pdata, 0x48, ea_size);
4366 SIVAL(pdata, 0x4C, access_mask);
4367 SBVAL(pdata, 0x50, pos);
4368 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4369 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4373 len = srvstr_push(dstart, flags2,
4375 PTR_DIFF(dend, pdata+4),
4379 data_size = PTR_DIFF(pdata,(*ppdata));
4382 case SMB_FILE_INTERNAL_INFORMATION:
4384 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4385 SBVAL(pdata, 0, file_index);
4389 case SMB_FILE_ACCESS_INFORMATION:
4390 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4391 SIVAL(pdata, 0, access_mask);
4395 case SMB_FILE_NAME_INFORMATION:
4396 /* Pathname with leading '\'. */
4399 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4400 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4401 SIVAL(pdata,0,byte_len);
4402 data_size = 4 + byte_len;
4406 case SMB_FILE_DISPOSITION_INFORMATION:
4407 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4409 SCVAL(pdata,0,delete_pending);
4412 case SMB_FILE_POSITION_INFORMATION:
4413 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4415 SOFF_T(pdata,0,pos);
4418 case SMB_FILE_MODE_INFORMATION:
4419 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4420 SIVAL(pdata,0,mode);
4424 case SMB_FILE_ALIGNMENT_INFORMATION:
4425 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4426 SIVAL(pdata,0,0); /* No alignment needed. */
4431 * NT4 server just returns "invalid query" to this - if we try
4432 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4435 /* The first statement above is false - verified using Thursby
4436 * client against NT4 -- gcolley.
4438 case SMB_QUERY_FILE_STREAM_INFO:
4439 case SMB_FILE_STREAM_INFORMATION: {
4440 unsigned int num_streams;
4441 struct stream_struct *streams;
4443 DEBUG(10,("smbd_do_qfilepathinfo: "
4444 "SMB_FILE_STREAM_INFORMATION\n"));
4446 status = SMB_VFS_STREAMINFO(
4447 conn, fsp, fname, talloc_tos(),
4448 &num_streams, &streams);
4450 if (!NT_STATUS_IS_OK(status)) {
4451 DEBUG(10, ("could not get stream info: %s\n",
4452 nt_errstr(status)));
4456 status = marshall_stream_info(num_streams, streams,
4457 pdata, max_data_bytes,
4460 if (!NT_STATUS_IS_OK(status)) {
4461 DEBUG(10, ("marshall_stream_info failed: %s\n",
4462 nt_errstr(status)));
4466 TALLOC_FREE(streams);
4470 case SMB_QUERY_COMPRESSION_INFO:
4471 case SMB_FILE_COMPRESSION_INFORMATION:
4472 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4473 SOFF_T(pdata,0,file_size);
4474 SIVAL(pdata,8,0); /* ??? */
4475 SIVAL(pdata,12,0); /* ??? */
4479 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4480 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4481 put_long_date_timespec(pdata,create_time_ts);
4482 put_long_date_timespec(pdata+8,atime_ts);
4483 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4484 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4485 SOFF_T(pdata,32,allocation_size);
4486 SOFF_T(pdata,40,file_size);
4487 SIVAL(pdata,48,mode);
4488 SIVAL(pdata,52,0); /* ??? */
4492 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4493 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4494 SIVAL(pdata,0,mode);
4500 * CIFS UNIX Extensions.
4503 case SMB_QUERY_FILE_UNIX_BASIC:
4505 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4506 data_size = PTR_DIFF(pdata,(*ppdata));
4510 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4512 for (i=0; i<100; i++)
4513 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4519 case SMB_QUERY_FILE_UNIX_INFO2:
4521 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4522 data_size = PTR_DIFF(pdata,(*ppdata));
4526 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4528 for (i=0; i<100; i++)
4529 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4535 case SMB_QUERY_FILE_UNIX_LINK:
4538 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4541 return NT_STATUS_NO_MEMORY;
4544 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4546 if(!S_ISLNK(sbuf.st_ex_mode)) {
4547 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4550 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4552 len = SMB_VFS_READLINK(conn,fname,
4555 return map_nt_error_from_unix(errno);
4558 len = srvstr_push(dstart, flags2,
4560 PTR_DIFF(dend, pdata),
4563 data_size = PTR_DIFF(pdata,(*ppdata));
4568 #if defined(HAVE_POSIX_ACLS)
4569 case SMB_QUERY_POSIX_ACL:
4571 SMB_ACL_T file_acl = NULL;
4572 SMB_ACL_T def_acl = NULL;
4573 uint16 num_file_acls = 0;
4574 uint16 num_def_acls = 0;
4576 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4577 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4579 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4582 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4583 DEBUG(5,("smbd_do_qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4585 return NT_STATUS_NOT_IMPLEMENTED;
4588 if (S_ISDIR(sbuf.st_ex_mode)) {
4589 if (fsp && fsp->is_directory) {
4591 SMB_VFS_SYS_ACL_GET_FILE(
4593 fsp->fsp_name->base_name,
4594 SMB_ACL_TYPE_DEFAULT);
4596 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4598 def_acl = free_empty_sys_acl(conn, def_acl);
4601 num_file_acls = count_acl_entries(conn, file_acl);
4602 num_def_acls = count_acl_entries(conn, def_acl);
4604 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4605 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4607 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4608 SMB_POSIX_ACL_HEADER_SIZE) ));
4610 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4613 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4615 return NT_STATUS_BUFFER_TOO_SMALL;
4618 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4619 SSVAL(pdata,2,num_file_acls);
4620 SSVAL(pdata,4,num_def_acls);
4621 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4623 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4626 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4628 return NT_STATUS_INTERNAL_ERROR;
4630 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4632 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4635 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4637 return NT_STATUS_INTERNAL_ERROR;
4641 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4644 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4646 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4652 case SMB_QUERY_POSIX_LOCK:
4657 enum brl_type lock_type;
4659 /* We need an open file with a real fd for this. */
4660 if (!fsp || fsp->is_directory || fsp->fh->fd == -1) {
4661 return NT_STATUS_INVALID_LEVEL;
4664 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4665 return NT_STATUS_INVALID_PARAMETER;
4668 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4669 case POSIX_LOCK_TYPE_READ:
4670 lock_type = READ_LOCK;
4672 case POSIX_LOCK_TYPE_WRITE:
4673 lock_type = WRITE_LOCK;
4675 case POSIX_LOCK_TYPE_UNLOCK:
4677 /* There's no point in asking for an unlock... */
4678 return NT_STATUS_INVALID_PARAMETER;
4681 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4682 #if defined(HAVE_LONGLONG)
4683 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4684 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4685 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4686 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4687 #else /* HAVE_LONGLONG */
4688 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4689 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4690 #endif /* HAVE_LONGLONG */
4692 status = query_lock(fsp,
4699 if (ERROR_WAS_LOCK_DENIED(status)) {
4700 /* Here we need to report who has it locked... */
4701 data_size = POSIX_LOCK_DATA_SIZE;
4703 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4704 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4705 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4706 #if defined(HAVE_LONGLONG)
4707 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4708 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4709 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4710 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4711 #else /* HAVE_LONGLONG */
4712 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4713 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4714 #endif /* HAVE_LONGLONG */
4716 } else if (NT_STATUS_IS_OK(status)) {
4717 /* For success we just return a copy of what we sent
4718 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4719 data_size = POSIX_LOCK_DATA_SIZE;
4720 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4721 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4729 return NT_STATUS_INVALID_LEVEL;
4732 *pdata_size = data_size;
4733 return NT_STATUS_OK;
4736 /****************************************************************************
4737 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4738 file name or file id).
4739 ****************************************************************************/
4741 static void call_trans2qfilepathinfo(connection_struct *conn,
4742 struct smb_request *req,
4743 unsigned int tran_call,
4744 char **pparams, int total_params,
4745 char **ppdata, int total_data,
4746 unsigned int max_data_bytes)
4748 char *params = *pparams;
4749 char *pdata = *ppdata;
4751 unsigned int data_size = 0;
4752 unsigned int param_size = 2;
4753 struct smb_filename *smb_fname = NULL;
4754 bool delete_pending = False;
4755 struct timespec write_time_ts;
4756 files_struct *fsp = NULL;
4757 struct file_id fileid;
4758 struct ea_list *ea_list = NULL;
4759 int lock_data_count = 0;
4760 char *lock_data = NULL;
4761 bool ms_dfs_link = false;
4762 NTSTATUS status = NT_STATUS_OK;
4765 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4769 ZERO_STRUCT(write_time_ts);
4771 if (tran_call == TRANSACT2_QFILEINFO) {
4772 if (total_params < 4) {
4773 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4778 call_trans2qpipeinfo(conn, req, tran_call,
4779 pparams, total_params,
4785 fsp = file_fsp(req, SVAL(params,0));
4786 info_level = SVAL(params,2);
4788 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
4790 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4791 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4795 /* Initial check for valid fsp ptr. */
4796 if (!check_fsp_open(conn, req, fsp)) {
4800 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
4802 if (!NT_STATUS_IS_OK(status)) {
4803 reply_nterror(req, status);
4807 if(fsp->fake_file_handle) {
4809 * This is actually for the QUOTA_FAKE_FILE --metze
4812 /* We know this name is ok, it's already passed the checks. */
4814 } else if(fsp->is_directory || fsp->fh->fd == -1) {
4816 * This is actually a QFILEINFO on a directory
4817 * handle (returned from an NT SMB). NT5.0 seems
4818 * to do this call. JRA.
4821 if (INFO_LEVEL_IS_UNIX(info_level)) {
4822 /* Always do lstat for UNIX calls. */
4823 if (SMB_VFS_LSTAT(conn, smb_fname)) {
4824 DEBUG(3,("call_trans2qfilepathinfo: "
4825 "SMB_VFS_LSTAT of %s failed "
4827 smb_fname_str_dbg(smb_fname),
4830 map_nt_error_from_unix(errno));
4833 } else if (SMB_VFS_STAT(conn, smb_fname)) {
4834 DEBUG(3,("call_trans2qfilepathinfo: "
4835 "SMB_VFS_STAT of %s failed (%s)\n",
4836 smb_fname_str_dbg(smb_fname),
4839 map_nt_error_from_unix(errno));
4843 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4844 get_file_infos(fileid, &delete_pending, &write_time_ts);
4847 * Original code - this is an open file.
4849 if (!check_fsp(conn, req, fsp)) {
4853 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
4854 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
4855 fsp->fnum, strerror(errno)));
4857 map_nt_error_from_unix(errno));
4860 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4861 get_file_infos(fileid, &delete_pending, &write_time_ts);
4868 if (total_params < 7) {
4869 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4873 info_level = SVAL(params,0);
4875 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
4877 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4878 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4882 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
4884 STR_TERMINATE, &status);
4885 if (!NT_STATUS_IS_OK(status)) {
4886 reply_nterror(req, status);
4890 status = filename_convert(req,
4892 req->flags2 & FLAGS2_DFS_PATHNAMES,
4895 if (!NT_STATUS_IS_OK(status)) {
4896 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4897 reply_botherror(req,
4898 NT_STATUS_PATH_NOT_COVERED,
4899 ERRSRV, ERRbadpath);
4902 reply_nterror(req, status);
4906 /* If this is a stream, check if there is a delete_pending. */
4907 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
4908 && is_ntfs_stream_smb_fname(smb_fname)) {
4909 struct smb_filename *smb_fname_base = NULL;
4911 /* Create an smb_filename with stream_name == NULL. */
4913 create_synthetic_smb_fname(talloc_tos(),
4914 smb_fname->base_name,
4917 if (!NT_STATUS_IS_OK(status)) {
4918 reply_nterror(req, status);
4922 if (INFO_LEVEL_IS_UNIX(info_level)) {
4923 /* Always do lstat for UNIX calls. */
4924 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
4925 DEBUG(3,("call_trans2qfilepathinfo: "
4926 "SMB_VFS_LSTAT of %s failed "
4928 smb_fname_str_dbg(smb_fname_base),
4930 TALLOC_FREE(smb_fname_base);
4932 map_nt_error_from_unix(errno));
4936 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
4937 DEBUG(3,("call_trans2qfilepathinfo: "
4938 "fileinfo of %s failed "
4940 smb_fname_str_dbg(smb_fname_base),
4942 TALLOC_FREE(smb_fname_base);
4944 map_nt_error_from_unix(errno));
4949 fileid = vfs_file_id_from_sbuf(conn,
4950 &smb_fname_base->st);
4951 TALLOC_FREE(smb_fname_base);
4952 get_file_infos(fileid, &delete_pending, NULL);
4953 if (delete_pending) {
4954 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4959 if (INFO_LEVEL_IS_UNIX(info_level)) {
4960 /* Always do lstat for UNIX calls. */
4961 if (SMB_VFS_LSTAT(conn, smb_fname)) {
4962 DEBUG(3,("call_trans2qfilepathinfo: "
4963 "SMB_VFS_LSTAT of %s failed (%s)\n",
4964 smb_fname_str_dbg(smb_fname),
4967 map_nt_error_from_unix(errno));
4971 } else if (!VALID_STAT(smb_fname->st) &&
4972 SMB_VFS_STAT(conn, smb_fname) &&
4973 (info_level != SMB_INFO_IS_NAME_VALID)) {
4974 ms_dfs_link = check_msdfs_link(conn,
4975 smb_fname->base_name,
4979 DEBUG(3,("call_trans2qfilepathinfo: "
4980 "SMB_VFS_STAT of %s failed (%s)\n",
4981 smb_fname_str_dbg(smb_fname),
4984 map_nt_error_from_unix(errno));
4989 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4990 get_file_infos(fileid, &delete_pending, &write_time_ts);
4991 if (delete_pending) {
4992 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4997 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
4998 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
4999 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5001 /* Pull out any data sent here before we realloc. */
5002 switch (info_level) {
5003 case SMB_INFO_QUERY_EAS_FROM_LIST:
5005 /* Pull any EA list from the data portion. */
5008 if (total_data < 4) {
5010 req, NT_STATUS_INVALID_PARAMETER);
5013 ea_size = IVAL(pdata,0);
5015 if (total_data > 0 && ea_size != total_data) {
5016 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5017 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5019 req, NT_STATUS_INVALID_PARAMETER);
5023 if (!lp_ea_support(SNUM(conn))) {
5024 reply_doserror(req, ERRDOS,
5025 ERReasnotsupported);
5029 /* Pull out the list of names. */
5030 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5033 req, NT_STATUS_INVALID_PARAMETER);
5039 case SMB_QUERY_POSIX_LOCK:
5041 if (fsp == NULL || fsp->fh->fd == -1) {
5042 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5046 if (total_data != POSIX_LOCK_DATA_SIZE) {
5048 req, NT_STATUS_INVALID_PARAMETER);
5052 /* Copy the lock range data. */
5053 lock_data = (char *)TALLOC_MEMDUP(
5054 req, pdata, total_data);
5056 reply_nterror(req, NT_STATUS_NO_MEMORY);
5059 lock_data_count = total_data;
5065 *pparams = (char *)SMB_REALLOC(*pparams,2);
5066 if (*pparams == NULL) {
5067 reply_nterror(req, NT_STATUS_NO_MEMORY);
5074 * draft-leach-cifs-v1-spec-02.txt
5075 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5078 * The requested information is placed in the Data portion of the
5079 * transaction response. For the information levels greater than 0x100,
5080 * the transaction response has 1 parameter word which should be
5081 * ignored by the client.
5083 * However Windows only follows this rule for the IS_NAME_VALID call.
5085 switch (info_level) {
5086 case SMB_INFO_IS_NAME_VALID:
5091 if ((info_level & 0xFF00) == 0xFF00) {
5093 * We use levels that start with 0xFF00
5094 * internally to represent SMB2 specific levels
5096 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5100 status = smbd_do_qfilepathinfo(conn, req, info_level,
5102 delete_pending, write_time_ts,
5103 ms_dfs_link, ea_list,
5104 lock_data_count, lock_data,
5105 req->flags2, max_data_bytes,
5106 ppdata, &data_size);
5107 if (!NT_STATUS_IS_OK(status)) {
5108 reply_nterror(req, status);
5112 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5118 /****************************************************************************
5119 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5121 ****************************************************************************/
5123 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5124 connection_struct *conn,
5125 const struct smb_filename *smb_fname_old,
5126 const struct smb_filename *smb_fname_new)
5128 NTSTATUS status = NT_STATUS_OK;
5130 /* source must already exist. */
5131 if (!VALID_STAT(smb_fname_old->st)) {
5132 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5135 /* Disallow if newname already exists. */
5136 if (VALID_STAT(smb_fname_new->st)) {
5137 return NT_STATUS_OBJECT_NAME_COLLISION;
5140 /* No links from a directory. */
5141 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5142 return NT_STATUS_FILE_IS_A_DIRECTORY;
5145 /* Setting a hardlink to/from a stream isn't currently supported. */
5146 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5147 is_ntfs_stream_smb_fname(smb_fname_new)) {
5148 return NT_STATUS_INVALID_PARAMETER;
5151 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5152 smb_fname_old->base_name, smb_fname_new->base_name));
5154 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5155 smb_fname_new->base_name) != 0) {
5156 status = map_nt_error_from_unix(errno);
5157 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5158 nt_errstr(status), smb_fname_old->base_name,
5159 smb_fname_new->base_name));
5164 /****************************************************************************
5165 Deal with setting the time from any of the setfilepathinfo functions.
5166 ****************************************************************************/
5168 NTSTATUS smb_set_file_time(connection_struct *conn,
5170 const struct smb_filename *smb_fname,
5171 struct smb_file_time *ft,
5172 bool setting_write_time)
5174 struct smb_filename *smb_fname_base = NULL;
5176 FILE_NOTIFY_CHANGE_LAST_ACCESS
5177 |FILE_NOTIFY_CHANGE_LAST_WRITE;
5180 if (!VALID_STAT(smb_fname->st)) {
5181 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5184 /* get some defaults (no modifications) if any info is zero or -1. */
5185 if (null_timespec(ft->atime)) {
5186 ft->atime= smb_fname->st.st_ex_atime;
5187 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5190 if (null_timespec(ft->mtime)) {
5191 ft->mtime = smb_fname->st.st_ex_mtime;
5192 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5195 if (!setting_write_time) {
5196 /* ft->mtime comes from change time, not write time. */
5197 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5200 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5201 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5202 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5203 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5204 if (!null_timespec(ft->create_time)) {
5205 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5206 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5210 * Try and set the times of this file if
5211 * they are different from the current values.
5215 struct timespec mts = smb_fname->st.st_ex_mtime;
5216 struct timespec ats = smb_fname->st.st_ex_atime;
5217 if ((timespec_compare(&ft->atime, &ats) == 0) &&
5218 (timespec_compare(&ft->mtime, &mts) == 0)) {
5219 return NT_STATUS_OK;
5223 if (setting_write_time) {
5225 * This was a Windows setfileinfo on an open file.
5226 * NT does this a lot. We also need to
5227 * set the time here, as it can be read by
5228 * FindFirst/FindNext and with the patch for bug #2045
5229 * in smbd/fileio.c it ensures that this timestamp is
5230 * kept sticky even after a write. We save the request
5231 * away and will set it on file close and after a write. JRA.
5234 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5235 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5238 if (fsp->base_fsp) {
5239 set_sticky_write_time_fsp(fsp->base_fsp,
5242 set_sticky_write_time_fsp(fsp, ft->mtime);
5245 set_sticky_write_time_path(
5246 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5251 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5253 /* Always call ntimes on the base, even if a stream was passed in. */
5254 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5255 NULL, &smb_fname->st,
5257 if (!NT_STATUS_IS_OK(status)) {
5261 if(file_ntimes(conn, smb_fname_base, ft)!=0) {
5262 TALLOC_FREE(smb_fname_base);
5263 return map_nt_error_from_unix(errno);
5265 TALLOC_FREE(smb_fname_base);
5267 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5268 smb_fname->base_name);
5269 return NT_STATUS_OK;
5272 /****************************************************************************
5273 Deal with setting the dosmode from any of the setfilepathinfo functions.
5274 ****************************************************************************/
5276 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5277 const struct smb_filename *smb_fname,
5280 struct smb_filename *smb_fname_base = NULL;
5283 if (!VALID_STAT(smb_fname->st)) {
5284 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5287 /* Always operate on the base_name, even if a stream was passed in. */
5288 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5289 NULL, &smb_fname->st,
5291 if (!NT_STATUS_IS_OK(status)) {
5296 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5303 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5305 /* check the mode isn't different, before changing it */
5306 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5307 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5308 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5309 (unsigned int)dosmode));
5311 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5313 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5315 smb_fname_str_dbg(smb_fname_base),
5317 status = map_nt_error_from_unix(errno);
5321 status = NT_STATUS_OK;
5323 TALLOC_FREE(smb_fname_base);
5327 /****************************************************************************
5328 Deal with setting the size from any of the setfilepathinfo functions.
5329 ****************************************************************************/
5331 static NTSTATUS smb_set_file_size(connection_struct *conn,
5332 struct smb_request *req,
5334 const struct smb_filename *smb_fname,
5335 const SMB_STRUCT_STAT *psbuf,
5338 NTSTATUS status = NT_STATUS_OK;
5339 struct smb_filename *smb_fname_tmp = NULL;
5340 files_struct *new_fsp = NULL;
5342 if (!VALID_STAT(*psbuf)) {
5343 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5346 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5348 if (size == get_file_size_stat(psbuf)) {
5349 return NT_STATUS_OK;
5352 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5353 smb_fname_str_dbg(smb_fname), (double)size));
5355 if (fsp && fsp->fh->fd != -1) {
5356 /* Handle based call. */
5357 if (vfs_set_filelen(fsp, size) == -1) {
5358 return map_nt_error_from_unix(errno);
5360 trigger_write_time_update_immediate(fsp);
5361 return NT_STATUS_OK;
5364 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5365 if (!NT_STATUS_IS_OK(status)) {
5369 smb_fname_tmp->st = *psbuf;
5371 status = SMB_VFS_CREATE_FILE(
5374 0, /* root_dir_fid */
5375 smb_fname_tmp, /* fname */
5376 FILE_WRITE_ATTRIBUTES, /* access_mask */
5377 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5379 FILE_OPEN, /* create_disposition*/
5380 0, /* create_options */
5381 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5382 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5383 0, /* allocation_size */
5386 &new_fsp, /* result */
5389 TALLOC_FREE(smb_fname_tmp);
5391 if (!NT_STATUS_IS_OK(status)) {
5392 /* NB. We check for open_was_deferred in the caller. */
5396 if (vfs_set_filelen(new_fsp, size) == -1) {
5397 status = map_nt_error_from_unix(errno);
5398 close_file(req, new_fsp,NORMAL_CLOSE);
5402 trigger_write_time_update_immediate(new_fsp);
5403 close_file(req, new_fsp,NORMAL_CLOSE);
5404 return NT_STATUS_OK;
5407 /****************************************************************************
5408 Deal with SMB_INFO_SET_EA.
5409 ****************************************************************************/
5411 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5415 const struct smb_filename *smb_fname)
5417 struct ea_list *ea_list = NULL;
5418 TALLOC_CTX *ctx = NULL;
5419 NTSTATUS status = NT_STATUS_OK;
5421 if (total_data < 10) {
5423 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5424 length. They seem to have no effect. Bug #3212. JRA */
5426 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5427 /* We're done. We only get EA info in this call. */
5428 return NT_STATUS_OK;
5431 return NT_STATUS_INVALID_PARAMETER;
5434 if (IVAL(pdata,0) > total_data) {
5435 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5436 IVAL(pdata,0), (unsigned int)total_data));
5437 return NT_STATUS_INVALID_PARAMETER;
5441 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5443 return NT_STATUS_INVALID_PARAMETER;
5445 status = set_ea(conn, fsp, smb_fname, ea_list);
5450 /****************************************************************************
5451 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5452 ****************************************************************************/
5454 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5458 const struct smb_filename *smb_fname)
5460 NTSTATUS status = NT_STATUS_OK;
5461 bool delete_on_close;
5464 if (total_data < 1) {
5465 return NT_STATUS_INVALID_PARAMETER;
5469 return NT_STATUS_INVALID_HANDLE;
5472 delete_on_close = (CVAL(pdata,0) ? True : False);
5473 dosmode = dos_mode(conn, smb_fname);
5475 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5476 "delete_on_close = %u\n",
5477 smb_fname_str_dbg(smb_fname),
5478 (unsigned int)dosmode,
5479 (unsigned int)delete_on_close ));
5481 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5483 if (!NT_STATUS_IS_OK(status)) {
5487 /* The set is across all open files on this dev/inode pair. */
5488 if (!set_delete_on_close(fsp, delete_on_close,
5489 &conn->server_info->utok)) {
5490 return NT_STATUS_ACCESS_DENIED;
5492 return NT_STATUS_OK;
5495 /****************************************************************************
5496 Deal with SMB_FILE_POSITION_INFORMATION.
5497 ****************************************************************************/
5499 static NTSTATUS smb_file_position_information(connection_struct *conn,
5504 uint64_t position_information;
5506 if (total_data < 8) {
5507 return NT_STATUS_INVALID_PARAMETER;
5511 /* Ignore on pathname based set. */
5512 return NT_STATUS_OK;
5515 position_information = (uint64_t)IVAL(pdata,0);
5516 #ifdef LARGE_SMB_OFF_T
5517 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5518 #else /* LARGE_SMB_OFF_T */
5519 if (IVAL(pdata,4) != 0) {
5520 /* more than 32 bits? */
5521 return NT_STATUS_INVALID_PARAMETER;
5523 #endif /* LARGE_SMB_OFF_T */
5525 DEBUG(10,("smb_file_position_information: Set file position "
5526 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5527 (double)position_information));
5528 fsp->fh->position_information = position_information;
5529 return NT_STATUS_OK;
5532 /****************************************************************************
5533 Deal with SMB_FILE_MODE_INFORMATION.
5534 ****************************************************************************/
5536 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5542 if (total_data < 4) {
5543 return NT_STATUS_INVALID_PARAMETER;
5545 mode = IVAL(pdata,0);
5546 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5547 return NT_STATUS_INVALID_PARAMETER;
5549 return NT_STATUS_OK;
5552 /****************************************************************************
5553 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5554 ****************************************************************************/
5556 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5557 struct smb_request *req,
5560 const struct smb_filename *smb_fname)
5562 char *link_target = NULL;
5563 const char *newname = smb_fname->base_name;
5564 NTSTATUS status = NT_STATUS_OK;
5565 TALLOC_CTX *ctx = talloc_tos();
5567 /* Set a symbolic link. */
5568 /* Don't allow this if follow links is false. */
5570 if (total_data == 0) {
5571 return NT_STATUS_INVALID_PARAMETER;
5574 if (!lp_symlinks(SNUM(conn))) {
5575 return NT_STATUS_ACCESS_DENIED;
5578 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5579 total_data, STR_TERMINATE);
5582 return NT_STATUS_INVALID_PARAMETER;
5585 /* !widelinks forces the target path to be within the share. */
5586 /* This means we can interpret the target as a pathname. */
5587 if (!lp_widelinks(SNUM(conn))) {
5588 char *rel_name = NULL;
5589 char *last_dirp = NULL;
5591 if (*link_target == '/') {
5592 /* No absolute paths allowed. */
5593 return NT_STATUS_ACCESS_DENIED;
5595 rel_name = talloc_strdup(ctx,newname);
5597 return NT_STATUS_NO_MEMORY;
5599 last_dirp = strrchr_m(rel_name, '/');
5601 last_dirp[1] = '\0';
5603 rel_name = talloc_strdup(ctx,"./");
5605 return NT_STATUS_NO_MEMORY;
5608 rel_name = talloc_asprintf_append(rel_name,
5612 return NT_STATUS_NO_MEMORY;
5615 status = check_name(conn, rel_name);
5616 if (!NT_STATUS_IS_OK(status)) {
5621 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5622 newname, link_target ));
5624 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5625 return map_nt_error_from_unix(errno);
5628 return NT_STATUS_OK;
5631 /****************************************************************************
5632 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5633 ****************************************************************************/
5635 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5636 struct smb_request *req,
5637 const char *pdata, int total_data,
5638 const struct smb_filename *smb_fname_new)
5640 char *oldname = NULL;
5641 struct smb_filename *smb_fname_old = NULL;
5642 TALLOC_CTX *ctx = talloc_tos();
5643 NTSTATUS status = NT_STATUS_OK;
5645 /* Set a hard link. */
5646 if (total_data == 0) {
5647 return NT_STATUS_INVALID_PARAMETER;
5650 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5651 total_data, STR_TERMINATE, &status);
5652 if (!NT_STATUS_IS_OK(status)) {
5656 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5657 smb_fname_str_dbg(smb_fname_new), oldname));
5659 status = filename_convert(ctx,
5661 req->flags2 & FLAGS2_DFS_PATHNAMES,
5664 if (!NT_STATUS_IS_OK(status)) {
5668 return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
5671 /****************************************************************************
5672 Deal with SMB_FILE_RENAME_INFORMATION.
5673 ****************************************************************************/
5675 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5676 struct smb_request *req,
5685 char *newname = NULL;
5686 char *base_name = NULL;
5687 struct smb_filename *smb_fname = NULL;
5688 bool dest_has_wcard = False;
5689 NTSTATUS status = NT_STATUS_OK;
5691 TALLOC_CTX *ctx = talloc_tos();
5693 if (total_data < 13) {
5694 return NT_STATUS_INVALID_PARAMETER;
5697 overwrite = (CVAL(pdata,0) ? True : False);
5698 root_fid = IVAL(pdata,4);
5699 len = IVAL(pdata,8);
5701 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5702 return NT_STATUS_INVALID_PARAMETER;
5705 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5708 if (!NT_STATUS_IS_OK(status)) {
5712 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5715 status = resolve_dfspath_wcard(ctx, conn,
5716 req->flags2 & FLAGS2_DFS_PATHNAMES,
5720 if (!NT_STATUS_IS_OK(status)) {
5724 /* Check the new name has no '/' characters. */
5725 if (strchr_m(newname, '/')) {
5726 return NT_STATUS_NOT_SUPPORTED;
5729 if (fsp && fsp->base_fsp) {
5730 /* newname must be a stream name. */
5731 if (newname[0] != ':') {
5732 return NT_STATUS_NOT_SUPPORTED;
5735 /* Create an smb_fname to call rename_internals_fsp() with. */
5736 status = create_synthetic_smb_fname(talloc_tos(),
5737 fsp->base_fsp->fsp_name->base_name, newname, NULL,
5739 if (!NT_STATUS_IS_OK(status)) {
5744 * Set the original last component, since
5745 * rename_internals_fsp() requires it.
5747 smb_fname->original_lcomp = talloc_strdup(smb_fname, newname);
5748 if (smb_fname->original_lcomp == NULL) {
5749 status = NT_STATUS_NO_MEMORY;
5753 /* Create a char * to call rename_internals() with. */
5754 base_name = talloc_asprintf(ctx, "%s%s",
5755 fsp->base_fsp->fsp_name->base_name,
5758 status = NT_STATUS_NO_MEMORY;
5762 /* newname must *not* be a stream name. */
5763 if (newname[0] == ':') {
5764 return NT_STATUS_NOT_SUPPORTED;
5767 /* Create the base directory. */
5768 base_name = talloc_strdup(ctx, fname);
5770 return NT_STATUS_NO_MEMORY;
5772 p = strrchr_m(base_name, '/');
5776 base_name = talloc_strdup(ctx, "./");
5778 return NT_STATUS_NO_MEMORY;
5781 /* Append the new name. */
5782 base_name = talloc_asprintf_append(base_name,
5786 return NT_STATUS_NO_MEMORY;
5789 status = unix_convert(ctx, conn, base_name, &smb_fname,
5792 /* If an error we expect this to be
5793 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5795 if (!NT_STATUS_IS_OK(status)) {
5796 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5800 /* Create an smb_fname to call rename_internals_fsp() */
5801 status = create_synthetic_smb_fname(talloc_tos(),
5804 if (!NT_STATUS_IS_OK(status)) {
5812 DEBUG(10,("smb_file_rename_information: "
5813 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5814 fsp->fnum, fsp_str_dbg(fsp), base_name));
5815 status = rename_internals_fsp(conn, fsp, smb_fname, 0,
5818 DEBUG(10,("smb_file_rename_information: "
5819 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5821 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5822 overwrite, False, dest_has_wcard,
5823 FILE_WRITE_ATTRIBUTES);
5826 TALLOC_FREE(smb_fname);
5830 /****************************************************************************
5831 Deal with SMB_SET_POSIX_ACL.
5832 ****************************************************************************/
5834 #if defined(HAVE_POSIX_ACLS)
5835 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5839 const struct smb_filename *smb_fname)
5841 uint16 posix_acl_version;
5842 uint16 num_file_acls;
5843 uint16 num_def_acls;
5844 bool valid_file_acls = True;
5845 bool valid_def_acls = True;
5847 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5848 return NT_STATUS_INVALID_PARAMETER;
5850 posix_acl_version = SVAL(pdata,0);
5851 num_file_acls = SVAL(pdata,2);
5852 num_def_acls = SVAL(pdata,4);
5854 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5855 valid_file_acls = False;
5859 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5860 valid_def_acls = False;
5864 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5865 return NT_STATUS_INVALID_PARAMETER;
5868 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5869 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5870 return NT_STATUS_INVALID_PARAMETER;
5873 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5874 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
5875 (unsigned int)num_file_acls,
5876 (unsigned int)num_def_acls));
5878 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
5879 smb_fname->base_name, num_file_acls,
5880 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5881 return map_nt_error_from_unix(errno);
5884 if (valid_def_acls && !set_unix_posix_default_acl(conn,
5885 smb_fname->base_name, &smb_fname->st, num_def_acls,
5886 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5887 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5888 return map_nt_error_from_unix(errno);
5890 return NT_STATUS_OK;
5894 /****************************************************************************
5895 Deal with SMB_SET_POSIX_LOCK.
5896 ****************************************************************************/
5898 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5899 struct smb_request *req,
5907 bool blocking_lock = False;
5908 enum brl_type lock_type;
5910 NTSTATUS status = NT_STATUS_OK;
5912 if (fsp == NULL || fsp->fh->fd == -1) {
5913 return NT_STATUS_INVALID_HANDLE;
5916 if (total_data != POSIX_LOCK_DATA_SIZE) {
5917 return NT_STATUS_INVALID_PARAMETER;
5920 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5921 case POSIX_LOCK_TYPE_READ:
5922 lock_type = READ_LOCK;
5924 case POSIX_LOCK_TYPE_WRITE:
5925 /* Return the right POSIX-mappable error code for files opened read-only. */
5926 if (!fsp->can_write) {
5927 return NT_STATUS_INVALID_HANDLE;
5929 lock_type = WRITE_LOCK;
5931 case POSIX_LOCK_TYPE_UNLOCK:
5932 lock_type = UNLOCK_LOCK;
5935 return NT_STATUS_INVALID_PARAMETER;
5938 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5939 blocking_lock = False;
5940 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5941 blocking_lock = True;
5943 return NT_STATUS_INVALID_PARAMETER;
5946 if (!lp_blocking_locks(SNUM(conn))) {
5947 blocking_lock = False;
5950 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5951 #if defined(HAVE_LONGLONG)
5952 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5953 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5954 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5955 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5956 #else /* HAVE_LONGLONG */
5957 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5958 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5959 #endif /* HAVE_LONGLONG */
5961 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5962 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5964 (unsigned int)lock_type,
5965 (unsigned int)lock_pid,
5969 if (lock_type == UNLOCK_LOCK) {
5970 status = do_unlock(smbd_messaging_context(),
5977 uint32 block_smbpid;
5979 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5991 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5993 * A blocking lock was requested. Package up
5994 * this smb into a queued request and push it
5995 * onto the blocking lock queue.
5997 if(push_blocking_lock_request(br_lck,
6000 -1, /* infinite timeout. */
6008 TALLOC_FREE(br_lck);
6012 TALLOC_FREE(br_lck);
6018 /****************************************************************************
6019 Deal with SMB_INFO_STANDARD.
6020 ****************************************************************************/
6022 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6026 const struct smb_filename *smb_fname)
6028 struct smb_file_time ft;
6031 if (total_data < 12) {
6032 return NT_STATUS_INVALID_PARAMETER;
6036 ft.create_time = interpret_long_date(pdata);
6039 ft.atime = interpret_long_date(pdata + 8);
6042 ft.mtime = interpret_long_date(pdata + 16);
6044 DEBUG(10,("smb_set_info_standard: file %s\n",
6045 smb_fname_str_dbg(smb_fname)));
6047 return smb_set_file_time(conn, fsp, smb_fname, &ft, true);
6050 /****************************************************************************
6051 Deal with SMB_SET_FILE_BASIC_INFO.
6052 ****************************************************************************/
6054 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6058 const struct smb_filename *smb_fname)
6060 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6061 struct timespec write_time;
6062 struct timespec changed_time;
6063 struct smb_file_time ft;
6065 NTSTATUS status = NT_STATUS_OK;
6066 bool setting_write_time = true;
6070 if (total_data < 36) {
6071 return NT_STATUS_INVALID_PARAMETER;
6074 /* Set the attributes */
6075 dosmode = IVAL(pdata,32);
6076 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6077 if (!NT_STATUS_IS_OK(status)) {
6082 ft.atime = interpret_long_date(pdata+8);
6084 write_time = interpret_long_date(pdata+16);
6085 changed_time = interpret_long_date(pdata+24);
6088 ft.mtime = timespec_min(&write_time, &changed_time);
6091 ft.create_time = interpret_long_date(pdata);
6093 if ((timespec_compare(&write_time, &ft.mtime) == 1) &&
6094 !null_timespec(write_time)) {
6095 ft.mtime = write_time;
6098 /* Prefer a defined time to an undefined one. */
6099 if (null_timespec(ft.mtime)) {
6100 if (null_timespec(write_time)) {
6101 ft.mtime = changed_time;
6102 setting_write_time = false;
6104 ft.mtime = write_time;
6108 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6109 smb_fname_str_dbg(smb_fname)));
6111 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6112 setting_write_time);
6115 /****************************************************************************
6116 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6117 ****************************************************************************/
6119 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6120 struct smb_request *req,
6124 struct smb_filename *smb_fname)
6126 uint64_t allocation_size = 0;
6127 NTSTATUS status = NT_STATUS_OK;
6128 files_struct *new_fsp = NULL;
6130 if (!VALID_STAT(smb_fname->st)) {
6131 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6134 if (total_data < 8) {
6135 return NT_STATUS_INVALID_PARAMETER;
6138 allocation_size = (uint64_t)IVAL(pdata,0);
6139 #ifdef LARGE_SMB_OFF_T
6140 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6141 #else /* LARGE_SMB_OFF_T */
6142 if (IVAL(pdata,4) != 0) {
6143 /* more than 32 bits? */
6144 return NT_STATUS_INVALID_PARAMETER;
6146 #endif /* LARGE_SMB_OFF_T */
6148 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6149 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6150 (double)allocation_size));
6152 if (allocation_size) {
6153 allocation_size = smb_roundup(conn, allocation_size);
6156 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6157 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6158 (double)allocation_size));
6160 if (fsp && fsp->fh->fd != -1) {
6161 /* Open file handle. */
6162 /* Only change if needed. */
6163 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6164 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6165 return map_nt_error_from_unix(errno);
6168 /* But always update the time. */
6170 * This is equivalent to a write. Ensure it's seen immediately
6171 * if there are no pending writes.
6173 trigger_write_time_update_immediate(fsp);
6174 return NT_STATUS_OK;
6177 /* Pathname or stat or directory file. */
6178 status = SMB_VFS_CREATE_FILE(
6181 0, /* root_dir_fid */
6182 smb_fname, /* fname */
6183 FILE_WRITE_DATA, /* access_mask */
6184 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6186 FILE_OPEN, /* create_disposition*/
6187 0, /* create_options */
6188 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6189 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6190 0, /* allocation_size */
6193 &new_fsp, /* result */
6196 if (!NT_STATUS_IS_OK(status)) {
6197 /* NB. We check for open_was_deferred in the caller. */
6201 /* Only change if needed. */
6202 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6203 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6204 status = map_nt_error_from_unix(errno);
6205 close_file(req, new_fsp, NORMAL_CLOSE);
6210 /* Changing the allocation size should set the last mod time. */
6212 * This is equivalent to a write. Ensure it's seen immediately
6213 * if there are no pending writes.
6215 trigger_write_time_update_immediate(new_fsp);
6217 close_file(req, new_fsp, NORMAL_CLOSE);
6218 return NT_STATUS_OK;
6221 /****************************************************************************
6222 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6223 ****************************************************************************/
6225 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6226 struct smb_request *req,
6230 const struct smb_filename *smb_fname)
6234 if (total_data < 8) {
6235 return NT_STATUS_INVALID_PARAMETER;
6238 size = IVAL(pdata,0);
6239 #ifdef LARGE_SMB_OFF_T
6240 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6241 #else /* LARGE_SMB_OFF_T */
6242 if (IVAL(pdata,4) != 0) {
6243 /* more than 32 bits? */
6244 return NT_STATUS_INVALID_PARAMETER;
6246 #endif /* LARGE_SMB_OFF_T */
6247 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6248 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6251 return smb_set_file_size(conn, req,
6258 /****************************************************************************
6259 Allow a UNIX info mknod.
6260 ****************************************************************************/
6262 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6265 const struct smb_filename *smb_fname)
6267 uint32 file_type = IVAL(pdata,56);
6268 #if defined(HAVE_MAKEDEV)
6269 uint32 dev_major = IVAL(pdata,60);
6270 uint32 dev_minor = IVAL(pdata,68);
6272 SMB_DEV_T dev = (SMB_DEV_T)0;
6273 uint32 raw_unixmode = IVAL(pdata,84);
6277 if (total_data < 100) {
6278 return NT_STATUS_INVALID_PARAMETER;
6281 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6282 PERM_NEW_FILE, &unixmode);
6283 if (!NT_STATUS_IS_OK(status)) {
6287 #if defined(HAVE_MAKEDEV)
6288 dev = makedev(dev_major, dev_minor);
6291 switch (file_type) {
6292 #if defined(S_IFIFO)
6293 case UNIX_TYPE_FIFO:
6294 unixmode |= S_IFIFO;
6297 #if defined(S_IFSOCK)
6298 case UNIX_TYPE_SOCKET:
6299 unixmode |= S_IFSOCK;
6302 #if defined(S_IFCHR)
6303 case UNIX_TYPE_CHARDEV:
6304 unixmode |= S_IFCHR;
6307 #if defined(S_IFBLK)
6308 case UNIX_TYPE_BLKDEV:
6309 unixmode |= S_IFBLK;
6313 return NT_STATUS_INVALID_PARAMETER;
6316 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6317 "%.0f mode 0%o for file %s\n", (double)dev,
6318 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6320 /* Ok - do the mknod. */
6321 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6322 return map_nt_error_from_unix(errno);
6325 /* If any of the other "set" calls fail we
6326 * don't want to end up with a half-constructed mknod.
6329 if (lp_inherit_perms(SNUM(conn))) {
6331 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6333 return NT_STATUS_NO_MEMORY;
6335 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6337 TALLOC_FREE(parent);
6340 return NT_STATUS_OK;
6343 /****************************************************************************
6344 Deal with SMB_SET_FILE_UNIX_BASIC.
6345 ****************************************************************************/
6347 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6348 struct smb_request *req,
6352 const struct smb_filename *smb_fname)
6354 struct smb_file_time ft;
6355 uint32 raw_unixmode;
6358 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6359 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6360 NTSTATUS status = NT_STATUS_OK;
6361 bool delete_on_fail = False;
6362 enum perm_type ptype;
6363 files_struct *all_fsps = NULL;
6364 bool modify_mtime = true;
6366 SMB_STRUCT_STAT sbuf;
6370 if (total_data < 100) {
6371 return NT_STATUS_INVALID_PARAMETER;
6374 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6375 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6376 size=IVAL(pdata,0); /* first 8 Bytes are size */
6377 #ifdef LARGE_SMB_OFF_T
6378 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6379 #else /* LARGE_SMB_OFF_T */
6380 if (IVAL(pdata,4) != 0) {
6381 /* more than 32 bits? */
6382 return NT_STATUS_INVALID_PARAMETER;
6384 #endif /* LARGE_SMB_OFF_T */
6387 ft.atime = interpret_long_date(pdata+24); /* access_time */
6388 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6389 set_owner = (uid_t)IVAL(pdata,40);
6390 set_grp = (gid_t)IVAL(pdata,48);
6391 raw_unixmode = IVAL(pdata,84);
6393 if (VALID_STAT(smb_fname->st)) {
6394 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6395 ptype = PERM_EXISTING_DIR;
6397 ptype = PERM_EXISTING_FILE;
6400 ptype = PERM_NEW_FILE;
6403 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6405 if (!NT_STATUS_IS_OK(status)) {
6409 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6410 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6411 smb_fname_str_dbg(smb_fname), (double)size,
6412 (unsigned int)set_owner, (unsigned int)set_grp,
6413 (int)raw_unixmode));
6415 sbuf = smb_fname->st;
6417 if (!VALID_STAT(sbuf)) {
6418 struct smb_filename *smb_fname_tmp = NULL;
6420 * The only valid use of this is to create character and block
6421 * devices, and named pipes. This is deprecated (IMHO) and
6422 * a new info level should be used for mknod. JRA.
6425 status = smb_unix_mknod(conn,
6429 if (!NT_STATUS_IS_OK(status)) {
6433 status = copy_smb_filename(talloc_tos(), smb_fname,
6435 if (!NT_STATUS_IS_OK(status)) {
6439 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6440 status = map_nt_error_from_unix(errno);
6441 TALLOC_FREE(smb_fname_tmp);
6442 SMB_VFS_UNLINK(conn, smb_fname);
6446 sbuf = smb_fname_tmp->st;
6447 TALLOC_FREE(smb_fname_tmp);
6449 /* Ensure we don't try and change anything else. */
6450 raw_unixmode = SMB_MODE_NO_CHANGE;
6451 size = get_file_size_stat(&sbuf);
6452 ft.atime = sbuf.st_ex_atime;
6453 ft.mtime = sbuf.st_ex_mtime;
6455 * We continue here as we might want to change the
6458 delete_on_fail = True;
6462 /* Horrible backwards compatibility hack as an old server bug
6463 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6467 size = get_file_size_stat(&sbuf);
6472 * Deal with the UNIX specific mode set.
6475 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6476 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6477 "setting mode 0%o for file %s\n",
6478 (unsigned int)unixmode,
6479 smb_fname_str_dbg(smb_fname)));
6480 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6481 return map_nt_error_from_unix(errno);
6486 * Deal with the UNIX specific uid set.
6489 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6490 (sbuf.st_ex_uid != set_owner)) {
6493 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6494 "changing owner %u for path %s\n",
6495 (unsigned int)set_owner,
6496 smb_fname_str_dbg(smb_fname)));
6498 if (S_ISLNK(sbuf.st_ex_mode)) {
6499 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6500 set_owner, (gid_t)-1);
6502 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6503 set_owner, (gid_t)-1);
6507 status = map_nt_error_from_unix(errno);
6508 if (delete_on_fail) {
6509 SMB_VFS_UNLINK(conn, smb_fname);
6516 * Deal with the UNIX specific gid set.
6519 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6520 (sbuf.st_ex_gid != set_grp)) {
6521 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6522 "changing group %u for file %s\n",
6523 (unsigned int)set_owner,
6524 smb_fname_str_dbg(smb_fname)));
6525 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6527 status = map_nt_error_from_unix(errno);
6528 if (delete_on_fail) {
6529 SMB_VFS_UNLINK(conn, smb_fname);
6535 /* Deal with any size changes. */
6537 status = smb_set_file_size(conn, req,
6542 if (!NT_STATUS_IS_OK(status)) {
6546 /* Deal with any time changes. */
6547 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6548 /* No change, don't cancel anything. */
6552 id = vfs_file_id_from_sbuf(conn, &sbuf);
6553 for(all_fsps = file_find_di_first(id); all_fsps;
6554 all_fsps = file_find_di_next(all_fsps)) {
6556 * We're setting the time explicitly for UNIX.
6557 * Cancel any pending changes over all handles.
6559 all_fsps->update_write_time_on_close = false;
6560 TALLOC_FREE(all_fsps->update_write_time_event);
6564 * Override the "setting_write_time"
6565 * parameter here as it almost does what
6566 * we need. Just remember if we modified
6567 * mtime and send the notify ourselves.
6569 if (null_timespec(ft.mtime)) {
6570 modify_mtime = false;
6573 status = smb_set_file_time(conn,
6579 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6580 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6585 /****************************************************************************
6586 Deal with SMB_SET_FILE_UNIX_INFO2.
6587 ****************************************************************************/
6589 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6590 struct smb_request *req,
6594 const struct smb_filename *smb_fname)
6600 if (total_data < 116) {
6601 return NT_STATUS_INVALID_PARAMETER;
6604 /* Start by setting all the fields that are common between UNIX_BASIC
6607 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6609 if (!NT_STATUS_IS_OK(status)) {
6613 smb_fflags = IVAL(pdata, 108);
6614 smb_fmask = IVAL(pdata, 112);
6616 /* NB: We should only attempt to alter the file flags if the client
6617 * sends a non-zero mask.
6619 if (smb_fmask != 0) {
6620 int stat_fflags = 0;
6622 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6623 smb_fmask, &stat_fflags)) {
6624 /* Client asked to alter a flag we don't understand. */
6625 return NT_STATUS_INVALID_PARAMETER;
6628 if (fsp && fsp->fh->fd != -1) {
6629 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6630 return NT_STATUS_NOT_SUPPORTED;
6632 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
6633 stat_fflags) != 0) {
6634 return map_nt_error_from_unix(errno);
6639 /* XXX: need to add support for changing the create_time here. You
6640 * can do this for paths on Darwin with setattrlist(2). The right way
6641 * to hook this up is probably by extending the VFS utimes interface.
6644 return NT_STATUS_OK;
6647 /****************************************************************************
6648 Create a directory with POSIX semantics.
6649 ****************************************************************************/
6651 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6652 struct smb_request *req,
6655 struct smb_filename *smb_fname,
6656 int *pdata_return_size)
6658 NTSTATUS status = NT_STATUS_OK;
6659 uint32 raw_unixmode = 0;
6660 uint32 mod_unixmode = 0;
6661 mode_t unixmode = (mode_t)0;
6662 files_struct *fsp = NULL;
6663 uint16 info_level_return = 0;
6665 char *pdata = *ppdata;
6667 if (total_data < 18) {
6668 return NT_STATUS_INVALID_PARAMETER;
6671 raw_unixmode = IVAL(pdata,8);
6672 /* Next 4 bytes are not yet defined. */
6674 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6675 PERM_NEW_DIR, &unixmode);
6676 if (!NT_STATUS_IS_OK(status)) {
6680 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6682 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6683 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
6685 status = SMB_VFS_CREATE_FILE(
6688 0, /* root_dir_fid */
6689 smb_fname, /* fname */
6690 FILE_READ_ATTRIBUTES, /* access_mask */
6691 FILE_SHARE_NONE, /* share_access */
6692 FILE_CREATE, /* create_disposition*/
6693 FILE_DIRECTORY_FILE, /* create_options */
6694 mod_unixmode, /* file_attributes */
6695 0, /* oplock_request */
6696 0, /* allocation_size */
6702 if (NT_STATUS_IS_OK(status)) {
6703 close_file(req, fsp, NORMAL_CLOSE);
6706 info_level_return = SVAL(pdata,16);
6708 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6709 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6710 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6711 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6713 *pdata_return_size = 12;
6716 /* Realloc the data size */
6717 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6718 if (*ppdata == NULL) {
6719 *pdata_return_size = 0;
6720 return NT_STATUS_NO_MEMORY;
6724 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6725 SSVAL(pdata,2,0); /* No fnum. */
6726 SIVAL(pdata,4,info); /* Was directory created. */
6728 switch (info_level_return) {
6729 case SMB_QUERY_FILE_UNIX_BASIC:
6730 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6731 SSVAL(pdata,10,0); /* Padding. */
6732 store_file_unix_basic(conn, pdata + 12, fsp,
6735 case SMB_QUERY_FILE_UNIX_INFO2:
6736 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6737 SSVAL(pdata,10,0); /* Padding. */
6738 store_file_unix_basic_info2(conn, pdata + 12, fsp,
6742 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6743 SSVAL(pdata,10,0); /* Padding. */
6750 /****************************************************************************
6751 Open/Create a file with POSIX semantics.
6752 ****************************************************************************/
6754 static NTSTATUS smb_posix_open(connection_struct *conn,
6755 struct smb_request *req,
6758 struct smb_filename *smb_fname,
6759 int *pdata_return_size)
6761 bool extended_oplock_granted = False;
6762 char *pdata = *ppdata;
6764 uint32 wire_open_mode = 0;
6765 uint32 raw_unixmode = 0;
6766 uint32 mod_unixmode = 0;
6767 uint32 create_disp = 0;
6768 uint32 access_mask = 0;
6769 uint32 create_options = 0;
6770 NTSTATUS status = NT_STATUS_OK;
6771 mode_t unixmode = (mode_t)0;
6772 files_struct *fsp = NULL;
6773 int oplock_request = 0;
6775 uint16 info_level_return = 0;
6777 if (total_data < 18) {
6778 return NT_STATUS_INVALID_PARAMETER;
6781 flags = IVAL(pdata,0);
6782 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6783 if (oplock_request) {
6784 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6787 wire_open_mode = IVAL(pdata,4);
6789 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6790 return smb_posix_mkdir(conn, req,
6797 switch (wire_open_mode & SMB_ACCMODE) {
6799 access_mask = FILE_READ_DATA;
6802 access_mask = FILE_WRITE_DATA;
6805 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6808 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6809 (unsigned int)wire_open_mode ));
6810 return NT_STATUS_INVALID_PARAMETER;
6813 wire_open_mode &= ~SMB_ACCMODE;
6815 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6816 create_disp = FILE_CREATE;
6817 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6818 create_disp = FILE_OVERWRITE_IF;
6819 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6820 create_disp = FILE_OPEN_IF;
6821 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6822 create_disp = FILE_OPEN;
6824 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6825 (unsigned int)wire_open_mode ));
6826 return NT_STATUS_INVALID_PARAMETER;
6829 raw_unixmode = IVAL(pdata,8);
6830 /* Next 4 bytes are not yet defined. */
6832 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6833 (VALID_STAT(smb_fname->st) ?
6834 PERM_EXISTING_FILE : PERM_NEW_FILE),
6837 if (!NT_STATUS_IS_OK(status)) {
6841 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6843 if (wire_open_mode & SMB_O_SYNC) {
6844 create_options |= FILE_WRITE_THROUGH;
6846 if (wire_open_mode & SMB_O_APPEND) {
6847 access_mask |= FILE_APPEND_DATA;
6849 if (wire_open_mode & SMB_O_DIRECT) {
6850 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6853 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6854 smb_fname_str_dbg(smb_fname),
6855 (unsigned int)wire_open_mode,
6856 (unsigned int)unixmode ));
6858 status = SMB_VFS_CREATE_FILE(
6861 0, /* root_dir_fid */
6862 smb_fname, /* fname */
6863 access_mask, /* access_mask */
6864 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6866 create_disp, /* create_disposition*/
6867 FILE_NON_DIRECTORY_FILE, /* create_options */
6868 mod_unixmode, /* file_attributes */
6869 oplock_request, /* oplock_request */
6870 0, /* allocation_size */
6876 if (!NT_STATUS_IS_OK(status)) {
6880 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6881 extended_oplock_granted = True;
6884 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6885 extended_oplock_granted = True;
6888 info_level_return = SVAL(pdata,16);
6890 /* Allocate the correct return size. */
6892 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6893 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6894 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6895 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6897 *pdata_return_size = 12;
6900 /* Realloc the data size */
6901 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6902 if (*ppdata == NULL) {
6903 close_file(req, fsp, ERROR_CLOSE);
6904 *pdata_return_size = 0;
6905 return NT_STATUS_NO_MEMORY;
6909 if (extended_oplock_granted) {
6910 if (flags & REQUEST_BATCH_OPLOCK) {
6911 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6913 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6915 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6916 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6918 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6921 SSVAL(pdata,2,fsp->fnum);
6922 SIVAL(pdata,4,info); /* Was file created etc. */
6924 switch (info_level_return) {
6925 case SMB_QUERY_FILE_UNIX_BASIC:
6926 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6927 SSVAL(pdata,10,0); /* padding. */
6928 store_file_unix_basic(conn, pdata + 12, fsp,
6931 case SMB_QUERY_FILE_UNIX_INFO2:
6932 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6933 SSVAL(pdata,10,0); /* padding. */
6934 store_file_unix_basic_info2(conn, pdata + 12, fsp,
6938 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6939 SSVAL(pdata,10,0); /* padding. */
6942 return NT_STATUS_OK;
6945 /****************************************************************************
6946 Delete a file with POSIX semantics.
6947 ****************************************************************************/
6949 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6950 struct smb_request *req,
6953 struct smb_filename *smb_fname)
6955 NTSTATUS status = NT_STATUS_OK;
6956 files_struct *fsp = NULL;
6960 int create_options = 0;
6962 struct share_mode_lock *lck = NULL;
6964 if (total_data < 2) {
6965 return NT_STATUS_INVALID_PARAMETER;
6968 flags = SVAL(pdata,0);
6970 if (!VALID_STAT(smb_fname->st)) {
6971 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6974 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6975 !VALID_STAT_OF_DIR(smb_fname->st)) {
6976 return NT_STATUS_NOT_A_DIRECTORY;
6979 DEBUG(10,("smb_posix_unlink: %s %s\n",
6980 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6981 smb_fname_str_dbg(smb_fname)));
6983 if (VALID_STAT_OF_DIR(smb_fname->st)) {
6984 create_options |= FILE_DIRECTORY_FILE;
6987 status = SMB_VFS_CREATE_FILE(
6990 0, /* root_dir_fid */
6991 smb_fname, /* fname */
6992 DELETE_ACCESS, /* access_mask */
6993 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6995 FILE_OPEN, /* create_disposition*/
6996 create_options, /* create_options */
6997 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
6998 0, /* oplock_request */
6999 0, /* allocation_size */
7005 if (!NT_STATUS_IS_OK(status)) {
7010 * Don't lie to client. If we can't really delete due to
7011 * non-POSIX opens return SHARING_VIOLATION.
7014 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7017 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7018 "lock for file %s\n", fsp_str_dbg(fsp)));
7019 close_file(req, fsp, NORMAL_CLOSE);
7020 return NT_STATUS_INVALID_PARAMETER;
7024 * See if others still have the file open. If this is the case, then
7025 * don't delete. If all opens are POSIX delete we can set the delete
7026 * on close disposition.
7028 for (i=0; i<lck->num_share_modes; i++) {
7029 struct share_mode_entry *e = &lck->share_modes[i];
7030 if (is_valid_share_mode_entry(e)) {
7031 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7034 /* Fail with sharing violation. */
7035 close_file(req, fsp, NORMAL_CLOSE);
7037 return NT_STATUS_SHARING_VIOLATION;
7042 * Set the delete on close.
7044 status = smb_set_file_disposition_info(conn,
7050 if (!NT_STATUS_IS_OK(status)) {
7051 close_file(req, fsp, NORMAL_CLOSE);
7056 return close_file(req, fsp, NORMAL_CLOSE);
7059 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7060 struct smb_request *req,
7061 TALLOC_CTX *mem_ctx,
7062 uint16_t info_level,
7064 struct smb_filename *smb_fname,
7065 char **ppdata, int total_data,
7068 char *pdata = *ppdata;
7070 NTSTATUS status = NT_STATUS_OK;
7071 int data_return_size = 0;
7075 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7076 return NT_STATUS_INVALID_LEVEL;
7079 if (!CAN_WRITE(conn)) {
7080 /* Allow POSIX opens. The open path will deny
7081 * any non-readonly opens. */
7082 if (info_level != SMB_POSIX_PATH_OPEN) {
7083 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7087 status = get_full_smb_filename(mem_ctx, smb_fname, &fname);
7088 if (!NT_STATUS_IS_OK(status)) {
7092 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7093 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7094 fsp ? fsp->fnum : -1, info_level, total_data));
7096 switch (info_level) {
7098 case SMB_INFO_STANDARD:
7100 status = smb_set_info_standard(conn,
7108 case SMB_INFO_SET_EA:
7110 status = smb_info_set_ea(conn,
7118 case SMB_SET_FILE_BASIC_INFO:
7119 case SMB_FILE_BASIC_INFORMATION:
7121 status = smb_set_file_basic_info(conn,
7129 case SMB_FILE_ALLOCATION_INFORMATION:
7130 case SMB_SET_FILE_ALLOCATION_INFO:
7132 status = smb_set_file_allocation_info(conn, req,
7140 case SMB_FILE_END_OF_FILE_INFORMATION:
7141 case SMB_SET_FILE_END_OF_FILE_INFO:
7143 status = smb_set_file_end_of_file_info(conn, req,
7151 case SMB_FILE_DISPOSITION_INFORMATION:
7152 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7155 /* JRA - We used to just ignore this on a path ?
7156 * Shouldn't this be invalid level on a pathname
7159 if (tran_call != TRANSACT2_SETFILEINFO) {
7160 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7163 status = smb_set_file_disposition_info(conn,
7171 case SMB_FILE_POSITION_INFORMATION:
7173 status = smb_file_position_information(conn,
7180 /* From tridge Samba4 :
7181 * MODE_INFORMATION in setfileinfo (I have no
7182 * idea what "mode information" on a file is - it takes a value of 0,
7183 * 2, 4 or 6. What could it be?).
7186 case SMB_FILE_MODE_INFORMATION:
7188 status = smb_file_mode_information(conn,
7195 * CIFS UNIX extensions.
7198 case SMB_SET_FILE_UNIX_BASIC:
7200 status = smb_set_file_unix_basic(conn, req,
7208 case SMB_SET_FILE_UNIX_INFO2:
7210 status = smb_set_file_unix_info2(conn, req,
7218 case SMB_SET_FILE_UNIX_LINK:
7221 /* We must have a pathname for this. */
7222 return NT_STATUS_INVALID_LEVEL;
7224 status = smb_set_file_unix_link(conn, req, pdata,
7225 total_data, smb_fname);
7229 case SMB_SET_FILE_UNIX_HLINK:
7232 /* We must have a pathname for this. */
7233 return NT_STATUS_INVALID_LEVEL;
7235 status = smb_set_file_unix_hlink(conn, req,
7241 case SMB_FILE_RENAME_INFORMATION:
7243 status = smb_file_rename_information(conn, req,
7249 #if defined(HAVE_POSIX_ACLS)
7250 case SMB_SET_POSIX_ACL:
7252 status = smb_set_posix_acl(conn,
7261 case SMB_SET_POSIX_LOCK:
7264 return NT_STATUS_INVALID_LEVEL;
7266 status = smb_set_posix_lock(conn, req,
7267 pdata, total_data, fsp);
7271 case SMB_POSIX_PATH_OPEN:
7274 /* We must have a pathname for this. */
7275 return NT_STATUS_INVALID_LEVEL;
7278 status = smb_posix_open(conn, req,
7286 case SMB_POSIX_PATH_UNLINK:
7289 /* We must have a pathname for this. */
7290 return NT_STATUS_INVALID_LEVEL;
7293 status = smb_posix_unlink(conn, req,
7301 return NT_STATUS_INVALID_LEVEL;
7304 if (!NT_STATUS_IS_OK(status)) {
7308 *ret_data_size = data_return_size;
7309 return NT_STATUS_OK;
7312 /****************************************************************************
7313 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7314 ****************************************************************************/
7316 static void call_trans2setfilepathinfo(connection_struct *conn,
7317 struct smb_request *req,
7318 unsigned int tran_call,
7319 char **pparams, int total_params,
7320 char **ppdata, int total_data,
7321 unsigned int max_data_bytes)
7323 char *params = *pparams;
7324 char *pdata = *ppdata;
7326 struct smb_filename *smb_fname = NULL;
7327 files_struct *fsp = NULL;
7328 NTSTATUS status = NT_STATUS_OK;
7329 int data_return_size = 0;
7332 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7336 if (tran_call == TRANSACT2_SETFILEINFO) {
7337 if (total_params < 4) {
7338 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7342 fsp = file_fsp(req, SVAL(params,0));
7343 /* Basic check for non-null fsp. */
7344 if (!check_fsp_open(conn, req, fsp)) {
7347 info_level = SVAL(params,2);
7349 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7351 if (!NT_STATUS_IS_OK(status)) {
7352 reply_nterror(req, status);
7356 if(fsp->is_directory || fsp->fh->fd == -1) {
7358 * This is actually a SETFILEINFO on a directory
7359 * handle (returned from an NT SMB). NT5.0 seems
7360 * to do this call. JRA.
7362 if (INFO_LEVEL_IS_UNIX(info_level)) {
7363 /* Always do lstat for UNIX calls. */
7364 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7365 DEBUG(3,("call_trans2setfilepathinfo: "
7366 "SMB_VFS_LSTAT of %s failed "
7368 smb_fname_str_dbg(smb_fname),
7370 reply_nterror(req, map_nt_error_from_unix(errno));
7374 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7375 DEBUG(3,("call_trans2setfilepathinfo: "
7376 "fileinfo of %s failed (%s)\n",
7377 smb_fname_str_dbg(smb_fname),
7379 reply_nterror(req, map_nt_error_from_unix(errno));
7383 } else if (fsp->print_file) {
7385 * Doing a DELETE_ON_CLOSE should cancel a print job.
7387 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7388 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
7390 DEBUG(3,("call_trans2setfilepathinfo: "
7391 "Cancelling print job (%s)\n",
7395 send_trans2_replies(conn, req, params, 2,
7400 reply_doserror(req, ERRDOS, ERRbadpath);
7405 * Original code - this is an open file.
7407 if (!check_fsp(conn, req, fsp)) {
7411 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7412 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7413 "of fnum %d failed (%s)\n", fsp->fnum,
7415 reply_nterror(req, map_nt_error_from_unix(errno));
7423 if (total_params < 7) {
7424 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7428 info_level = SVAL(params,0);
7429 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
7430 total_params - 6, STR_TERMINATE,
7432 if (!NT_STATUS_IS_OK(status)) {
7433 reply_nterror(req, status);
7437 status = filename_convert(req, conn,
7438 req->flags2 & FLAGS2_DFS_PATHNAMES,
7441 if (!NT_STATUS_IS_OK(status)) {
7442 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7443 reply_botherror(req,
7444 NT_STATUS_PATH_NOT_COVERED,
7445 ERRSRV, ERRbadpath);
7448 reply_nterror(req, status);
7452 if (INFO_LEVEL_IS_UNIX(info_level)) {
7454 * For CIFS UNIX extensions the target name may not exist.
7457 /* Always do lstat for UNIX calls. */
7458 SMB_VFS_LSTAT(conn, smb_fname);
7460 } else if (!VALID_STAT(smb_fname->st) &&
7461 SMB_VFS_STAT(conn, smb_fname)) {
7462 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7464 smb_fname_str_dbg(smb_fname),
7466 reply_nterror(req, map_nt_error_from_unix(errno));
7471 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7472 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
7473 fsp ? fsp->fnum : -1, info_level,total_data));
7475 /* Realloc the parameter size */
7476 *pparams = (char *)SMB_REALLOC(*pparams,2);
7477 if (*pparams == NULL) {
7478 reply_nterror(req, NT_STATUS_NO_MEMORY);
7485 status = smbd_do_setfilepathinfo(conn, req, req,
7491 if (!NT_STATUS_IS_OK(status)) {
7492 if (open_was_deferred(req->mid)) {
7493 /* We have re-scheduled this call. */
7496 if (blocking_lock_was_deferred(req->mid)) {
7497 /* We have re-scheduled this call. */
7500 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7501 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7502 ERRSRV, ERRbadpath);
7505 if (info_level == SMB_POSIX_PATH_OPEN) {
7506 reply_openerror(req, status);
7510 reply_nterror(req, status);
7514 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7520 /****************************************************************************
7521 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7522 ****************************************************************************/
7524 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7525 char **pparams, int total_params,
7526 char **ppdata, int total_data,
7527 unsigned int max_data_bytes)
7529 struct smb_filename *smb_dname = NULL;
7530 char *params = *pparams;
7531 char *pdata = *ppdata;
7532 char *directory = NULL;
7533 NTSTATUS status = NT_STATUS_OK;
7534 struct ea_list *ea_list = NULL;
7535 TALLOC_CTX *ctx = talloc_tos();
7537 if (!CAN_WRITE(conn)) {
7538 reply_doserror(req, ERRSRV, ERRaccess);
7542 if (total_params < 5) {
7543 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7547 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7548 total_params - 4, STR_TERMINATE,
7550 if (!NT_STATUS_IS_OK(status)) {
7551 reply_nterror(req, status);
7555 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7557 status = filename_convert(ctx,
7559 req->flags2 & FLAGS2_DFS_PATHNAMES,
7563 if (!NT_STATUS_IS_OK(status)) {
7564 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7565 reply_botherror(req,
7566 NT_STATUS_PATH_NOT_COVERED,
7567 ERRSRV, ERRbadpath);
7570 reply_nterror(req, status);
7574 /* Any data in this call is an EA list. */
7575 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7576 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7581 * OS/2 workplace shell seems to send SET_EA requests of "null"
7582 * length (4 bytes containing IVAL 4).
7583 * They seem to have no effect. Bug #3212. JRA.
7586 if (total_data != 4) {
7587 if (total_data < 10) {
7588 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7592 if (IVAL(pdata,0) > total_data) {
7593 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7594 IVAL(pdata,0), (unsigned int)total_data));
7595 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7599 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7602 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7606 /* If total_data == 4 Windows doesn't care what values
7607 * are placed in that field, it just ignores them.
7608 * The System i QNTC IBM SMB client puts bad values here,
7609 * so ignore them. */
7611 status = create_directory(conn, req, smb_dname);
7613 if (!NT_STATUS_IS_OK(status)) {
7614 reply_nterror(req, status);
7618 /* Try and set any given EA. */
7620 status = set_ea(conn, NULL, smb_dname, ea_list);
7621 if (!NT_STATUS_IS_OK(status)) {
7622 reply_nterror(req, status);
7627 /* Realloc the parameter and data sizes */
7628 *pparams = (char *)SMB_REALLOC(*pparams,2);
7629 if(*pparams == NULL) {
7630 reply_nterror(req, NT_STATUS_NO_MEMORY);
7637 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7640 TALLOC_FREE(smb_dname);
7644 /****************************************************************************
7645 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7646 We don't actually do this - we just send a null response.
7647 ****************************************************************************/
7649 static void call_trans2findnotifyfirst(connection_struct *conn,
7650 struct smb_request *req,
7651 char **pparams, int total_params,
7652 char **ppdata, int total_data,
7653 unsigned int max_data_bytes)
7655 char *params = *pparams;
7658 if (total_params < 6) {
7659 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7663 info_level = SVAL(params,4);
7664 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7666 switch (info_level) {
7671 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7675 /* Realloc the parameter and data sizes */
7676 *pparams = (char *)SMB_REALLOC(*pparams,6);
7677 if (*pparams == NULL) {
7678 reply_nterror(req, NT_STATUS_NO_MEMORY);
7683 SSVAL(params,0,fnf_handle);
7684 SSVAL(params,2,0); /* No changes */
7685 SSVAL(params,4,0); /* No EA errors */
7692 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7697 /****************************************************************************
7698 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7699 changes). Currently this does nothing.
7700 ****************************************************************************/
7702 static void call_trans2findnotifynext(connection_struct *conn,
7703 struct smb_request *req,
7704 char **pparams, int total_params,
7705 char **ppdata, int total_data,
7706 unsigned int max_data_bytes)
7708 char *params = *pparams;
7710 DEBUG(3,("call_trans2findnotifynext\n"));
7712 /* Realloc the parameter and data sizes */
7713 *pparams = (char *)SMB_REALLOC(*pparams,4);
7714 if (*pparams == NULL) {
7715 reply_nterror(req, NT_STATUS_NO_MEMORY);
7720 SSVAL(params,0,0); /* No changes */
7721 SSVAL(params,2,0); /* No EA errors */
7723 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7728 /****************************************************************************
7729 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7730 ****************************************************************************/
7732 static void call_trans2getdfsreferral(connection_struct *conn,
7733 struct smb_request *req,
7734 char **pparams, int total_params,
7735 char **ppdata, int total_data,
7736 unsigned int max_data_bytes)
7738 char *params = *pparams;
7739 char *pathname = NULL;
7741 int max_referral_level;
7742 NTSTATUS status = NT_STATUS_OK;
7743 TALLOC_CTX *ctx = talloc_tos();
7745 DEBUG(10,("call_trans2getdfsreferral\n"));
7747 if (total_params < 3) {
7748 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7752 max_referral_level = SVAL(params,0);
7754 if(!lp_host_msdfs()) {
7755 reply_doserror(req, ERRDOS, ERRbadfunc);
7759 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7760 total_params - 2, STR_TERMINATE);
7762 reply_nterror(req, NT_STATUS_NOT_FOUND);
7765 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7766 ppdata,&status)) < 0) {
7767 reply_nterror(req, status);
7771 SSVAL(req->inbuf, smb_flg2,
7772 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7773 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7778 #define LMCAT_SPL 0x53
7779 #define LMFUNC_GETJOBID 0x60
7781 /****************************************************************************
7782 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7783 ****************************************************************************/
7785 static void call_trans2ioctl(connection_struct *conn,
7786 struct smb_request *req,
7787 char **pparams, int total_params,
7788 char **ppdata, int total_data,
7789 unsigned int max_data_bytes)
7791 char *pdata = *ppdata;
7792 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7794 /* check for an invalid fid before proceeding */
7797 reply_doserror(req, ERRDOS, ERRbadfid);
7801 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7802 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7803 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7804 if (*ppdata == NULL) {
7805 reply_nterror(req, NT_STATUS_NO_MEMORY);
7810 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7811 CAN ACCEPT THIS IN UNICODE. JRA. */
7813 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7814 srvstr_push(pdata, req->flags2, pdata + 2,
7815 global_myname(), 15,
7816 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7817 srvstr_push(pdata, req->flags2, pdata+18,
7818 lp_servicename(SNUM(conn)), 13,
7819 STR_ASCII|STR_TERMINATE); /* Service name */
7820 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7825 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7826 reply_doserror(req, ERRSRV, ERRerror);
7829 /****************************************************************************
7830 Reply to a SMBfindclose (stop trans2 directory search).
7831 ****************************************************************************/
7833 void reply_findclose(struct smb_request *req)
7837 START_PROFILE(SMBfindclose);
7840 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7841 END_PROFILE(SMBfindclose);
7845 dptr_num = SVALS(req->vwv+0, 0);
7847 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7849 dptr_close(&dptr_num);
7851 reply_outbuf(req, 0, 0);
7853 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7855 END_PROFILE(SMBfindclose);
7859 /****************************************************************************
7860 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7861 ****************************************************************************/
7863 void reply_findnclose(struct smb_request *req)
7867 START_PROFILE(SMBfindnclose);
7870 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7871 END_PROFILE(SMBfindnclose);
7875 dptr_num = SVAL(req->vwv+0, 0);
7877 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7879 /* We never give out valid handles for a
7880 findnotifyfirst - so any dptr_num is ok here.
7883 reply_outbuf(req, 0, 0);
7885 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7887 END_PROFILE(SMBfindnclose);
7891 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7892 struct trans_state *state)
7894 if (Protocol >= PROTOCOL_NT1) {
7895 req->flags2 |= 0x40; /* IS_LONG_NAME */
7896 SSVAL(req->inbuf,smb_flg2,req->flags2);
7899 if (conn->encrypt_level == Required && !req->encrypted) {
7900 if (state->call != TRANSACT2_QFSINFO &&
7901 state->call != TRANSACT2_SETFSINFO) {
7902 DEBUG(0,("handle_trans2: encryption required "
7904 (unsigned int)state->call));
7905 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7910 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
7912 /* Now we must call the relevant TRANS2 function */
7913 switch(state->call) {
7914 case TRANSACT2_OPEN:
7916 START_PROFILE(Trans2_open);
7917 call_trans2open(conn, req,
7918 &state->param, state->total_param,
7919 &state->data, state->total_data,
7920 state->max_data_return);
7921 END_PROFILE(Trans2_open);
7925 case TRANSACT2_FINDFIRST:
7927 START_PROFILE(Trans2_findfirst);
7928 call_trans2findfirst(conn, req,
7929 &state->param, state->total_param,
7930 &state->data, state->total_data,
7931 state->max_data_return);
7932 END_PROFILE(Trans2_findfirst);
7936 case TRANSACT2_FINDNEXT:
7938 START_PROFILE(Trans2_findnext);
7939 call_trans2findnext(conn, req,
7940 &state->param, state->total_param,
7941 &state->data, state->total_data,
7942 state->max_data_return);
7943 END_PROFILE(Trans2_findnext);
7947 case TRANSACT2_QFSINFO:
7949 START_PROFILE(Trans2_qfsinfo);
7950 call_trans2qfsinfo(conn, req,
7951 &state->param, state->total_param,
7952 &state->data, state->total_data,
7953 state->max_data_return);
7954 END_PROFILE(Trans2_qfsinfo);
7958 case TRANSACT2_SETFSINFO:
7960 START_PROFILE(Trans2_setfsinfo);
7961 call_trans2setfsinfo(conn, req,
7962 &state->param, state->total_param,
7963 &state->data, state->total_data,
7964 state->max_data_return);
7965 END_PROFILE(Trans2_setfsinfo);
7969 case TRANSACT2_QPATHINFO:
7970 case TRANSACT2_QFILEINFO:
7972 START_PROFILE(Trans2_qpathinfo);
7973 call_trans2qfilepathinfo(conn, req, state->call,
7974 &state->param, state->total_param,
7975 &state->data, state->total_data,
7976 state->max_data_return);
7977 END_PROFILE(Trans2_qpathinfo);
7981 case TRANSACT2_SETPATHINFO:
7982 case TRANSACT2_SETFILEINFO:
7984 START_PROFILE(Trans2_setpathinfo);
7985 call_trans2setfilepathinfo(conn, req, state->call,
7986 &state->param, state->total_param,
7987 &state->data, state->total_data,
7988 state->max_data_return);
7989 END_PROFILE(Trans2_setpathinfo);
7993 case TRANSACT2_FINDNOTIFYFIRST:
7995 START_PROFILE(Trans2_findnotifyfirst);
7996 call_trans2findnotifyfirst(conn, req,
7997 &state->param, state->total_param,
7998 &state->data, state->total_data,
7999 state->max_data_return);
8000 END_PROFILE(Trans2_findnotifyfirst);
8004 case TRANSACT2_FINDNOTIFYNEXT:
8006 START_PROFILE(Trans2_findnotifynext);
8007 call_trans2findnotifynext(conn, req,
8008 &state->param, state->total_param,
8009 &state->data, state->total_data,
8010 state->max_data_return);
8011 END_PROFILE(Trans2_findnotifynext);
8015 case TRANSACT2_MKDIR:
8017 START_PROFILE(Trans2_mkdir);
8018 call_trans2mkdir(conn, req,
8019 &state->param, state->total_param,
8020 &state->data, state->total_data,
8021 state->max_data_return);
8022 END_PROFILE(Trans2_mkdir);
8026 case TRANSACT2_GET_DFS_REFERRAL:
8028 START_PROFILE(Trans2_get_dfs_referral);
8029 call_trans2getdfsreferral(conn, req,
8030 &state->param, state->total_param,
8031 &state->data, state->total_data,
8032 state->max_data_return);
8033 END_PROFILE(Trans2_get_dfs_referral);
8037 case TRANSACT2_IOCTL:
8039 START_PROFILE(Trans2_ioctl);
8040 call_trans2ioctl(conn, req,
8041 &state->param, state->total_param,
8042 &state->data, state->total_data,
8043 state->max_data_return);
8044 END_PROFILE(Trans2_ioctl);
8049 /* Error in request */
8050 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8051 reply_doserror(req, ERRSRV,ERRerror);
8055 /****************************************************************************
8056 Reply to a SMBtrans2.
8057 ****************************************************************************/
8059 void reply_trans2(struct smb_request *req)
8061 connection_struct *conn = req->conn;
8066 unsigned int tran_call;
8067 struct trans_state *state;
8070 START_PROFILE(SMBtrans2);
8072 if (req->wct < 14) {
8073 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8074 END_PROFILE(SMBtrans2);
8078 dsoff = SVAL(req->vwv+12, 0);
8079 dscnt = SVAL(req->vwv+11, 0);
8080 psoff = SVAL(req->vwv+10, 0);
8081 pscnt = SVAL(req->vwv+9, 0);
8082 tran_call = SVAL(req->vwv+14, 0);
8084 result = allow_new_trans(conn->pending_trans, req->mid);
8085 if (!NT_STATUS_IS_OK(result)) {
8086 DEBUG(2, ("Got invalid trans2 request: %s\n",
8087 nt_errstr(result)));
8088 reply_nterror(req, result);
8089 END_PROFILE(SMBtrans2);
8094 switch (tran_call) {
8095 /* List the allowed trans2 calls on IPC$ */
8096 case TRANSACT2_OPEN:
8097 case TRANSACT2_GET_DFS_REFERRAL:
8098 case TRANSACT2_QFILEINFO:
8099 case TRANSACT2_QFSINFO:
8100 case TRANSACT2_SETFSINFO:
8103 reply_doserror(req, ERRSRV, ERRaccess);
8104 END_PROFILE(SMBtrans2);
8109 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8110 DEBUG(0, ("talloc failed\n"));
8111 reply_nterror(req, NT_STATUS_NO_MEMORY);
8112 END_PROFILE(SMBtrans2);
8116 state->cmd = SMBtrans2;
8118 state->mid = req->mid;
8119 state->vuid = req->vuid;
8120 state->setup_count = SVAL(req->vwv+13, 0);
8121 state->setup = NULL;
8122 state->total_param = SVAL(req->vwv+0, 0);
8123 state->param = NULL;
8124 state->total_data = SVAL(req->vwv+1, 0);
8126 state->max_param_return = SVAL(req->vwv+2, 0);
8127 state->max_data_return = SVAL(req->vwv+3, 0);
8128 state->max_setup_return = SVAL(req->vwv+4, 0);
8129 state->close_on_completion = BITSETW(req->vwv+5, 0);
8130 state->one_way = BITSETW(req->vwv+5, 1);
8132 state->call = tran_call;
8134 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8135 is so as a sanity check */
8136 if (state->setup_count != 1) {
8138 * Need to have rc=0 for ioctl to get job id for OS/2.
8139 * Network printing will fail if function is not successful.
8140 * Similar function in reply.c will be used if protocol
8141 * is LANMAN1.0 instead of LM1.2X002.
8142 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8143 * outbuf doesn't have to be set(only job id is used).
8145 if ( (state->setup_count == 4)
8146 && (tran_call == TRANSACT2_IOCTL)
8147 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8148 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8149 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8151 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8152 DEBUG(2,("Transaction is %d\n",tran_call));
8154 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8155 END_PROFILE(SMBtrans2);
8160 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8163 if (state->total_data) {
8165 if (trans_oob(state->total_data, 0, dscnt)
8166 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8170 /* Can't use talloc here, the core routines do realloc on the
8171 * params and data. */
8172 state->data = (char *)SMB_MALLOC(state->total_data);
8173 if (state->data == NULL) {
8174 DEBUG(0,("reply_trans2: data malloc fail for %u "
8175 "bytes !\n", (unsigned int)state->total_data));
8177 reply_nterror(req, NT_STATUS_NO_MEMORY);
8178 END_PROFILE(SMBtrans2);
8182 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8185 if (state->total_param) {
8187 if (trans_oob(state->total_param, 0, pscnt)
8188 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8192 /* Can't use talloc here, the core routines do realloc on the
8193 * params and data. */
8194 state->param = (char *)SMB_MALLOC(state->total_param);
8195 if (state->param == NULL) {
8196 DEBUG(0,("reply_trans: param malloc fail for %u "
8197 "bytes !\n", (unsigned int)state->total_param));
8198 SAFE_FREE(state->data);
8200 reply_nterror(req, NT_STATUS_NO_MEMORY);
8201 END_PROFILE(SMBtrans2);
8205 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8208 state->received_data = dscnt;
8209 state->received_param = pscnt;
8211 if ((state->received_param == state->total_param) &&
8212 (state->received_data == state->total_data)) {
8214 handle_trans2(conn, req, state);
8216 SAFE_FREE(state->data);
8217 SAFE_FREE(state->param);
8219 END_PROFILE(SMBtrans2);
8223 DLIST_ADD(conn->pending_trans, state);
8225 /* We need to send an interim response then receive the rest
8226 of the parameter/data bytes */
8227 reply_outbuf(req, 0, 0);
8228 show_msg((char *)req->outbuf);
8229 END_PROFILE(SMBtrans2);
8234 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8235 SAFE_FREE(state->data);
8236 SAFE_FREE(state->param);
8238 END_PROFILE(SMBtrans2);
8239 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8243 /****************************************************************************
8244 Reply to a SMBtranss2
8245 ****************************************************************************/
8247 void reply_transs2(struct smb_request *req)
8249 connection_struct *conn = req->conn;
8250 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8251 struct trans_state *state;
8253 START_PROFILE(SMBtranss2);
8255 show_msg((char *)req->inbuf);
8258 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8259 END_PROFILE(SMBtranss2);
8263 for (state = conn->pending_trans; state != NULL;
8264 state = state->next) {
8265 if (state->mid == req->mid) {
8270 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8271 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8272 END_PROFILE(SMBtranss2);
8276 /* Revise state->total_param and state->total_data in case they have
8277 changed downwards */
8279 if (SVAL(req->vwv+0, 0) < state->total_param)
8280 state->total_param = SVAL(req->vwv+0, 0);
8281 if (SVAL(req->vwv+1, 0) < state->total_data)
8282 state->total_data = SVAL(req->vwv+1, 0);
8284 pcnt = SVAL(req->vwv+2, 0);
8285 poff = SVAL(req->vwv+3, 0);
8286 pdisp = SVAL(req->vwv+4, 0);
8288 dcnt = SVAL(req->vwv+5, 0);
8289 doff = SVAL(req->vwv+6, 0);
8290 ddisp = SVAL(req->vwv+7, 0);
8292 state->received_param += pcnt;
8293 state->received_data += dcnt;
8295 if ((state->received_data > state->total_data) ||
8296 (state->received_param > state->total_param))
8300 if (trans_oob(state->total_param, pdisp, pcnt)
8301 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8304 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8308 if (trans_oob(state->total_data, ddisp, dcnt)
8309 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8312 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8315 if ((state->received_param < state->total_param) ||
8316 (state->received_data < state->total_data)) {
8317 END_PROFILE(SMBtranss2);
8321 handle_trans2(conn, req, state);
8323 DLIST_REMOVE(conn->pending_trans, state);
8324 SAFE_FREE(state->data);
8325 SAFE_FREE(state->param);
8328 END_PROFILE(SMBtranss2);
8333 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8334 DLIST_REMOVE(conn->pending_trans, state);
8335 SAFE_FREE(state->data);
8336 SAFE_FREE(state->param);
8338 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8339 END_PROFILE(SMBtranss2);