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,
2687 unsigned int max_data_bytes,
2691 char *pdata, *end_data;
2692 int data_len = 0, len;
2693 const char *vname = volume_label(SNUM(conn));
2694 int snum = SNUM(conn);
2695 char *fstype = lp_fstype(SNUM(conn));
2696 uint32 additional_flags = 0;
2699 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2700 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2701 "info level (0x%x) on IPC$.\n",
2702 (unsigned int)info_level));
2703 return NT_STATUS_ACCESS_DENIED;
2707 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2709 *ppdata = (char *)SMB_REALLOC(
2710 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2711 if (*ppdata == NULL) {
2712 return NT_STATUS_NO_MEMORY;
2716 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2717 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2719 switch (info_level) {
2720 case SMB_INFO_ALLOCATION:
2722 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2724 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2725 return map_nt_error_from_unix(errno);
2728 block_size = lp_block_size(snum);
2729 if (bsize < block_size) {
2730 uint64_t factor = block_size/bsize;
2735 if (bsize > block_size) {
2736 uint64_t factor = bsize/block_size;
2741 bytes_per_sector = 512;
2742 sectors_per_unit = bsize/bytes_per_sector;
2744 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2745 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2746 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2748 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2749 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2750 SIVAL(pdata,l1_cUnit,dsize);
2751 SIVAL(pdata,l1_cUnitAvail,dfree);
2752 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2756 case SMB_INFO_VOLUME:
2757 /* Return volume name */
2759 * Add volume serial number - hash of a combination of
2760 * the called hostname and the service name.
2762 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2764 * Win2k3 and previous mess this up by sending a name length
2765 * one byte short. I believe only older clients (OS/2 Win9x) use
2766 * this call so try fixing this by adding a terminating null to
2767 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2771 pdata+l2_vol_szVolLabel, vname,
2772 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2773 STR_NOALIGN|STR_TERMINATE);
2774 SCVAL(pdata,l2_vol_cch,len);
2775 data_len = l2_vol_szVolLabel + len;
2776 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
2777 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2781 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2782 case SMB_FS_ATTRIBUTE_INFORMATION:
2784 additional_flags = 0;
2785 #if defined(HAVE_SYS_QUOTAS)
2786 additional_flags |= FILE_VOLUME_QUOTAS;
2789 if(lp_nt_acl_support(SNUM(conn))) {
2790 additional_flags |= FILE_PERSISTENT_ACLS;
2793 /* Capabilities are filled in at connection time through STATVFS call */
2794 additional_flags |= conn->fs_capabilities;
2796 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2797 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2798 additional_flags); /* FS ATTRIBUTES */
2800 SIVAL(pdata,4,255); /* Max filename component length */
2801 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2802 and will think we can't do long filenames */
2803 len = srvstr_push(pdata, flags2, pdata+12, fstype,
2804 PTR_DIFF(end_data, pdata+12),
2807 data_len = 12 + len;
2810 case SMB_QUERY_FS_LABEL_INFO:
2811 case SMB_FS_LABEL_INFORMATION:
2812 len = srvstr_push(pdata, flags2, pdata+4, vname,
2813 PTR_DIFF(end_data, pdata+4), 0);
2818 case SMB_QUERY_FS_VOLUME_INFO:
2819 case SMB_FS_VOLUME_INFORMATION:
2822 * Add volume serial number - hash of a combination of
2823 * the called hostname and the service name.
2825 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2826 (str_checksum(get_local_machine_name())<<16));
2828 /* Max label len is 32 characters. */
2829 len = srvstr_push(pdata, flags2, pdata+18, vname,
2830 PTR_DIFF(end_data, pdata+18),
2832 SIVAL(pdata,12,len);
2835 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2836 (int)strlen(vname),vname, lp_servicename(snum)));
2839 case SMB_QUERY_FS_SIZE_INFO:
2840 case SMB_FS_SIZE_INFORMATION:
2842 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2844 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2845 return map_nt_error_from_unix(errno);
2847 block_size = lp_block_size(snum);
2848 if (bsize < block_size) {
2849 uint64_t factor = block_size/bsize;
2854 if (bsize > block_size) {
2855 uint64_t factor = bsize/block_size;
2860 bytes_per_sector = 512;
2861 sectors_per_unit = bsize/bytes_per_sector;
2862 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2863 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2864 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2865 SBIG_UINT(pdata,0,dsize);
2866 SBIG_UINT(pdata,8,dfree);
2867 SIVAL(pdata,16,sectors_per_unit);
2868 SIVAL(pdata,20,bytes_per_sector);
2872 case SMB_FS_FULL_SIZE_INFORMATION:
2874 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2876 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2877 return map_nt_error_from_unix(errno);
2879 block_size = lp_block_size(snum);
2880 if (bsize < block_size) {
2881 uint64_t factor = block_size/bsize;
2886 if (bsize > block_size) {
2887 uint64_t factor = bsize/block_size;
2892 bytes_per_sector = 512;
2893 sectors_per_unit = bsize/bytes_per_sector;
2894 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2895 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2896 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2897 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2898 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2899 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2900 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2901 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2905 case SMB_QUERY_FS_DEVICE_INFO:
2906 case SMB_FS_DEVICE_INFORMATION:
2908 SIVAL(pdata,0,0); /* dev type */
2909 SIVAL(pdata,4,0); /* characteristics */
2912 #ifdef HAVE_SYS_QUOTAS
2913 case SMB_FS_QUOTA_INFORMATION:
2915 * what we have to send --metze:
2917 * Unknown1: 24 NULL bytes
2918 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2919 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2920 * Quota Flags: 2 byte :
2921 * Unknown3: 6 NULL bytes
2925 * details for Quota Flags:
2927 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2928 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2929 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2930 * 0x0001 Enable Quotas: enable quota for this fs
2934 /* we need to fake up a fsp here,
2935 * because its not send in this call
2938 SMB_NTQUOTA_STRUCT quotas;
2941 ZERO_STRUCT(quotas);
2947 if (conn->server_info->utok.uid != sec_initial_uid()) {
2948 DEBUG(0,("set_user_quota: access_denied "
2949 "service [%s] user [%s]\n",
2950 lp_servicename(SNUM(conn)),
2951 conn->server_info->unix_name));
2952 return NT_STATUS_ACCESS_DENIED;
2955 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2956 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2957 return map_nt_error_from_unix(errno);
2962 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
2963 lp_servicename(SNUM(conn))));
2965 /* Unknown1 24 NULL bytes*/
2966 SBIG_UINT(pdata,0,(uint64_t)0);
2967 SBIG_UINT(pdata,8,(uint64_t)0);
2968 SBIG_UINT(pdata,16,(uint64_t)0);
2970 /* Default Soft Quota 8 bytes */
2971 SBIG_UINT(pdata,24,quotas.softlim);
2973 /* Default Hard Quota 8 bytes */
2974 SBIG_UINT(pdata,32,quotas.hardlim);
2976 /* Quota flag 2 bytes */
2977 SSVAL(pdata,40,quotas.qflags);
2979 /* Unknown3 6 NULL bytes */
2985 #endif /* HAVE_SYS_QUOTAS */
2986 case SMB_FS_OBJECTID_INFORMATION:
2988 unsigned char objid[16];
2989 struct smb_extended_info extended_info;
2990 memcpy(pdata,create_volume_objectid(conn, objid),16);
2991 samba_extended_info_version (&extended_info);
2992 SIVAL(pdata,16,extended_info.samba_magic);
2993 SIVAL(pdata,20,extended_info.samba_version);
2994 SIVAL(pdata,24,extended_info.samba_subversion);
2995 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2996 memcpy(pdata+36,extended_info.samba_version_string,28);
3002 * Query the version and capabilities of the CIFS UNIX extensions
3006 case SMB_QUERY_CIFS_UNIX_INFO:
3008 bool large_write = lp_min_receive_file_size() &&
3009 !srv_is_signing_active(smbd_server_conn);
3010 bool large_read = !srv_is_signing_active(smbd_server_conn);
3011 int encrypt_caps = 0;
3013 if (!lp_unix_extensions()) {
3014 return NT_STATUS_INVALID_LEVEL;
3017 switch (conn->encrypt_level) {
3023 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3026 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3027 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3028 large_write = false;
3034 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3035 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3037 /* We have POSIX ACLs, pathname, encryption,
3038 * large read/write, and locking capability. */
3040 SBIG_UINT(pdata,4,((uint64_t)(
3041 CIFS_UNIX_POSIX_ACLS_CAP|
3042 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3043 CIFS_UNIX_FCNTL_LOCKS_CAP|
3044 CIFS_UNIX_EXTATTR_CAP|
3045 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3047 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3049 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3053 case SMB_QUERY_POSIX_FS_INFO:
3056 vfs_statvfs_struct svfs;
3058 if (!lp_unix_extensions()) {
3059 return NT_STATUS_INVALID_LEVEL;
3062 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3066 SIVAL(pdata,0,svfs.OptimalTransferSize);
3067 SIVAL(pdata,4,svfs.BlockSize);
3068 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3069 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3070 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3071 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3072 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3073 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3074 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3076 } else if (rc == EOPNOTSUPP) {
3077 return NT_STATUS_INVALID_LEVEL;
3078 #endif /* EOPNOTSUPP */
3080 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3081 return NT_STATUS_DOS(ERRSRV, ERRerror);
3086 case SMB_QUERY_POSIX_WHOAMI:
3092 if (!lp_unix_extensions()) {
3093 return NT_STATUS_INVALID_LEVEL;
3096 if (max_data_bytes < 40) {
3097 return NT_STATUS_BUFFER_TOO_SMALL;
3100 /* We ARE guest if global_sid_Builtin_Guests is
3101 * in our list of SIDs.
3103 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3104 conn->server_info->ptok)) {
3105 flags |= SMB_WHOAMI_GUEST;
3108 /* We are NOT guest if global_sid_Authenticated_Users
3109 * is in our list of SIDs.
3111 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3112 conn->server_info->ptok)) {
3113 flags &= ~SMB_WHOAMI_GUEST;
3116 /* NOTE: 8 bytes for UID/GID, irrespective of native
3117 * platform size. This matches
3118 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3120 data_len = 4 /* flags */
3127 + 4 /* pad/reserved */
3128 + (conn->server_info->utok.ngroups * 8)
3130 + (conn->server_info->ptok->num_sids *
3134 SIVAL(pdata, 0, flags);
3135 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3137 (uint64_t)conn->server_info->utok.uid);
3138 SBIG_UINT(pdata, 16,
3139 (uint64_t)conn->server_info->utok.gid);
3142 if (data_len >= max_data_bytes) {
3143 /* Potential overflow, skip the GIDs and SIDs. */
3145 SIVAL(pdata, 24, 0); /* num_groups */
3146 SIVAL(pdata, 28, 0); /* num_sids */
3147 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3148 SIVAL(pdata, 36, 0); /* reserved */
3154 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3155 SIVAL(pdata, 28, conn->server_info->num_sids);
3157 /* We walk the SID list twice, but this call is fairly
3158 * infrequent, and I don't expect that it's performance
3159 * sensitive -- jpeach
3161 for (i = 0, sid_bytes = 0;
3162 i < conn->server_info->ptok->num_sids; ++i) {
3163 sid_bytes += ndr_size_dom_sid(
3164 &conn->server_info->ptok->user_sids[i],
3169 /* SID list byte count */
3170 SIVAL(pdata, 32, sid_bytes);
3172 /* 4 bytes pad/reserved - must be zero */
3173 SIVAL(pdata, 36, 0);
3177 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3178 SBIG_UINT(pdata, data_len,
3179 (uint64_t)conn->server_info->utok.groups[i]);
3185 i < conn->server_info->ptok->num_sids; ++i) {
3186 int sid_len = ndr_size_dom_sid(
3187 &conn->server_info->ptok->user_sids[i],
3191 sid_linearize(pdata + data_len, sid_len,
3192 &conn->server_info->ptok->user_sids[i]);
3193 data_len += sid_len;
3199 case SMB_MAC_QUERY_FS_INFO:
3201 * Thursby MAC extension... ONLY on NTFS filesystems
3202 * once we do streams then we don't need this
3204 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3206 SIVAL(pdata,84,0x100); /* Don't support mac... */
3211 return NT_STATUS_INVALID_LEVEL;
3214 *ret_data_len = data_len;
3215 return NT_STATUS_OK;
3218 /****************************************************************************
3219 Reply to a TRANS2_QFSINFO (query filesystem info).
3220 ****************************************************************************/
3222 static void call_trans2qfsinfo(connection_struct *conn,
3223 struct smb_request *req,
3224 char **pparams, int total_params,
3225 char **ppdata, int total_data,
3226 unsigned int max_data_bytes)
3228 char *params = *pparams;
3229 uint16_t info_level;
3234 if (total_params < 2) {
3235 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3239 info_level = SVAL(params,0);
3241 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3242 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3243 DEBUG(0,("call_trans2qfsinfo: encryption required "
3244 "and info level 0x%x sent.\n",
3245 (unsigned int)info_level));
3246 exit_server_cleanly("encryption required "
3252 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3254 if(vfs_stat_smb_fname(conn,".",&st)!=0) {
3255 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
3256 reply_doserror(req, ERRSRV, ERRinvdevice);
3260 status = smbd_do_qfsinfo(conn, req,
3265 if (!NT_STATUS_IS_OK(status)) {
3266 reply_nterror(req, status);
3270 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3273 DEBUG( 4, ( "%s info_level = %d\n",
3274 smb_fn_name(req->cmd), info_level) );
3279 /****************************************************************************
3280 Reply to a TRANS2_SETFSINFO (set filesystem info).
3281 ****************************************************************************/
3283 static void call_trans2setfsinfo(connection_struct *conn,
3284 struct smb_request *req,
3285 char **pparams, int total_params,
3286 char **ppdata, int total_data,
3287 unsigned int max_data_bytes)
3289 char *pdata = *ppdata;
3290 char *params = *pparams;
3293 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3296 if (total_params < 4) {
3297 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3299 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3303 info_level = SVAL(params,2);
3306 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3307 info_level != SMB_SET_CIFS_UNIX_INFO) {
3308 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3309 "info level (0x%x) on IPC$.\n",
3310 (unsigned int)info_level));
3311 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3316 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3317 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3318 DEBUG(0,("call_trans2setfsinfo: encryption required "
3319 "and info level 0x%x sent.\n",
3320 (unsigned int)info_level));
3321 exit_server_cleanly("encryption required "
3327 switch(info_level) {
3328 case SMB_SET_CIFS_UNIX_INFO:
3330 uint16 client_unix_major;
3331 uint16 client_unix_minor;
3332 uint32 client_unix_cap_low;
3333 uint32 client_unix_cap_high;
3335 if (!lp_unix_extensions()) {
3337 NT_STATUS_INVALID_LEVEL);
3341 /* There should be 12 bytes of capabilities set. */
3342 if (total_data < 8) {
3345 NT_STATUS_INVALID_PARAMETER);
3348 client_unix_major = SVAL(pdata,0);
3349 client_unix_minor = SVAL(pdata,2);
3350 client_unix_cap_low = IVAL(pdata,4);
3351 client_unix_cap_high = IVAL(pdata,8);
3352 /* Just print these values for now. */
3353 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3354 cap_low = 0x%x, cap_high = 0x%x\n",
3355 (unsigned int)client_unix_major,
3356 (unsigned int)client_unix_minor,
3357 (unsigned int)client_unix_cap_low,
3358 (unsigned int)client_unix_cap_high ));
3360 /* Here is where we must switch to posix pathname processing... */
3361 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3362 lp_set_posix_pathnames();
3363 mangle_change_to_posix();
3366 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3367 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3368 /* Client that knows how to do posix locks,
3369 * but not posix open/mkdir operations. Set a
3370 * default type for read/write checks. */
3372 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3378 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3381 size_t param_len = 0;
3382 size_t data_len = total_data;
3384 if (!lp_unix_extensions()) {
3387 NT_STATUS_INVALID_LEVEL);
3391 if (lp_smb_encrypt(SNUM(conn)) == false) {
3394 NT_STATUS_NOT_SUPPORTED);
3398 DEBUG( 4,("call_trans2setfsinfo: "
3399 "request transport encryption.\n"));
3401 status = srv_request_encryption_setup(conn,
3402 (unsigned char **)ppdata,
3404 (unsigned char **)pparams,
3407 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3408 !NT_STATUS_IS_OK(status)) {
3409 reply_nterror(req, status);
3413 send_trans2_replies(conn, req,
3420 if (NT_STATUS_IS_OK(status)) {
3421 /* Server-side transport
3422 * encryption is now *on*. */
3423 status = srv_encryption_start(conn);
3424 if (!NT_STATUS_IS_OK(status)) {
3425 exit_server_cleanly(
3426 "Failure in setting "
3427 "up encrypted transport");
3433 case SMB_FS_QUOTA_INFORMATION:
3435 files_struct *fsp = NULL;
3436 SMB_NTQUOTA_STRUCT quotas;
3438 ZERO_STRUCT(quotas);
3441 if ((conn->server_info->utok.uid != sec_initial_uid())
3442 ||!CAN_WRITE(conn)) {
3443 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3444 lp_servicename(SNUM(conn)),
3445 conn->server_info->unix_name));
3446 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3450 /* note: normaly there're 48 bytes,
3451 * but we didn't use the last 6 bytes for now
3454 fsp = file_fsp(req, SVAL(params,0));
3456 if (!check_fsp_ntquota_handle(conn, req,
3458 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3460 req, NT_STATUS_INVALID_HANDLE);
3464 if (total_data < 42) {
3465 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3469 NT_STATUS_INVALID_PARAMETER);
3473 /* unknown_1 24 NULL bytes in pdata*/
3475 /* the soft quotas 8 bytes (uint64_t)*/
3476 quotas.softlim = (uint64_t)IVAL(pdata,24);
3477 #ifdef LARGE_SMB_OFF_T
3478 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3479 #else /* LARGE_SMB_OFF_T */
3480 if ((IVAL(pdata,28) != 0)&&
3481 ((quotas.softlim != 0xFFFFFFFF)||
3482 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3483 /* more than 32 bits? */
3486 NT_STATUS_INVALID_PARAMETER);
3489 #endif /* LARGE_SMB_OFF_T */
3491 /* the hard quotas 8 bytes (uint64_t)*/
3492 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3493 #ifdef LARGE_SMB_OFF_T
3494 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3495 #else /* LARGE_SMB_OFF_T */
3496 if ((IVAL(pdata,36) != 0)&&
3497 ((quotas.hardlim != 0xFFFFFFFF)||
3498 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3499 /* more than 32 bits? */
3502 NT_STATUS_INVALID_PARAMETER);
3505 #endif /* LARGE_SMB_OFF_T */
3507 /* quota_flags 2 bytes **/
3508 quotas.qflags = SVAL(pdata,40);
3510 /* unknown_2 6 NULL bytes follow*/
3512 /* now set the quotas */
3513 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3514 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3515 reply_nterror(req, map_nt_error_from_unix(errno));
3522 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3524 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3530 * sending this reply works fine,
3531 * but I'm not sure it's the same
3532 * like windows do...
3535 reply_outbuf(req, 10, 0);
3538 #if defined(HAVE_POSIX_ACLS)
3539 /****************************************************************************
3540 Utility function to count the number of entries in a POSIX acl.
3541 ****************************************************************************/
3543 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3545 unsigned int ace_count = 0;
3546 int entry_id = SMB_ACL_FIRST_ENTRY;
3547 SMB_ACL_ENTRY_T entry;
3549 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3551 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3552 entry_id = SMB_ACL_NEXT_ENTRY;
3559 /****************************************************************************
3560 Utility function to marshall a POSIX acl into wire format.
3561 ****************************************************************************/
3563 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3565 int entry_id = SMB_ACL_FIRST_ENTRY;
3566 SMB_ACL_ENTRY_T entry;
3568 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3569 SMB_ACL_TAG_T tagtype;
3570 SMB_ACL_PERMSET_T permset;
3571 unsigned char perms = 0;
3572 unsigned int own_grp;
3575 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3576 entry_id = SMB_ACL_NEXT_ENTRY;
3579 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3580 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3584 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3585 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3589 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3590 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3591 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3593 SCVAL(pdata,1,perms);
3596 case SMB_ACL_USER_OBJ:
3597 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3598 own_grp = (unsigned int)pst->st_ex_uid;
3599 SIVAL(pdata,2,own_grp);
3604 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3606 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3609 own_grp = (unsigned int)*puid;
3610 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3611 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3612 SIVAL(pdata,2,own_grp);
3616 case SMB_ACL_GROUP_OBJ:
3617 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3618 own_grp = (unsigned int)pst->st_ex_gid;
3619 SIVAL(pdata,2,own_grp);
3624 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3626 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3629 own_grp = (unsigned int)*pgid;
3630 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3631 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3632 SIVAL(pdata,2,own_grp);
3637 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3638 SIVAL(pdata,2,0xFFFFFFFF);
3639 SIVAL(pdata,6,0xFFFFFFFF);
3642 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3643 SIVAL(pdata,2,0xFFFFFFFF);
3644 SIVAL(pdata,6,0xFFFFFFFF);
3647 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3650 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3657 /****************************************************************************
3658 Store the FILE_UNIX_BASIC info.
3659 ****************************************************************************/
3661 static char *store_file_unix_basic(connection_struct *conn,
3664 const SMB_STRUCT_STAT *psbuf)
3666 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3667 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3669 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3672 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3675 put_long_date_timespec(pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3676 put_long_date_timespec(pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3677 put_long_date_timespec(pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3680 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3684 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3688 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3691 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3695 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3699 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */
3702 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3706 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3713 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3714 * the chflags(2) (or equivalent) flags.
3716 * XXX: this really should be behind the VFS interface. To do this, we would
3717 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3718 * Each VFS module could then implement its own mapping as appropriate for the
3719 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3721 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3725 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3729 { UF_IMMUTABLE, EXT_IMMUTABLE },
3733 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3737 { UF_HIDDEN, EXT_HIDDEN },
3740 /* Do not remove. We need to guarantee that this array has at least one
3741 * entry to build on HP-UX.
3747 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3748 uint32 *smb_fflags, uint32 *smb_fmask)
3752 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3753 *smb_fmask |= info2_flags_map[i].smb_fflag;
3754 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3755 *smb_fflags |= info2_flags_map[i].smb_fflag;
3760 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3761 const uint32 smb_fflags,
3762 const uint32 smb_fmask,
3765 uint32 max_fmask = 0;
3768 *stat_fflags = psbuf->st_ex_flags;
3770 /* For each flags requested in smb_fmask, check the state of the
3771 * corresponding flag in smb_fflags and set or clear the matching
3775 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3776 max_fmask |= info2_flags_map[i].smb_fflag;
3777 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3778 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3779 *stat_fflags |= info2_flags_map[i].stat_fflag;
3781 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3786 /* If smb_fmask is asking to set any bits that are not supported by
3787 * our flag mappings, we should fail.
3789 if ((smb_fmask & max_fmask) != smb_fmask) {
3797 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3798 * of file flags and birth (create) time.
3800 static char *store_file_unix_basic_info2(connection_struct *conn,
3803 const SMB_STRUCT_STAT *psbuf)
3805 uint32 file_flags = 0;
3806 uint32 flags_mask = 0;
3808 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3810 /* Create (birth) time 64 bit */
3811 put_long_date_timespec(pdata, psbuf->st_ex_btime);
3814 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3815 SIVAL(pdata, 0, file_flags); /* flags */
3816 SIVAL(pdata, 4, flags_mask); /* mask */
3822 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3823 const struct stream_struct *streams,
3825 unsigned int max_data_bytes,
3826 unsigned int *data_size)
3829 unsigned int ofs = 0;
3831 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3832 unsigned int next_offset;
3834 smb_ucs2_t *namebuf;
3836 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3837 streams[i].name, &namelen) ||
3840 return NT_STATUS_INVALID_PARAMETER;
3844 * name_buf is now null-terminated, we need to marshall as not
3850 SIVAL(data, ofs+4, namelen);
3851 SOFF_T(data, ofs+8, streams[i].size);
3852 SOFF_T(data, ofs+16, streams[i].alloc_size);
3853 memcpy(data+ofs+24, namebuf, namelen);
3854 TALLOC_FREE(namebuf);
3856 next_offset = ofs + 24 + namelen;
3858 if (i == num_streams-1) {
3859 SIVAL(data, ofs, 0);
3862 unsigned int align = ndr_align_size(next_offset, 8);
3864 memset(data+next_offset, 0, align);
3865 next_offset += align;
3867 SIVAL(data, ofs, next_offset - ofs);
3876 return NT_STATUS_OK;
3879 /****************************************************************************
3880 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3881 ****************************************************************************/
3883 static void call_trans2qpipeinfo(connection_struct *conn,
3884 struct smb_request *req,
3885 unsigned int tran_call,
3886 char **pparams, int total_params,
3887 char **ppdata, int total_data,
3888 unsigned int max_data_bytes)
3890 char *params = *pparams;
3891 char *pdata = *ppdata;
3892 unsigned int data_size = 0;
3893 unsigned int param_size = 2;
3898 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3902 if (total_params < 4) {
3903 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3907 fsp = file_fsp(req, SVAL(params,0));
3908 if (!fsp_is_np(fsp)) {
3909 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3913 info_level = SVAL(params,2);
3915 *pparams = (char *)SMB_REALLOC(*pparams,2);
3916 if (*pparams == NULL) {
3917 reply_nterror(req, NT_STATUS_NO_MEMORY);
3922 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3923 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3924 if (*ppdata == NULL ) {
3925 reply_nterror(req, NT_STATUS_NO_MEMORY);
3930 switch (info_level) {
3931 case SMB_FILE_STANDARD_INFORMATION:
3933 SOFF_T(pdata,0,4096LL);
3940 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3944 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3950 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
3951 TALLOC_CTX *mem_ctx,
3952 uint16_t info_level,
3954 const struct smb_filename *smb_fname,
3955 bool delete_pending,
3956 struct timespec write_time_ts,
3958 struct ea_list *ea_list,
3959 int lock_data_count,
3962 unsigned int max_data_bytes,
3964 unsigned int *pdata_size)
3966 char *pdata = *ppdata;
3967 char *dstart, *dend;
3968 unsigned int data_size;
3969 struct timespec create_time_ts, mtime_ts, atime_ts;
3970 time_t create_time, mtime, atime;
3971 SMB_STRUCT_STAT sbuf;
3979 uint64_t file_size = 0;
3981 uint64_t allocation_size = 0;
3982 uint64_t file_index = 0;
3983 uint32_t access_mask = 0;
3985 sbuf = smb_fname->st;
3987 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3988 return NT_STATUS_INVALID_LEVEL;
3991 status = get_full_smb_filename(mem_ctx, smb_fname, &fname);
3992 if (!NT_STATUS_IS_OK(status)) {
3996 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
3997 fname, fsp ? fsp->fnum : -1, info_level, max_data_bytes));
4000 mode = dos_mode_msdfs(conn, smb_fname);
4002 mode = dos_mode(conn, smb_fname);
4005 mode = FILE_ATTRIBUTE_NORMAL;
4007 nlink = sbuf.st_ex_nlink;
4009 if (nlink && (mode&aDIR)) {
4013 if ((nlink > 0) && delete_pending) {
4017 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4018 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4019 if (*ppdata == NULL) {
4020 return NT_STATUS_NO_MEMORY;
4024 dend = dstart + data_size - 1;
4026 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4027 update_stat_ex_mtime(&sbuf, write_time_ts);
4030 create_time_ts = sbuf.st_ex_btime;
4031 mtime_ts = sbuf.st_ex_mtime;
4032 atime_ts = sbuf.st_ex_atime;
4034 if (lp_dos_filetime_resolution(SNUM(conn))) {
4035 dos_filetime_timespec(&create_time_ts);
4036 dos_filetime_timespec(&mtime_ts);
4037 dos_filetime_timespec(&atime_ts);
4040 create_time = convert_timespec_to_time_t(create_time_ts);
4041 mtime = convert_timespec_to_time_t(mtime_ts);
4042 atime = convert_timespec_to_time_t(atime_ts);
4044 p = strrchr_m(smb_fname->base_name,'/');
4046 base_name = smb_fname->base_name;
4050 /* NT expects the name to be in an exact form of the *full*
4051 filename. See the trans2 torture test */
4052 if (ISDOT(base_name)) {
4053 dos_fname = talloc_strdup(mem_ctx, "\\");
4055 return NT_STATUS_NO_MEMORY;
4058 dos_fname = talloc_asprintf(mem_ctx,
4062 return NT_STATUS_NO_MEMORY;
4064 string_replace(dos_fname, '/', '\\');
4067 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &sbuf);
4070 /* Do we have this path open ? */
4072 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4073 fsp1 = file_find_di_first(fileid);
4074 if (fsp1 && fsp1->initial_allocation_size) {
4075 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
4079 if (!(mode & aDIR)) {
4080 file_size = get_file_size_stat(&sbuf);
4084 pos = fsp->fh->position_information;
4088 access_mask = fsp->access_mask;
4090 /* GENERIC_EXECUTE mapping from Windows */
4091 access_mask = 0x12019F;
4094 /* This should be an index number - looks like
4097 I think this causes us to fail the IFSKIT
4098 BasicFileInformationTest. -tpot */
4099 file_index = ((sbuf.st_ex_ino) & UINT32_MAX); /* FileIndexLow */
4100 file_index |= ((uint64_t)((sbuf.st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
4102 switch (info_level) {
4103 case SMB_INFO_STANDARD:
4104 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4106 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4107 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4108 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4109 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4110 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4111 SSVAL(pdata,l1_attrFile,mode);
4114 case SMB_INFO_QUERY_EA_SIZE:
4116 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4117 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4119 srv_put_dos_date2(pdata,0,create_time);
4120 srv_put_dos_date2(pdata,4,atime);
4121 srv_put_dos_date2(pdata,8,mtime); /* write time */
4122 SIVAL(pdata,12,(uint32)file_size);
4123 SIVAL(pdata,16,(uint32)allocation_size);
4124 SSVAL(pdata,20,mode);
4125 SIVAL(pdata,22,ea_size);
4129 case SMB_INFO_IS_NAME_VALID:
4130 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4132 /* os/2 needs this ? really ?*/
4133 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4135 /* This is only reached for qpathinfo */
4139 case SMB_INFO_QUERY_EAS_FROM_LIST:
4141 size_t total_ea_len = 0;
4142 struct ea_list *ea_file_list = NULL;
4144 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4146 ea_file_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
4147 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4149 if (!ea_list || (total_ea_len > data_size)) {
4151 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4155 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4159 case SMB_INFO_QUERY_ALL_EAS:
4161 /* We have data_size bytes to put EA's into. */
4162 size_t total_ea_len = 0;
4164 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4166 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
4167 if (!ea_list || (total_ea_len > data_size)) {
4169 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4173 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4177 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4179 /* We have data_size bytes to put EA's into. */
4180 size_t total_ea_len = 0;
4181 struct ea_list *ea_file_list = NULL;
4183 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4185 /*TODO: add filtering and index handling */
4187 ea_file_list = get_ea_list_from_file(mem_ctx,
4191 if (!ea_file_list) {
4192 return NT_STATUS_NO_EAS_ON_FILE;
4195 status = fill_ea_chained_buffer(mem_ctx,
4199 conn, ea_file_list);
4200 if (!NT_STATUS_IS_OK(status)) {
4206 case SMB_FILE_BASIC_INFORMATION:
4207 case SMB_QUERY_FILE_BASIC_INFO:
4209 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4210 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4211 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4213 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4217 put_long_date_timespec(pdata,create_time_ts);
4218 put_long_date_timespec(pdata+8,atime_ts);
4219 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4220 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4221 SIVAL(pdata,32,mode);
4223 DEBUG(5,("SMB_QFBI - "));
4224 DEBUG(5,("create: %s ", ctime(&create_time)));
4225 DEBUG(5,("access: %s ", ctime(&atime)));
4226 DEBUG(5,("write: %s ", ctime(&mtime)));
4227 DEBUG(5,("change: %s ", ctime(&mtime)));
4228 DEBUG(5,("mode: %x\n", mode));
4231 case SMB_FILE_STANDARD_INFORMATION:
4232 case SMB_QUERY_FILE_STANDARD_INFO:
4234 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4236 SOFF_T(pdata,0,allocation_size);
4237 SOFF_T(pdata,8,file_size);
4238 SIVAL(pdata,16,nlink);
4239 SCVAL(pdata,20,delete_pending?1:0);
4240 SCVAL(pdata,21,(mode&aDIR)?1:0);
4241 SSVAL(pdata,22,0); /* Padding. */
4244 case SMB_FILE_EA_INFORMATION:
4245 case SMB_QUERY_FILE_EA_INFO:
4247 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4248 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4250 SIVAL(pdata,0,ea_size);
4254 /* Get the 8.3 name - used if NT SMB was negotiated. */
4255 case SMB_QUERY_FILE_ALT_NAME_INFO:
4256 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4259 char mangled_name[13];
4260 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4261 if (!name_to_8_3(base_name,mangled_name,
4262 True,conn->params)) {
4263 return NT_STATUS_NO_MEMORY;
4265 len = srvstr_push(dstart, flags2,
4266 pdata+4, mangled_name,
4267 PTR_DIFF(dend, pdata+4),
4269 data_size = 4 + len;
4274 case SMB_QUERY_FILE_NAME_INFO:
4278 this must be *exactly* right for ACLs on mapped drives to work
4280 len = srvstr_push(dstart, flags2,
4282 PTR_DIFF(dend, pdata+4),
4284 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4285 data_size = 4 + len;
4290 case SMB_FILE_ALLOCATION_INFORMATION:
4291 case SMB_QUERY_FILE_ALLOCATION_INFO:
4292 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4294 SOFF_T(pdata,0,allocation_size);
4297 case SMB_FILE_END_OF_FILE_INFORMATION:
4298 case SMB_QUERY_FILE_END_OF_FILEINFO:
4299 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4301 SOFF_T(pdata,0,file_size);
4304 case SMB_QUERY_FILE_ALL_INFO:
4305 case SMB_FILE_ALL_INFORMATION:
4308 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4309 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4310 put_long_date_timespec(pdata,create_time_ts);
4311 put_long_date_timespec(pdata+8,atime_ts);
4312 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4313 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4314 SIVAL(pdata,32,mode);
4315 SIVAL(pdata,36,0); /* padding. */
4317 SOFF_T(pdata,0,allocation_size);
4318 SOFF_T(pdata,8,file_size);
4319 SIVAL(pdata,16,nlink);
4320 SCVAL(pdata,20,delete_pending);
4321 SCVAL(pdata,21,(mode&aDIR)?1:0);
4324 SIVAL(pdata,0,ea_size);
4325 pdata += 4; /* EA info */
4326 len = srvstr_push(dstart, flags2,
4328 PTR_DIFF(dend, pdata+4),
4332 data_size = PTR_DIFF(pdata,(*ppdata));
4336 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4339 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4340 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4341 put_long_date_timespec(pdata+0x00,create_time_ts);
4342 put_long_date_timespec(pdata+0x08,atime_ts);
4343 put_long_date_timespec(pdata+0x10,mtime_ts); /* write time */
4344 put_long_date_timespec(pdata+0x18,mtime_ts); /* change time */
4345 SIVAL(pdata, 0x20, mode);
4346 SIVAL(pdata, 0x24, 0); /* padding. */
4347 SBVAL(pdata, 0x28, allocation_size);
4348 SBVAL(pdata, 0x30, file_size);
4349 SIVAL(pdata, 0x38, nlink);
4350 SCVAL(pdata, 0x3C, delete_pending);
4351 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4352 SSVAL(pdata, 0x3E, 0); /* padding */
4353 SBVAL(pdata, 0x40, file_index);
4354 SIVAL(pdata, 0x48, ea_size);
4355 SIVAL(pdata, 0x4C, access_mask);
4356 SBVAL(pdata, 0x50, pos);
4357 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4358 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4362 len = srvstr_push(dstart, flags2,
4364 PTR_DIFF(dend, pdata+4),
4368 data_size = PTR_DIFF(pdata,(*ppdata));
4371 case SMB_FILE_INTERNAL_INFORMATION:
4373 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4374 SBVAL(pdata, 0, file_index);
4378 case SMB_FILE_ACCESS_INFORMATION:
4379 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4380 SIVAL(pdata, 0, access_mask);
4384 case SMB_FILE_NAME_INFORMATION:
4385 /* Pathname with leading '\'. */
4388 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4389 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4390 SIVAL(pdata,0,byte_len);
4391 data_size = 4 + byte_len;
4395 case SMB_FILE_DISPOSITION_INFORMATION:
4396 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4398 SCVAL(pdata,0,delete_pending);
4401 case SMB_FILE_POSITION_INFORMATION:
4402 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4404 SOFF_T(pdata,0,pos);
4407 case SMB_FILE_MODE_INFORMATION:
4408 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4409 SIVAL(pdata,0,mode);
4413 case SMB_FILE_ALIGNMENT_INFORMATION:
4414 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4415 SIVAL(pdata,0,0); /* No alignment needed. */
4420 * NT4 server just returns "invalid query" to this - if we try
4421 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4424 /* The first statement above is false - verified using Thursby
4425 * client against NT4 -- gcolley.
4427 case SMB_QUERY_FILE_STREAM_INFO:
4428 case SMB_FILE_STREAM_INFORMATION: {
4429 unsigned int num_streams;
4430 struct stream_struct *streams;
4432 DEBUG(10,("smbd_do_qfilepathinfo: "
4433 "SMB_FILE_STREAM_INFORMATION\n"));
4435 status = SMB_VFS_STREAMINFO(
4436 conn, fsp, fname, talloc_tos(),
4437 &num_streams, &streams);
4439 if (!NT_STATUS_IS_OK(status)) {
4440 DEBUG(10, ("could not get stream info: %s\n",
4441 nt_errstr(status)));
4445 status = marshall_stream_info(num_streams, streams,
4446 pdata, max_data_bytes,
4449 if (!NT_STATUS_IS_OK(status)) {
4450 DEBUG(10, ("marshall_stream_info failed: %s\n",
4451 nt_errstr(status)));
4455 TALLOC_FREE(streams);
4459 case SMB_QUERY_COMPRESSION_INFO:
4460 case SMB_FILE_COMPRESSION_INFORMATION:
4461 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4462 SOFF_T(pdata,0,file_size);
4463 SIVAL(pdata,8,0); /* ??? */
4464 SIVAL(pdata,12,0); /* ??? */
4468 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4469 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4470 put_long_date_timespec(pdata,create_time_ts);
4471 put_long_date_timespec(pdata+8,atime_ts);
4472 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4473 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4474 SOFF_T(pdata,32,allocation_size);
4475 SOFF_T(pdata,40,file_size);
4476 SIVAL(pdata,48,mode);
4477 SIVAL(pdata,52,0); /* ??? */
4481 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4482 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4483 SIVAL(pdata,0,mode);
4489 * CIFS UNIX Extensions.
4492 case SMB_QUERY_FILE_UNIX_BASIC:
4494 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4495 data_size = PTR_DIFF(pdata,(*ppdata));
4499 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4501 for (i=0; i<100; i++)
4502 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4508 case SMB_QUERY_FILE_UNIX_INFO2:
4510 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4511 data_size = PTR_DIFF(pdata,(*ppdata));
4515 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4517 for (i=0; i<100; i++)
4518 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4524 case SMB_QUERY_FILE_UNIX_LINK:
4527 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4530 return NT_STATUS_NO_MEMORY;
4533 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4535 if(!S_ISLNK(sbuf.st_ex_mode)) {
4536 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4539 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4541 len = SMB_VFS_READLINK(conn,fname,
4544 return map_nt_error_from_unix(errno);
4547 len = srvstr_push(dstart, flags2,
4549 PTR_DIFF(dend, pdata),
4552 data_size = PTR_DIFF(pdata,(*ppdata));
4557 #if defined(HAVE_POSIX_ACLS)
4558 case SMB_QUERY_POSIX_ACL:
4560 SMB_ACL_T file_acl = NULL;
4561 SMB_ACL_T def_acl = NULL;
4562 uint16 num_file_acls = 0;
4563 uint16 num_def_acls = 0;
4565 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4566 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4568 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4571 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4572 DEBUG(5,("smbd_do_qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4574 return NT_STATUS_NOT_IMPLEMENTED;
4577 if (S_ISDIR(sbuf.st_ex_mode)) {
4578 if (fsp && fsp->is_directory) {
4580 SMB_VFS_SYS_ACL_GET_FILE(
4582 fsp->fsp_name->base_name,
4583 SMB_ACL_TYPE_DEFAULT);
4585 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4587 def_acl = free_empty_sys_acl(conn, def_acl);
4590 num_file_acls = count_acl_entries(conn, file_acl);
4591 num_def_acls = count_acl_entries(conn, def_acl);
4593 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4594 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4596 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4597 SMB_POSIX_ACL_HEADER_SIZE) ));
4599 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4602 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4604 return NT_STATUS_BUFFER_TOO_SMALL;
4607 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4608 SSVAL(pdata,2,num_file_acls);
4609 SSVAL(pdata,4,num_def_acls);
4610 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4612 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4615 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4617 return NT_STATUS_INTERNAL_ERROR;
4619 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4621 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4624 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4626 return NT_STATUS_INTERNAL_ERROR;
4630 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4633 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4635 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4641 case SMB_QUERY_POSIX_LOCK:
4646 enum brl_type lock_type;
4648 /* We need an open file with a real fd for this. */
4649 if (!fsp || fsp->is_directory || fsp->fh->fd == -1) {
4650 return NT_STATUS_INVALID_LEVEL;
4653 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4654 return NT_STATUS_INVALID_PARAMETER;
4657 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4658 case POSIX_LOCK_TYPE_READ:
4659 lock_type = READ_LOCK;
4661 case POSIX_LOCK_TYPE_WRITE:
4662 lock_type = WRITE_LOCK;
4664 case POSIX_LOCK_TYPE_UNLOCK:
4666 /* There's no point in asking for an unlock... */
4667 return NT_STATUS_INVALID_PARAMETER;
4670 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4671 #if defined(HAVE_LONGLONG)
4672 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4673 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4674 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4675 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4676 #else /* HAVE_LONGLONG */
4677 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4678 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4679 #endif /* HAVE_LONGLONG */
4681 status = query_lock(fsp,
4688 if (ERROR_WAS_LOCK_DENIED(status)) {
4689 /* Here we need to report who has it locked... */
4690 data_size = POSIX_LOCK_DATA_SIZE;
4692 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4693 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4694 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4695 #if defined(HAVE_LONGLONG)
4696 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4697 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4698 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4699 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4700 #else /* HAVE_LONGLONG */
4701 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4702 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4703 #endif /* HAVE_LONGLONG */
4705 } else if (NT_STATUS_IS_OK(status)) {
4706 /* For success we just return a copy of what we sent
4707 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4708 data_size = POSIX_LOCK_DATA_SIZE;
4709 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4710 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4718 return NT_STATUS_INVALID_LEVEL;
4721 *pdata_size = data_size;
4722 return NT_STATUS_OK;
4725 /****************************************************************************
4726 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4727 file name or file id).
4728 ****************************************************************************/
4730 static void call_trans2qfilepathinfo(connection_struct *conn,
4731 struct smb_request *req,
4732 unsigned int tran_call,
4733 char **pparams, int total_params,
4734 char **ppdata, int total_data,
4735 unsigned int max_data_bytes)
4737 char *params = *pparams;
4738 char *pdata = *ppdata;
4740 unsigned int data_size = 0;
4741 unsigned int param_size = 2;
4742 struct smb_filename *smb_fname = NULL;
4743 bool delete_pending = False;
4744 struct timespec write_time_ts;
4745 files_struct *fsp = NULL;
4746 struct file_id fileid;
4747 struct ea_list *ea_list = NULL;
4748 int lock_data_count = 0;
4749 char *lock_data = NULL;
4750 bool ms_dfs_link = false;
4751 NTSTATUS status = NT_STATUS_OK;
4754 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4758 ZERO_STRUCT(write_time_ts);
4760 if (tran_call == TRANSACT2_QFILEINFO) {
4761 if (total_params < 4) {
4762 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4767 call_trans2qpipeinfo(conn, req, tran_call,
4768 pparams, total_params,
4774 fsp = file_fsp(req, SVAL(params,0));
4775 info_level = SVAL(params,2);
4777 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
4779 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4780 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4784 /* Initial check for valid fsp ptr. */
4785 if (!check_fsp_open(conn, req, fsp)) {
4789 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
4791 if (!NT_STATUS_IS_OK(status)) {
4792 reply_nterror(req, status);
4796 if(fsp->fake_file_handle) {
4798 * This is actually for the QUOTA_FAKE_FILE --metze
4801 /* We know this name is ok, it's already passed the checks. */
4803 } else if(fsp->is_directory || fsp->fh->fd == -1) {
4805 * This is actually a QFILEINFO on a directory
4806 * handle (returned from an NT SMB). NT5.0 seems
4807 * to do this call. JRA.
4810 if (INFO_LEVEL_IS_UNIX(info_level)) {
4811 /* Always do lstat for UNIX calls. */
4812 if (SMB_VFS_LSTAT(conn, smb_fname)) {
4813 DEBUG(3,("call_trans2qfilepathinfo: "
4814 "SMB_VFS_LSTAT of %s failed "
4816 smb_fname_str_dbg(smb_fname),
4819 map_nt_error_from_unix(errno));
4822 } else if (SMB_VFS_STAT(conn, smb_fname)) {
4823 DEBUG(3,("call_trans2qfilepathinfo: "
4824 "SMB_VFS_STAT of %s failed (%s)\n",
4825 smb_fname_str_dbg(smb_fname),
4828 map_nt_error_from_unix(errno));
4832 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4833 get_file_infos(fileid, &delete_pending, &write_time_ts);
4836 * Original code - this is an open file.
4838 if (!check_fsp(conn, req, fsp)) {
4842 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
4843 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
4844 fsp->fnum, strerror(errno)));
4846 map_nt_error_from_unix(errno));
4849 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4850 get_file_infos(fileid, &delete_pending, &write_time_ts);
4857 if (total_params < 7) {
4858 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4862 info_level = SVAL(params,0);
4864 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
4866 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4867 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4871 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
4873 STR_TERMINATE, &status);
4874 if (!NT_STATUS_IS_OK(status)) {
4875 reply_nterror(req, status);
4879 status = filename_convert(req,
4881 req->flags2 & FLAGS2_DFS_PATHNAMES,
4884 if (!NT_STATUS_IS_OK(status)) {
4885 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4886 reply_botherror(req,
4887 NT_STATUS_PATH_NOT_COVERED,
4888 ERRSRV, ERRbadpath);
4891 reply_nterror(req, status);
4895 /* If this is a stream, check if there is a delete_pending. */
4896 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
4897 && is_ntfs_stream_smb_fname(smb_fname)) {
4898 struct smb_filename *smb_fname_base = NULL;
4900 /* Create an smb_filename with stream_name == NULL. */
4902 create_synthetic_smb_fname(talloc_tos(),
4903 smb_fname->base_name,
4906 if (!NT_STATUS_IS_OK(status)) {
4907 reply_nterror(req, status);
4911 if (INFO_LEVEL_IS_UNIX(info_level)) {
4912 /* Always do lstat for UNIX calls. */
4913 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
4914 DEBUG(3,("call_trans2qfilepathinfo: "
4915 "SMB_VFS_LSTAT of %s failed "
4917 smb_fname_str_dbg(smb_fname_base),
4919 TALLOC_FREE(smb_fname_base);
4921 map_nt_error_from_unix(errno));
4925 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
4926 DEBUG(3,("call_trans2qfilepathinfo: "
4927 "fileinfo of %s failed "
4929 smb_fname_str_dbg(smb_fname_base),
4931 TALLOC_FREE(smb_fname_base);
4933 map_nt_error_from_unix(errno));
4938 fileid = vfs_file_id_from_sbuf(conn,
4939 &smb_fname_base->st);
4940 TALLOC_FREE(smb_fname_base);
4941 get_file_infos(fileid, &delete_pending, NULL);
4942 if (delete_pending) {
4943 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4948 if (INFO_LEVEL_IS_UNIX(info_level)) {
4949 /* Always do lstat for UNIX calls. */
4950 if (SMB_VFS_LSTAT(conn, smb_fname)) {
4951 DEBUG(3,("call_trans2qfilepathinfo: "
4952 "SMB_VFS_LSTAT of %s failed (%s)\n",
4953 smb_fname_str_dbg(smb_fname),
4956 map_nt_error_from_unix(errno));
4960 } else if (!VALID_STAT(smb_fname->st) &&
4961 SMB_VFS_STAT(conn, smb_fname) &&
4962 (info_level != SMB_INFO_IS_NAME_VALID)) {
4963 ms_dfs_link = check_msdfs_link(conn,
4964 smb_fname->base_name,
4968 DEBUG(3,("call_trans2qfilepathinfo: "
4969 "SMB_VFS_STAT of %s failed (%s)\n",
4970 smb_fname_str_dbg(smb_fname),
4973 map_nt_error_from_unix(errno));
4978 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4979 get_file_infos(fileid, &delete_pending, &write_time_ts);
4980 if (delete_pending) {
4981 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4986 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
4987 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
4988 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4990 /* Pull out any data sent here before we realloc. */
4991 switch (info_level) {
4992 case SMB_INFO_QUERY_EAS_FROM_LIST:
4994 /* Pull any EA list from the data portion. */
4997 if (total_data < 4) {
4999 req, NT_STATUS_INVALID_PARAMETER);
5002 ea_size = IVAL(pdata,0);
5004 if (total_data > 0 && ea_size != total_data) {
5005 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5006 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5008 req, NT_STATUS_INVALID_PARAMETER);
5012 if (!lp_ea_support(SNUM(conn))) {
5013 reply_doserror(req, ERRDOS,
5014 ERReasnotsupported);
5018 /* Pull out the list of names. */
5019 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5022 req, NT_STATUS_INVALID_PARAMETER);
5028 case SMB_QUERY_POSIX_LOCK:
5030 if (fsp == NULL || fsp->fh->fd == -1) {
5031 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5035 if (total_data != POSIX_LOCK_DATA_SIZE) {
5037 req, NT_STATUS_INVALID_PARAMETER);
5041 /* Copy the lock range data. */
5042 lock_data = (char *)TALLOC_MEMDUP(
5043 req, pdata, total_data);
5045 reply_nterror(req, NT_STATUS_NO_MEMORY);
5048 lock_data_count = total_data;
5054 *pparams = (char *)SMB_REALLOC(*pparams,2);
5055 if (*pparams == NULL) {
5056 reply_nterror(req, NT_STATUS_NO_MEMORY);
5063 * draft-leach-cifs-v1-spec-02.txt
5064 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5067 * The requested information is placed in the Data portion of the
5068 * transaction response. For the information levels greater than 0x100,
5069 * the transaction response has 1 parameter word which should be
5070 * ignored by the client.
5072 * However Windows only follows this rule for the IS_NAME_VALID call.
5074 switch (info_level) {
5075 case SMB_INFO_IS_NAME_VALID:
5080 if ((info_level & 0xFF00) == 0xFF00) {
5082 * We use levels that start with 0xFF00
5083 * internally to represent SMB2 specific levels
5085 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5089 status = smbd_do_qfilepathinfo(conn, req, info_level,
5091 delete_pending, write_time_ts,
5092 ms_dfs_link, ea_list,
5093 lock_data_count, lock_data,
5094 req->flags2, max_data_bytes,
5095 ppdata, &data_size);
5096 if (!NT_STATUS_IS_OK(status)) {
5097 reply_nterror(req, status);
5101 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5107 /****************************************************************************
5108 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5110 ****************************************************************************/
5112 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5113 connection_struct *conn,
5114 const struct smb_filename *smb_fname_old,
5115 const struct smb_filename *smb_fname_new)
5117 NTSTATUS status = NT_STATUS_OK;
5119 /* source must already exist. */
5120 if (!VALID_STAT(smb_fname_old->st)) {
5121 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5124 /* Disallow if newname already exists. */
5125 if (VALID_STAT(smb_fname_new->st)) {
5126 return NT_STATUS_OBJECT_NAME_COLLISION;
5129 /* No links from a directory. */
5130 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5131 return NT_STATUS_FILE_IS_A_DIRECTORY;
5134 /* Setting a hardlink to/from a stream isn't currently supported. */
5135 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5136 is_ntfs_stream_smb_fname(smb_fname_new)) {
5137 return NT_STATUS_INVALID_PARAMETER;
5140 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5141 smb_fname_old->base_name, smb_fname_new->base_name));
5143 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5144 smb_fname_new->base_name) != 0) {
5145 status = map_nt_error_from_unix(errno);
5146 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5147 nt_errstr(status), smb_fname_old->base_name,
5148 smb_fname_new->base_name));
5153 /****************************************************************************
5154 Deal with setting the time from any of the setfilepathinfo functions.
5155 ****************************************************************************/
5157 NTSTATUS smb_set_file_time(connection_struct *conn,
5159 const struct smb_filename *smb_fname,
5160 struct smb_file_time *ft,
5161 bool setting_write_time)
5163 struct smb_filename *smb_fname_base = NULL;
5165 FILE_NOTIFY_CHANGE_LAST_ACCESS
5166 |FILE_NOTIFY_CHANGE_LAST_WRITE;
5169 if (!VALID_STAT(smb_fname->st)) {
5170 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5173 /* get some defaults (no modifications) if any info is zero or -1. */
5174 if (null_timespec(ft->atime)) {
5175 ft->atime= smb_fname->st.st_ex_atime;
5176 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5179 if (null_timespec(ft->mtime)) {
5180 ft->mtime = smb_fname->st.st_ex_mtime;
5181 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5184 if (!setting_write_time) {
5185 /* ft->mtime comes from change time, not write time. */
5186 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5189 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5190 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5191 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5192 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5193 if (!null_timespec(ft->create_time)) {
5194 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5195 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5199 * Try and set the times of this file if
5200 * they are different from the current values.
5204 struct timespec mts = smb_fname->st.st_ex_mtime;
5205 struct timespec ats = smb_fname->st.st_ex_atime;
5206 if ((timespec_compare(&ft->atime, &ats) == 0) &&
5207 (timespec_compare(&ft->mtime, &mts) == 0)) {
5208 return NT_STATUS_OK;
5212 if (setting_write_time) {
5214 * This was a Windows setfileinfo on an open file.
5215 * NT does this a lot. We also need to
5216 * set the time here, as it can be read by
5217 * FindFirst/FindNext and with the patch for bug #2045
5218 * in smbd/fileio.c it ensures that this timestamp is
5219 * kept sticky even after a write. We save the request
5220 * away and will set it on file close and after a write. JRA.
5223 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5224 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5227 if (fsp->base_fsp) {
5228 set_sticky_write_time_fsp(fsp->base_fsp,
5231 set_sticky_write_time_fsp(fsp, ft->mtime);
5234 set_sticky_write_time_path(
5235 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5240 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5242 /* Always call ntimes on the base, even if a stream was passed in. */
5243 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5244 NULL, &smb_fname->st,
5246 if (!NT_STATUS_IS_OK(status)) {
5250 if(file_ntimes(conn, smb_fname_base, ft)!=0) {
5251 TALLOC_FREE(smb_fname_base);
5252 return map_nt_error_from_unix(errno);
5254 TALLOC_FREE(smb_fname_base);
5256 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5257 smb_fname->base_name);
5258 return NT_STATUS_OK;
5261 /****************************************************************************
5262 Deal with setting the dosmode from any of the setfilepathinfo functions.
5263 ****************************************************************************/
5265 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5266 const struct smb_filename *smb_fname,
5269 struct smb_filename *smb_fname_base = NULL;
5272 if (!VALID_STAT(smb_fname->st)) {
5273 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5276 /* Always operate on the base_name, even if a stream was passed in. */
5277 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5278 NULL, &smb_fname->st,
5280 if (!NT_STATUS_IS_OK(status)) {
5285 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5292 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5294 /* check the mode isn't different, before changing it */
5295 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5296 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5297 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5298 (unsigned int)dosmode));
5300 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5302 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5304 smb_fname_str_dbg(smb_fname_base),
5306 status = map_nt_error_from_unix(errno);
5310 status = NT_STATUS_OK;
5312 TALLOC_FREE(smb_fname_base);
5316 /****************************************************************************
5317 Deal with setting the size from any of the setfilepathinfo functions.
5318 ****************************************************************************/
5320 static NTSTATUS smb_set_file_size(connection_struct *conn,
5321 struct smb_request *req,
5323 const struct smb_filename *smb_fname,
5324 const SMB_STRUCT_STAT *psbuf,
5327 NTSTATUS status = NT_STATUS_OK;
5328 struct smb_filename *smb_fname_tmp = NULL;
5329 files_struct *new_fsp = NULL;
5331 if (!VALID_STAT(*psbuf)) {
5332 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5335 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5337 if (size == get_file_size_stat(psbuf)) {
5338 return NT_STATUS_OK;
5341 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5342 smb_fname_str_dbg(smb_fname), (double)size));
5344 if (fsp && fsp->fh->fd != -1) {
5345 /* Handle based call. */
5346 if (vfs_set_filelen(fsp, size) == -1) {
5347 return map_nt_error_from_unix(errno);
5349 trigger_write_time_update_immediate(fsp);
5350 return NT_STATUS_OK;
5353 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5354 if (!NT_STATUS_IS_OK(status)) {
5358 smb_fname_tmp->st = *psbuf;
5360 status = SMB_VFS_CREATE_FILE(
5363 0, /* root_dir_fid */
5364 smb_fname_tmp, /* fname */
5365 FILE_WRITE_ATTRIBUTES, /* access_mask */
5366 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5368 FILE_OPEN, /* create_disposition*/
5369 0, /* create_options */
5370 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5371 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5372 0, /* allocation_size */
5375 &new_fsp, /* result */
5378 TALLOC_FREE(smb_fname_tmp);
5380 if (!NT_STATUS_IS_OK(status)) {
5381 /* NB. We check for open_was_deferred in the caller. */
5385 if (vfs_set_filelen(new_fsp, size) == -1) {
5386 status = map_nt_error_from_unix(errno);
5387 close_file(req, new_fsp,NORMAL_CLOSE);
5391 trigger_write_time_update_immediate(new_fsp);
5392 close_file(req, new_fsp,NORMAL_CLOSE);
5393 return NT_STATUS_OK;
5396 /****************************************************************************
5397 Deal with SMB_INFO_SET_EA.
5398 ****************************************************************************/
5400 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5404 const struct smb_filename *smb_fname)
5406 struct ea_list *ea_list = NULL;
5407 TALLOC_CTX *ctx = NULL;
5408 NTSTATUS status = NT_STATUS_OK;
5410 if (total_data < 10) {
5412 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5413 length. They seem to have no effect. Bug #3212. JRA */
5415 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5416 /* We're done. We only get EA info in this call. */
5417 return NT_STATUS_OK;
5420 return NT_STATUS_INVALID_PARAMETER;
5423 if (IVAL(pdata,0) > total_data) {
5424 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5425 IVAL(pdata,0), (unsigned int)total_data));
5426 return NT_STATUS_INVALID_PARAMETER;
5430 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5432 return NT_STATUS_INVALID_PARAMETER;
5434 status = set_ea(conn, fsp, smb_fname, ea_list);
5439 /****************************************************************************
5440 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5441 ****************************************************************************/
5443 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5447 const struct smb_filename *smb_fname)
5449 NTSTATUS status = NT_STATUS_OK;
5450 bool delete_on_close;
5453 if (total_data < 1) {
5454 return NT_STATUS_INVALID_PARAMETER;
5458 return NT_STATUS_INVALID_HANDLE;
5461 delete_on_close = (CVAL(pdata,0) ? True : False);
5462 dosmode = dos_mode(conn, smb_fname);
5464 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5465 "delete_on_close = %u\n",
5466 smb_fname_str_dbg(smb_fname),
5467 (unsigned int)dosmode,
5468 (unsigned int)delete_on_close ));
5470 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5472 if (!NT_STATUS_IS_OK(status)) {
5476 /* The set is across all open files on this dev/inode pair. */
5477 if (!set_delete_on_close(fsp, delete_on_close,
5478 &conn->server_info->utok)) {
5479 return NT_STATUS_ACCESS_DENIED;
5481 return NT_STATUS_OK;
5484 /****************************************************************************
5485 Deal with SMB_FILE_POSITION_INFORMATION.
5486 ****************************************************************************/
5488 static NTSTATUS smb_file_position_information(connection_struct *conn,
5493 uint64_t position_information;
5495 if (total_data < 8) {
5496 return NT_STATUS_INVALID_PARAMETER;
5500 /* Ignore on pathname based set. */
5501 return NT_STATUS_OK;
5504 position_information = (uint64_t)IVAL(pdata,0);
5505 #ifdef LARGE_SMB_OFF_T
5506 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5507 #else /* LARGE_SMB_OFF_T */
5508 if (IVAL(pdata,4) != 0) {
5509 /* more than 32 bits? */
5510 return NT_STATUS_INVALID_PARAMETER;
5512 #endif /* LARGE_SMB_OFF_T */
5514 DEBUG(10,("smb_file_position_information: Set file position "
5515 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5516 (double)position_information));
5517 fsp->fh->position_information = position_information;
5518 return NT_STATUS_OK;
5521 /****************************************************************************
5522 Deal with SMB_FILE_MODE_INFORMATION.
5523 ****************************************************************************/
5525 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5531 if (total_data < 4) {
5532 return NT_STATUS_INVALID_PARAMETER;
5534 mode = IVAL(pdata,0);
5535 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5536 return NT_STATUS_INVALID_PARAMETER;
5538 return NT_STATUS_OK;
5541 /****************************************************************************
5542 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5543 ****************************************************************************/
5545 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5546 struct smb_request *req,
5551 char *link_target = NULL;
5552 const char *newname = fname;
5553 NTSTATUS status = NT_STATUS_OK;
5554 TALLOC_CTX *ctx = talloc_tos();
5556 /* Set a symbolic link. */
5557 /* Don't allow this if follow links is false. */
5559 if (total_data == 0) {
5560 return NT_STATUS_INVALID_PARAMETER;
5563 if (!lp_symlinks(SNUM(conn))) {
5564 return NT_STATUS_ACCESS_DENIED;
5567 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5568 total_data, STR_TERMINATE);
5571 return NT_STATUS_INVALID_PARAMETER;
5574 /* !widelinks forces the target path to be within the share. */
5575 /* This means we can interpret the target as a pathname. */
5576 if (!lp_widelinks(SNUM(conn))) {
5577 char *rel_name = NULL;
5578 char *last_dirp = NULL;
5580 if (*link_target == '/') {
5581 /* No absolute paths allowed. */
5582 return NT_STATUS_ACCESS_DENIED;
5584 rel_name = talloc_strdup(ctx,newname);
5586 return NT_STATUS_NO_MEMORY;
5588 last_dirp = strrchr_m(rel_name, '/');
5590 last_dirp[1] = '\0';
5592 rel_name = talloc_strdup(ctx,"./");
5594 return NT_STATUS_NO_MEMORY;
5597 rel_name = talloc_asprintf_append(rel_name,
5601 return NT_STATUS_NO_MEMORY;
5604 status = check_name(conn, rel_name);
5605 if (!NT_STATUS_IS_OK(status)) {
5610 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5611 newname, link_target ));
5613 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5614 return map_nt_error_from_unix(errno);
5617 return NT_STATUS_OK;
5620 /****************************************************************************
5621 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5622 ****************************************************************************/
5624 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5625 struct smb_request *req,
5626 const char *pdata, int total_data,
5627 const struct smb_filename *smb_fname_new)
5629 char *oldname = NULL;
5630 struct smb_filename *smb_fname_old = NULL;
5631 TALLOC_CTX *ctx = talloc_tos();
5632 NTSTATUS status = NT_STATUS_OK;
5634 /* Set a hard link. */
5635 if (total_data == 0) {
5636 return NT_STATUS_INVALID_PARAMETER;
5639 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5640 total_data, STR_TERMINATE, &status);
5641 if (!NT_STATUS_IS_OK(status)) {
5645 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5646 smb_fname_str_dbg(smb_fname_new), oldname));
5648 status = filename_convert(ctx,
5650 req->flags2 & FLAGS2_DFS_PATHNAMES,
5653 if (!NT_STATUS_IS_OK(status)) {
5657 return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
5660 /****************************************************************************
5661 Deal with SMB_FILE_RENAME_INFORMATION.
5662 ****************************************************************************/
5664 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5665 struct smb_request *req,
5674 char *newname = NULL;
5675 char *base_name = NULL;
5676 struct smb_filename *smb_fname = NULL;
5677 bool dest_has_wcard = False;
5678 NTSTATUS status = NT_STATUS_OK;
5680 TALLOC_CTX *ctx = talloc_tos();
5682 if (total_data < 13) {
5683 return NT_STATUS_INVALID_PARAMETER;
5686 overwrite = (CVAL(pdata,0) ? True : False);
5687 root_fid = IVAL(pdata,4);
5688 len = IVAL(pdata,8);
5690 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5691 return NT_STATUS_INVALID_PARAMETER;
5694 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5697 if (!NT_STATUS_IS_OK(status)) {
5701 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5704 status = resolve_dfspath_wcard(ctx, conn,
5705 req->flags2 & FLAGS2_DFS_PATHNAMES,
5709 if (!NT_STATUS_IS_OK(status)) {
5713 /* Check the new name has no '/' characters. */
5714 if (strchr_m(newname, '/')) {
5715 return NT_STATUS_NOT_SUPPORTED;
5718 if (fsp && fsp->base_fsp) {
5719 /* newname must be a stream name. */
5720 if (newname[0] != ':') {
5721 return NT_STATUS_NOT_SUPPORTED;
5724 /* Create an smb_fname to call rename_internals_fsp() with. */
5725 status = create_synthetic_smb_fname(talloc_tos(),
5726 fsp->base_fsp->fsp_name->base_name, newname, NULL,
5728 if (!NT_STATUS_IS_OK(status)) {
5733 * Set the original last component, since
5734 * rename_internals_fsp() requires it.
5736 smb_fname->original_lcomp = talloc_strdup(smb_fname, newname);
5737 if (smb_fname->original_lcomp == NULL) {
5738 status = NT_STATUS_NO_MEMORY;
5742 /* Create a char * to call rename_internals() with. */
5743 base_name = talloc_asprintf(ctx, "%s%s",
5744 fsp->base_fsp->fsp_name->base_name,
5747 status = NT_STATUS_NO_MEMORY;
5751 /* newname must *not* be a stream name. */
5752 if (newname[0] == ':') {
5753 return NT_STATUS_NOT_SUPPORTED;
5756 /* Create the base directory. */
5757 base_name = talloc_strdup(ctx, fname);
5759 return NT_STATUS_NO_MEMORY;
5761 p = strrchr_m(base_name, '/');
5765 base_name = talloc_strdup(ctx, "./");
5767 return NT_STATUS_NO_MEMORY;
5770 /* Append the new name. */
5771 base_name = talloc_asprintf_append(base_name,
5775 return NT_STATUS_NO_MEMORY;
5778 status = unix_convert(ctx, conn, base_name, &smb_fname,
5781 /* If an error we expect this to be
5782 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5784 if (!NT_STATUS_IS_OK(status)) {
5785 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5789 /* Create an smb_fname to call rename_internals_fsp() */
5790 status = create_synthetic_smb_fname(talloc_tos(),
5793 if (!NT_STATUS_IS_OK(status)) {
5801 DEBUG(10,("smb_file_rename_information: "
5802 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5803 fsp->fnum, fsp_str_dbg(fsp), base_name));
5804 status = rename_internals_fsp(conn, fsp, smb_fname, 0,
5807 DEBUG(10,("smb_file_rename_information: "
5808 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5810 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5811 overwrite, False, dest_has_wcard,
5812 FILE_WRITE_ATTRIBUTES);
5815 TALLOC_FREE(smb_fname);
5819 /****************************************************************************
5820 Deal with SMB_SET_POSIX_ACL.
5821 ****************************************************************************/
5823 #if defined(HAVE_POSIX_ACLS)
5824 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5829 SMB_STRUCT_STAT *psbuf)
5831 uint16 posix_acl_version;
5832 uint16 num_file_acls;
5833 uint16 num_def_acls;
5834 bool valid_file_acls = True;
5835 bool valid_def_acls = True;
5837 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5838 return NT_STATUS_INVALID_PARAMETER;
5840 posix_acl_version = SVAL(pdata,0);
5841 num_file_acls = SVAL(pdata,2);
5842 num_def_acls = SVAL(pdata,4);
5844 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5845 valid_file_acls = False;
5849 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5850 valid_def_acls = False;
5854 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5855 return NT_STATUS_INVALID_PARAMETER;
5858 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5859 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5860 return NT_STATUS_INVALID_PARAMETER;
5863 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5864 fname ? fname : fsp_str_dbg(fsp),
5865 (unsigned int)num_file_acls,
5866 (unsigned int)num_def_acls));
5868 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5869 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5870 return map_nt_error_from_unix(errno);
5873 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5874 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5875 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5876 return map_nt_error_from_unix(errno);
5878 return NT_STATUS_OK;
5882 /****************************************************************************
5883 Deal with SMB_SET_POSIX_LOCK.
5884 ****************************************************************************/
5886 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5887 struct smb_request *req,
5895 bool blocking_lock = False;
5896 enum brl_type lock_type;
5898 NTSTATUS status = NT_STATUS_OK;
5900 if (fsp == NULL || fsp->fh->fd == -1) {
5901 return NT_STATUS_INVALID_HANDLE;
5904 if (total_data != POSIX_LOCK_DATA_SIZE) {
5905 return NT_STATUS_INVALID_PARAMETER;
5908 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5909 case POSIX_LOCK_TYPE_READ:
5910 lock_type = READ_LOCK;
5912 case POSIX_LOCK_TYPE_WRITE:
5913 /* Return the right POSIX-mappable error code for files opened read-only. */
5914 if (!fsp->can_write) {
5915 return NT_STATUS_INVALID_HANDLE;
5917 lock_type = WRITE_LOCK;
5919 case POSIX_LOCK_TYPE_UNLOCK:
5920 lock_type = UNLOCK_LOCK;
5923 return NT_STATUS_INVALID_PARAMETER;
5926 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5927 blocking_lock = False;
5928 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5929 blocking_lock = True;
5931 return NT_STATUS_INVALID_PARAMETER;
5934 if (!lp_blocking_locks(SNUM(conn))) {
5935 blocking_lock = False;
5938 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5939 #if defined(HAVE_LONGLONG)
5940 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5941 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5942 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5943 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5944 #else /* HAVE_LONGLONG */
5945 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5946 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5947 #endif /* HAVE_LONGLONG */
5949 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5950 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5952 (unsigned int)lock_type,
5953 (unsigned int)lock_pid,
5957 if (lock_type == UNLOCK_LOCK) {
5958 status = do_unlock(smbd_messaging_context(),
5965 uint32 block_smbpid;
5967 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5979 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5981 * A blocking lock was requested. Package up
5982 * this smb into a queued request and push it
5983 * onto the blocking lock queue.
5985 if(push_blocking_lock_request(br_lck,
5988 -1, /* infinite timeout. */
5996 TALLOC_FREE(br_lck);
6000 TALLOC_FREE(br_lck);
6006 /****************************************************************************
6007 Deal with SMB_INFO_STANDARD.
6008 ****************************************************************************/
6010 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6014 const struct smb_filename *smb_fname)
6016 struct smb_file_time ft;
6019 if (total_data < 12) {
6020 return NT_STATUS_INVALID_PARAMETER;
6024 ft.create_time = interpret_long_date(pdata);
6027 ft.atime = interpret_long_date(pdata + 8);
6030 ft.mtime = interpret_long_date(pdata + 16);
6032 DEBUG(10,("smb_set_info_standard: file %s\n",
6033 smb_fname_str_dbg(smb_fname)));
6035 return smb_set_file_time(conn, fsp, smb_fname, &ft, true);
6038 /****************************************************************************
6039 Deal with SMB_SET_FILE_BASIC_INFO.
6040 ****************************************************************************/
6042 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6046 const struct smb_filename *smb_fname)
6048 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6049 struct timespec write_time;
6050 struct timespec changed_time;
6051 struct smb_file_time ft;
6053 NTSTATUS status = NT_STATUS_OK;
6054 bool setting_write_time = true;
6058 if (total_data < 36) {
6059 return NT_STATUS_INVALID_PARAMETER;
6062 /* Set the attributes */
6063 dosmode = IVAL(pdata,32);
6064 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6065 if (!NT_STATUS_IS_OK(status)) {
6070 ft.atime = interpret_long_date(pdata+8);
6072 write_time = interpret_long_date(pdata+16);
6073 changed_time = interpret_long_date(pdata+24);
6076 ft.mtime = timespec_min(&write_time, &changed_time);
6079 ft.create_time = interpret_long_date(pdata);
6081 if ((timespec_compare(&write_time, &ft.mtime) == 1) &&
6082 !null_timespec(write_time)) {
6083 ft.mtime = write_time;
6086 /* Prefer a defined time to an undefined one. */
6087 if (null_timespec(ft.mtime)) {
6088 if (null_timespec(write_time)) {
6089 ft.mtime = changed_time;
6090 setting_write_time = false;
6092 ft.mtime = write_time;
6096 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6097 smb_fname_str_dbg(smb_fname)));
6099 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6100 setting_write_time);
6103 /****************************************************************************
6104 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6105 ****************************************************************************/
6107 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6108 struct smb_request *req,
6112 struct smb_filename *smb_fname)
6114 uint64_t allocation_size = 0;
6115 NTSTATUS status = NT_STATUS_OK;
6116 files_struct *new_fsp = NULL;
6118 if (!VALID_STAT(smb_fname->st)) {
6119 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6122 if (total_data < 8) {
6123 return NT_STATUS_INVALID_PARAMETER;
6126 allocation_size = (uint64_t)IVAL(pdata,0);
6127 #ifdef LARGE_SMB_OFF_T
6128 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6129 #else /* LARGE_SMB_OFF_T */
6130 if (IVAL(pdata,4) != 0) {
6131 /* more than 32 bits? */
6132 return NT_STATUS_INVALID_PARAMETER;
6134 #endif /* LARGE_SMB_OFF_T */
6136 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6137 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6138 (double)allocation_size));
6140 if (allocation_size) {
6141 allocation_size = smb_roundup(conn, allocation_size);
6144 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6145 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6146 (double)allocation_size));
6148 if (fsp && fsp->fh->fd != -1) {
6149 /* Open file handle. */
6150 /* Only change if needed. */
6151 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6152 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6153 return map_nt_error_from_unix(errno);
6156 /* But always update the time. */
6158 * This is equivalent to a write. Ensure it's seen immediately
6159 * if there are no pending writes.
6161 trigger_write_time_update_immediate(fsp);
6162 return NT_STATUS_OK;
6165 /* Pathname or stat or directory file. */
6166 status = SMB_VFS_CREATE_FILE(
6169 0, /* root_dir_fid */
6170 smb_fname, /* fname */
6171 FILE_WRITE_DATA, /* access_mask */
6172 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6174 FILE_OPEN, /* create_disposition*/
6175 0, /* create_options */
6176 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6177 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6178 0, /* allocation_size */
6181 &new_fsp, /* result */
6184 if (!NT_STATUS_IS_OK(status)) {
6185 /* NB. We check for open_was_deferred in the caller. */
6189 /* Only change if needed. */
6190 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6191 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6192 status = map_nt_error_from_unix(errno);
6193 close_file(req, new_fsp, NORMAL_CLOSE);
6198 /* Changing the allocation size should set the last mod time. */
6200 * This is equivalent to a write. Ensure it's seen immediately
6201 * if there are no pending writes.
6203 trigger_write_time_update_immediate(new_fsp);
6205 close_file(req, new_fsp, NORMAL_CLOSE);
6206 return NT_STATUS_OK;
6209 /****************************************************************************
6210 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6211 ****************************************************************************/
6213 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6214 struct smb_request *req,
6218 const struct smb_filename *smb_fname)
6222 if (total_data < 8) {
6223 return NT_STATUS_INVALID_PARAMETER;
6226 size = IVAL(pdata,0);
6227 #ifdef LARGE_SMB_OFF_T
6228 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6229 #else /* LARGE_SMB_OFF_T */
6230 if (IVAL(pdata,4) != 0) {
6231 /* more than 32 bits? */
6232 return NT_STATUS_INVALID_PARAMETER;
6234 #endif /* LARGE_SMB_OFF_T */
6235 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6236 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6239 return smb_set_file_size(conn, req,
6246 /****************************************************************************
6247 Allow a UNIX info mknod.
6248 ****************************************************************************/
6250 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6253 const struct smb_filename *smb_fname)
6255 uint32 file_type = IVAL(pdata,56);
6256 #if defined(HAVE_MAKEDEV)
6257 uint32 dev_major = IVAL(pdata,60);
6258 uint32 dev_minor = IVAL(pdata,68);
6260 SMB_DEV_T dev = (SMB_DEV_T)0;
6261 uint32 raw_unixmode = IVAL(pdata,84);
6265 if (total_data < 100) {
6266 return NT_STATUS_INVALID_PARAMETER;
6269 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6270 PERM_NEW_FILE, &unixmode);
6271 if (!NT_STATUS_IS_OK(status)) {
6275 #if defined(HAVE_MAKEDEV)
6276 dev = makedev(dev_major, dev_minor);
6279 switch (file_type) {
6280 #if defined(S_IFIFO)
6281 case UNIX_TYPE_FIFO:
6282 unixmode |= S_IFIFO;
6285 #if defined(S_IFSOCK)
6286 case UNIX_TYPE_SOCKET:
6287 unixmode |= S_IFSOCK;
6290 #if defined(S_IFCHR)
6291 case UNIX_TYPE_CHARDEV:
6292 unixmode |= S_IFCHR;
6295 #if defined(S_IFBLK)
6296 case UNIX_TYPE_BLKDEV:
6297 unixmode |= S_IFBLK;
6301 return NT_STATUS_INVALID_PARAMETER;
6304 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6305 "%.0f mode 0%o for file %s\n", (double)dev,
6306 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6308 /* Ok - do the mknod. */
6309 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6310 return map_nt_error_from_unix(errno);
6313 /* If any of the other "set" calls fail we
6314 * don't want to end up with a half-constructed mknod.
6317 if (lp_inherit_perms(SNUM(conn))) {
6319 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6321 return NT_STATUS_NO_MEMORY;
6323 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6325 TALLOC_FREE(parent);
6328 return NT_STATUS_OK;
6331 /****************************************************************************
6332 Deal with SMB_SET_FILE_UNIX_BASIC.
6333 ****************************************************************************/
6335 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6336 struct smb_request *req,
6340 const struct smb_filename *smb_fname)
6342 struct smb_file_time ft;
6343 uint32 raw_unixmode;
6346 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6347 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6348 NTSTATUS status = NT_STATUS_OK;
6349 bool delete_on_fail = False;
6350 enum perm_type ptype;
6351 files_struct *all_fsps = NULL;
6352 bool modify_mtime = true;
6354 SMB_STRUCT_STAT sbuf;
6358 if (total_data < 100) {
6359 return NT_STATUS_INVALID_PARAMETER;
6362 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6363 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6364 size=IVAL(pdata,0); /* first 8 Bytes are size */
6365 #ifdef LARGE_SMB_OFF_T
6366 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6367 #else /* LARGE_SMB_OFF_T */
6368 if (IVAL(pdata,4) != 0) {
6369 /* more than 32 bits? */
6370 return NT_STATUS_INVALID_PARAMETER;
6372 #endif /* LARGE_SMB_OFF_T */
6375 ft.atime = interpret_long_date(pdata+24); /* access_time */
6376 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6377 set_owner = (uid_t)IVAL(pdata,40);
6378 set_grp = (gid_t)IVAL(pdata,48);
6379 raw_unixmode = IVAL(pdata,84);
6381 if (VALID_STAT(smb_fname->st)) {
6382 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6383 ptype = PERM_EXISTING_DIR;
6385 ptype = PERM_EXISTING_FILE;
6388 ptype = PERM_NEW_FILE;
6391 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6393 if (!NT_STATUS_IS_OK(status)) {
6397 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6398 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6399 smb_fname_str_dbg(smb_fname), (double)size,
6400 (unsigned int)set_owner, (unsigned int)set_grp,
6401 (int)raw_unixmode));
6403 sbuf = smb_fname->st;
6405 if (!VALID_STAT(sbuf)) {
6406 struct smb_filename *smb_fname_tmp = NULL;
6408 * The only valid use of this is to create character and block
6409 * devices, and named pipes. This is deprecated (IMHO) and
6410 * a new info level should be used for mknod. JRA.
6413 status = smb_unix_mknod(conn,
6417 if (!NT_STATUS_IS_OK(status)) {
6421 status = copy_smb_filename(talloc_tos(), smb_fname,
6423 if (!NT_STATUS_IS_OK(status)) {
6427 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6428 status = map_nt_error_from_unix(errno);
6429 TALLOC_FREE(smb_fname_tmp);
6430 SMB_VFS_UNLINK(conn, smb_fname);
6434 sbuf = smb_fname_tmp->st;
6435 TALLOC_FREE(smb_fname_tmp);
6437 /* Ensure we don't try and change anything else. */
6438 raw_unixmode = SMB_MODE_NO_CHANGE;
6439 size = get_file_size_stat(&sbuf);
6440 ft.atime = sbuf.st_ex_atime;
6441 ft.mtime = sbuf.st_ex_mtime;
6443 * We continue here as we might want to change the
6446 delete_on_fail = True;
6450 /* Horrible backwards compatibility hack as an old server bug
6451 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6455 size = get_file_size_stat(&sbuf);
6460 * Deal with the UNIX specific mode set.
6463 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6464 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6465 "setting mode 0%o for file %s\n",
6466 (unsigned int)unixmode,
6467 smb_fname_str_dbg(smb_fname)));
6468 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6469 return map_nt_error_from_unix(errno);
6474 * Deal with the UNIX specific uid set.
6477 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6478 (sbuf.st_ex_uid != set_owner)) {
6481 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6482 "changing owner %u for path %s\n",
6483 (unsigned int)set_owner,
6484 smb_fname_str_dbg(smb_fname)));
6486 if (S_ISLNK(sbuf.st_ex_mode)) {
6487 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6488 set_owner, (gid_t)-1);
6490 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6491 set_owner, (gid_t)-1);
6495 status = map_nt_error_from_unix(errno);
6496 if (delete_on_fail) {
6497 SMB_VFS_UNLINK(conn, smb_fname);
6504 * Deal with the UNIX specific gid set.
6507 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6508 (sbuf.st_ex_gid != set_grp)) {
6509 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6510 "changing group %u for file %s\n",
6511 (unsigned int)set_owner,
6512 smb_fname_str_dbg(smb_fname)));
6513 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6515 status = map_nt_error_from_unix(errno);
6516 if (delete_on_fail) {
6517 SMB_VFS_UNLINK(conn, smb_fname);
6523 /* Deal with any size changes. */
6525 status = smb_set_file_size(conn, req,
6530 if (!NT_STATUS_IS_OK(status)) {
6534 /* Deal with any time changes. */
6535 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6536 /* No change, don't cancel anything. */
6540 id = vfs_file_id_from_sbuf(conn, &sbuf);
6541 for(all_fsps = file_find_di_first(id); all_fsps;
6542 all_fsps = file_find_di_next(all_fsps)) {
6544 * We're setting the time explicitly for UNIX.
6545 * Cancel any pending changes over all handles.
6547 all_fsps->update_write_time_on_close = false;
6548 TALLOC_FREE(all_fsps->update_write_time_event);
6552 * Override the "setting_write_time"
6553 * parameter here as it almost does what
6554 * we need. Just remember if we modified
6555 * mtime and send the notify ourselves.
6557 if (null_timespec(ft.mtime)) {
6558 modify_mtime = false;
6561 status = smb_set_file_time(conn,
6567 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6568 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6573 /****************************************************************************
6574 Deal with SMB_SET_FILE_UNIX_INFO2.
6575 ****************************************************************************/
6577 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6578 struct smb_request *req,
6582 const struct smb_filename *smb_fname)
6588 if (total_data < 116) {
6589 return NT_STATUS_INVALID_PARAMETER;
6592 /* Start by setting all the fields that are common between UNIX_BASIC
6595 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6597 if (!NT_STATUS_IS_OK(status)) {
6601 smb_fflags = IVAL(pdata, 108);
6602 smb_fmask = IVAL(pdata, 112);
6604 /* NB: We should only attempt to alter the file flags if the client
6605 * sends a non-zero mask.
6607 if (smb_fmask != 0) {
6608 int stat_fflags = 0;
6610 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6611 smb_fmask, &stat_fflags)) {
6612 /* Client asked to alter a flag we don't understand. */
6613 return NT_STATUS_INVALID_PARAMETER;
6616 if (fsp && fsp->fh->fd != -1) {
6617 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6618 return NT_STATUS_NOT_SUPPORTED;
6620 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
6621 stat_fflags) != 0) {
6622 return map_nt_error_from_unix(errno);
6627 /* XXX: need to add support for changing the create_time here. You
6628 * can do this for paths on Darwin with setattrlist(2). The right way
6629 * to hook this up is probably by extending the VFS utimes interface.
6632 return NT_STATUS_OK;
6635 /****************************************************************************
6636 Create a directory with POSIX semantics.
6637 ****************************************************************************/
6639 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6640 struct smb_request *req,
6644 SMB_STRUCT_STAT *psbuf,
6645 int *pdata_return_size)
6647 struct smb_filename *smb_fname;
6648 NTSTATUS status = NT_STATUS_OK;
6649 uint32 raw_unixmode = 0;
6650 uint32 mod_unixmode = 0;
6651 mode_t unixmode = (mode_t)0;
6652 files_struct *fsp = NULL;
6653 uint16 info_level_return = 0;
6655 char *pdata = *ppdata;
6657 if (total_data < 18) {
6658 return NT_STATUS_INVALID_PARAMETER;
6661 raw_unixmode = IVAL(pdata,8);
6662 /* Next 4 bytes are not yet defined. */
6664 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6665 if (!NT_STATUS_IS_OK(status)) {
6669 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6671 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6672 fname, (unsigned int)unixmode ));
6674 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
6676 if (!NT_STATUS_IS_OK(status)) {
6680 status = SMB_VFS_CREATE_FILE(
6683 0, /* root_dir_fid */
6684 smb_fname, /* fname */
6685 FILE_READ_ATTRIBUTES, /* access_mask */
6686 FILE_SHARE_NONE, /* share_access */
6687 FILE_CREATE, /* create_disposition*/
6688 FILE_DIRECTORY_FILE, /* create_options */
6689 mod_unixmode, /* file_attributes */
6690 0, /* oplock_request */
6691 0, /* allocation_size */
6697 *psbuf = smb_fname->st;
6698 TALLOC_FREE(smb_fname);
6700 if (NT_STATUS_IS_OK(status)) {
6701 close_file(req, fsp, NORMAL_CLOSE);
6704 info_level_return = SVAL(pdata,16);
6706 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6707 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6708 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6709 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6711 *pdata_return_size = 12;
6714 /* Realloc the data size */
6715 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6716 if (*ppdata == NULL) {
6717 *pdata_return_size = 0;
6718 return NT_STATUS_NO_MEMORY;
6722 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6723 SSVAL(pdata,2,0); /* No fnum. */
6724 SIVAL(pdata,4,info); /* Was directory created. */
6726 switch (info_level_return) {
6727 case SMB_QUERY_FILE_UNIX_BASIC:
6728 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6729 SSVAL(pdata,10,0); /* Padding. */
6730 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6732 case SMB_QUERY_FILE_UNIX_INFO2:
6733 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6734 SSVAL(pdata,10,0); /* Padding. */
6735 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6738 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6739 SSVAL(pdata,10,0); /* Padding. */
6746 /****************************************************************************
6747 Open/Create a file with POSIX semantics.
6748 ****************************************************************************/
6750 static NTSTATUS smb_posix_open(connection_struct *conn,
6751 struct smb_request *req,
6755 SMB_STRUCT_STAT *psbuf,
6756 int *pdata_return_size)
6758 struct smb_filename *smb_fname = NULL;
6759 bool extended_oplock_granted = False;
6760 char *pdata = *ppdata;
6762 uint32 wire_open_mode = 0;
6763 uint32 raw_unixmode = 0;
6764 uint32 mod_unixmode = 0;
6765 uint32 create_disp = 0;
6766 uint32 access_mask = 0;
6767 uint32 create_options = 0;
6768 NTSTATUS status = NT_STATUS_OK;
6769 mode_t unixmode = (mode_t)0;
6770 files_struct *fsp = NULL;
6771 int oplock_request = 0;
6773 uint16 info_level_return = 0;
6775 if (total_data < 18) {
6776 return NT_STATUS_INVALID_PARAMETER;
6779 flags = IVAL(pdata,0);
6780 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6781 if (oplock_request) {
6782 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6785 wire_open_mode = IVAL(pdata,4);
6787 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6788 return smb_posix_mkdir(conn, req,
6796 switch (wire_open_mode & SMB_ACCMODE) {
6798 access_mask = FILE_READ_DATA;
6801 access_mask = FILE_WRITE_DATA;
6804 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6807 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6808 (unsigned int)wire_open_mode ));
6809 return NT_STATUS_INVALID_PARAMETER;
6812 wire_open_mode &= ~SMB_ACCMODE;
6814 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6815 create_disp = FILE_CREATE;
6816 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6817 create_disp = FILE_OVERWRITE_IF;
6818 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6819 create_disp = FILE_OPEN_IF;
6820 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6821 create_disp = FILE_OPEN;
6823 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6824 (unsigned int)wire_open_mode ));
6825 return NT_STATUS_INVALID_PARAMETER;
6828 raw_unixmode = IVAL(pdata,8);
6829 /* Next 4 bytes are not yet defined. */
6831 status = unix_perms_from_wire(conn,
6834 VALID_STAT(*psbuf) ? 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",
6855 (unsigned int)wire_open_mode,
6856 (unsigned int)unixmode ));
6858 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
6860 if (!NT_STATUS_IS_OK(status)) {
6864 status = SMB_VFS_CREATE_FILE(
6867 0, /* root_dir_fid */
6868 smb_fname, /* fname */
6869 access_mask, /* access_mask */
6870 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6872 create_disp, /* create_disposition*/
6873 FILE_NON_DIRECTORY_FILE, /* create_options */
6874 mod_unixmode, /* file_attributes */
6875 oplock_request, /* oplock_request */
6876 0, /* allocation_size */
6882 *psbuf = smb_fname->st;
6883 TALLOC_FREE(smb_fname);
6885 if (!NT_STATUS_IS_OK(status)) {
6889 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6890 extended_oplock_granted = True;
6893 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6894 extended_oplock_granted = True;
6897 info_level_return = SVAL(pdata,16);
6899 /* Allocate the correct return size. */
6901 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6902 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6903 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6904 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6906 *pdata_return_size = 12;
6909 /* Realloc the data size */
6910 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6911 if (*ppdata == NULL) {
6912 close_file(req, fsp, ERROR_CLOSE);
6913 *pdata_return_size = 0;
6914 return NT_STATUS_NO_MEMORY;
6918 if (extended_oplock_granted) {
6919 if (flags & REQUEST_BATCH_OPLOCK) {
6920 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6922 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6924 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6925 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6927 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6930 SSVAL(pdata,2,fsp->fnum);
6931 SIVAL(pdata,4,info); /* Was file created etc. */
6933 switch (info_level_return) {
6934 case SMB_QUERY_FILE_UNIX_BASIC:
6935 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6936 SSVAL(pdata,10,0); /* padding. */
6937 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6939 case SMB_QUERY_FILE_UNIX_INFO2:
6940 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6941 SSVAL(pdata,10,0); /* padding. */
6942 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6945 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6946 SSVAL(pdata,10,0); /* padding. */
6949 return NT_STATUS_OK;
6952 /****************************************************************************
6953 Delete a file with POSIX semantics.
6954 ****************************************************************************/
6956 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6957 struct smb_request *req,
6960 struct smb_filename *smb_fname)
6962 NTSTATUS status = NT_STATUS_OK;
6963 files_struct *fsp = NULL;
6967 int create_options = 0;
6969 struct share_mode_lock *lck = NULL;
6971 if (total_data < 2) {
6972 return NT_STATUS_INVALID_PARAMETER;
6975 flags = SVAL(pdata,0);
6977 if (!VALID_STAT(smb_fname->st)) {
6978 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6981 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6982 !VALID_STAT_OF_DIR(smb_fname->st)) {
6983 return NT_STATUS_NOT_A_DIRECTORY;
6986 DEBUG(10,("smb_posix_unlink: %s %s\n",
6987 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6988 smb_fname_str_dbg(smb_fname)));
6990 if (VALID_STAT_OF_DIR(smb_fname->st)) {
6991 create_options |= FILE_DIRECTORY_FILE;
6994 status = SMB_VFS_CREATE_FILE(
6997 0, /* root_dir_fid */
6998 smb_fname, /* fname */
6999 DELETE_ACCESS, /* access_mask */
7000 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7002 FILE_OPEN, /* create_disposition*/
7003 create_options, /* create_options */
7004 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7005 0, /* oplock_request */
7006 0, /* allocation_size */
7012 if (!NT_STATUS_IS_OK(status)) {
7017 * Don't lie to client. If we can't really delete due to
7018 * non-POSIX opens return SHARING_VIOLATION.
7021 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7024 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7025 "lock for file %s\n", fsp_str_dbg(fsp)));
7026 close_file(req, fsp, NORMAL_CLOSE);
7027 return NT_STATUS_INVALID_PARAMETER;
7031 * See if others still have the file open. If this is the case, then
7032 * don't delete. If all opens are POSIX delete we can set the delete
7033 * on close disposition.
7035 for (i=0; i<lck->num_share_modes; i++) {
7036 struct share_mode_entry *e = &lck->share_modes[i];
7037 if (is_valid_share_mode_entry(e)) {
7038 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7041 /* Fail with sharing violation. */
7042 close_file(req, fsp, NORMAL_CLOSE);
7044 return NT_STATUS_SHARING_VIOLATION;
7049 * Set the delete on close.
7051 status = smb_set_file_disposition_info(conn,
7057 if (!NT_STATUS_IS_OK(status)) {
7058 close_file(req, fsp, NORMAL_CLOSE);
7063 return close_file(req, fsp, NORMAL_CLOSE);
7066 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7067 struct smb_request *req,
7068 TALLOC_CTX *mem_ctx,
7069 uint16_t info_level,
7071 struct smb_filename *smb_fname,
7072 char **ppdata, int total_data,
7075 char *pdata = *ppdata;
7076 SMB_STRUCT_STAT sbuf;
7078 NTSTATUS status = NT_STATUS_OK;
7079 int data_return_size = 0;
7083 /* Set sbuf for use below. */
7084 sbuf = smb_fname->st;
7086 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7087 return NT_STATUS_INVALID_LEVEL;
7090 if (!CAN_WRITE(conn)) {
7091 /* Allow POSIX opens. The open path will deny
7092 * any non-readonly opens. */
7093 if (info_level != SMB_POSIX_PATH_OPEN) {
7094 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7098 status = get_full_smb_filename(mem_ctx, smb_fname, &fname);
7099 if (!NT_STATUS_IS_OK(status)) {
7103 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d totdata=%d\n",
7104 fname, fsp ? fsp->fnum : -1, info_level, total_data));
7106 switch (info_level) {
7108 case SMB_INFO_STANDARD:
7110 status = smb_set_info_standard(conn,
7118 case SMB_INFO_SET_EA:
7120 status = smb_info_set_ea(conn,
7128 case SMB_SET_FILE_BASIC_INFO:
7129 case SMB_FILE_BASIC_INFORMATION:
7131 status = smb_set_file_basic_info(conn,
7139 case SMB_FILE_ALLOCATION_INFORMATION:
7140 case SMB_SET_FILE_ALLOCATION_INFO:
7142 status = smb_set_file_allocation_info(conn, req,
7150 case SMB_FILE_END_OF_FILE_INFORMATION:
7151 case SMB_SET_FILE_END_OF_FILE_INFO:
7153 status = smb_set_file_end_of_file_info(conn, req,
7161 case SMB_FILE_DISPOSITION_INFORMATION:
7162 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7165 /* JRA - We used to just ignore this on a path ?
7166 * Shouldn't this be invalid level on a pathname
7169 if (tran_call != TRANSACT2_SETFILEINFO) {
7170 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7173 status = smb_set_file_disposition_info(conn,
7181 case SMB_FILE_POSITION_INFORMATION:
7183 status = smb_file_position_information(conn,
7190 /* From tridge Samba4 :
7191 * MODE_INFORMATION in setfileinfo (I have no
7192 * idea what "mode information" on a file is - it takes a value of 0,
7193 * 2, 4 or 6. What could it be?).
7196 case SMB_FILE_MODE_INFORMATION:
7198 status = smb_file_mode_information(conn,
7205 * CIFS UNIX extensions.
7208 case SMB_SET_FILE_UNIX_BASIC:
7210 status = smb_set_file_unix_basic(conn, req,
7218 case SMB_SET_FILE_UNIX_INFO2:
7220 status = smb_set_file_unix_info2(conn, req,
7228 case SMB_SET_FILE_UNIX_LINK:
7231 /* We must have a pathname for this. */
7232 return NT_STATUS_INVALID_LEVEL;
7234 status = smb_set_file_unix_link(conn, req, pdata,
7239 case SMB_SET_FILE_UNIX_HLINK:
7242 /* We must have a pathname for this. */
7243 return NT_STATUS_INVALID_LEVEL;
7245 status = smb_set_file_unix_hlink(conn, req,
7251 case SMB_FILE_RENAME_INFORMATION:
7253 status = smb_file_rename_information(conn, req,
7259 #if defined(HAVE_POSIX_ACLS)
7260 case SMB_SET_POSIX_ACL:
7262 status = smb_set_posix_acl(conn,
7272 case SMB_SET_POSIX_LOCK:
7275 return NT_STATUS_INVALID_LEVEL;
7277 status = smb_set_posix_lock(conn, req,
7278 pdata, total_data, fsp);
7282 case SMB_POSIX_PATH_OPEN:
7285 /* We must have a pathname for this. */
7286 return NT_STATUS_INVALID_LEVEL;
7289 status = smb_posix_open(conn, req,
7298 case SMB_POSIX_PATH_UNLINK:
7301 /* We must have a pathname for this. */
7302 return NT_STATUS_INVALID_LEVEL;
7305 status = smb_posix_unlink(conn, req,
7313 return NT_STATUS_INVALID_LEVEL;
7316 if (!NT_STATUS_IS_OK(status)) {
7320 *ret_data_size = data_return_size;
7321 return NT_STATUS_OK;
7324 /****************************************************************************
7325 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7326 ****************************************************************************/
7328 static void call_trans2setfilepathinfo(connection_struct *conn,
7329 struct smb_request *req,
7330 unsigned int tran_call,
7331 char **pparams, int total_params,
7332 char **ppdata, int total_data,
7333 unsigned int max_data_bytes)
7335 char *params = *pparams;
7336 char *pdata = *ppdata;
7338 struct smb_filename *smb_fname = NULL;
7339 files_struct *fsp = NULL;
7340 NTSTATUS status = NT_STATUS_OK;
7341 int data_return_size = 0;
7344 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7348 if (tran_call == TRANSACT2_SETFILEINFO) {
7349 if (total_params < 4) {
7350 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7354 fsp = file_fsp(req, SVAL(params,0));
7355 /* Basic check for non-null fsp. */
7356 if (!check_fsp_open(conn, req, fsp)) {
7359 info_level = SVAL(params,2);
7361 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7363 if (!NT_STATUS_IS_OK(status)) {
7364 reply_nterror(req, status);
7368 if(fsp->is_directory || fsp->fh->fd == -1) {
7370 * This is actually a SETFILEINFO on a directory
7371 * handle (returned from an NT SMB). NT5.0 seems
7372 * to do this call. JRA.
7374 if (INFO_LEVEL_IS_UNIX(info_level)) {
7375 /* Always do lstat for UNIX calls. */
7376 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7377 DEBUG(3,("call_trans2setfilepathinfo: "
7378 "SMB_VFS_LSTAT of %s failed "
7380 smb_fname_str_dbg(smb_fname),
7382 reply_nterror(req, map_nt_error_from_unix(errno));
7386 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7387 DEBUG(3,("call_trans2setfilepathinfo: "
7388 "fileinfo of %s failed (%s)\n",
7389 smb_fname_str_dbg(smb_fname),
7391 reply_nterror(req, map_nt_error_from_unix(errno));
7395 } else if (fsp->print_file) {
7397 * Doing a DELETE_ON_CLOSE should cancel a print job.
7399 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7400 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
7402 DEBUG(3,("call_trans2setfilepathinfo: "
7403 "Cancelling print job (%s)\n",
7407 send_trans2_replies(conn, req, params, 2,
7412 reply_doserror(req, ERRDOS, ERRbadpath);
7417 * Original code - this is an open file.
7419 if (!check_fsp(conn, req, fsp)) {
7423 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7424 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7425 "of fnum %d failed (%s)\n", fsp->fnum,
7427 reply_nterror(req, map_nt_error_from_unix(errno));
7435 if (total_params < 7) {
7436 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7440 info_level = SVAL(params,0);
7441 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
7442 total_params - 6, STR_TERMINATE,
7444 if (!NT_STATUS_IS_OK(status)) {
7445 reply_nterror(req, status);
7449 status = filename_convert(req, conn,
7450 req->flags2 & FLAGS2_DFS_PATHNAMES,
7453 if (!NT_STATUS_IS_OK(status)) {
7454 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7455 reply_botherror(req,
7456 NT_STATUS_PATH_NOT_COVERED,
7457 ERRSRV, ERRbadpath);
7460 reply_nterror(req, status);
7464 if (INFO_LEVEL_IS_UNIX(info_level)) {
7466 * For CIFS UNIX extensions the target name may not exist.
7469 /* Always do lstat for UNIX calls. */
7470 SMB_VFS_LSTAT(conn, smb_fname);
7472 } else if (!VALID_STAT(smb_fname->st) &&
7473 SMB_VFS_STAT(conn, smb_fname)) {
7474 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7476 smb_fname_str_dbg(smb_fname),
7478 reply_nterror(req, map_nt_error_from_unix(errno));
7483 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7484 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
7485 fsp ? fsp->fnum : -1, info_level,total_data));
7487 /* Realloc the parameter size */
7488 *pparams = (char *)SMB_REALLOC(*pparams,2);
7489 if (*pparams == NULL) {
7490 reply_nterror(req, NT_STATUS_NO_MEMORY);
7497 status = smbd_do_setfilepathinfo(conn, req, req,
7503 if (!NT_STATUS_IS_OK(status)) {
7504 if (open_was_deferred(req->mid)) {
7505 /* We have re-scheduled this call. */
7508 if (blocking_lock_was_deferred(req->mid)) {
7509 /* We have re-scheduled this call. */
7512 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7513 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7514 ERRSRV, ERRbadpath);
7517 if (info_level == SMB_POSIX_PATH_OPEN) {
7518 reply_openerror(req, status);
7522 reply_nterror(req, status);
7526 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7532 /****************************************************************************
7533 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7534 ****************************************************************************/
7536 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7537 char **pparams, int total_params,
7538 char **ppdata, int total_data,
7539 unsigned int max_data_bytes)
7541 struct smb_filename *smb_dname = NULL;
7542 char *params = *pparams;
7543 char *pdata = *ppdata;
7544 char *directory = NULL;
7545 NTSTATUS status = NT_STATUS_OK;
7546 struct ea_list *ea_list = NULL;
7547 TALLOC_CTX *ctx = talloc_tos();
7549 if (!CAN_WRITE(conn)) {
7550 reply_doserror(req, ERRSRV, ERRaccess);
7554 if (total_params < 5) {
7555 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7559 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7560 total_params - 4, STR_TERMINATE,
7562 if (!NT_STATUS_IS_OK(status)) {
7563 reply_nterror(req, status);
7567 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7569 status = filename_convert(ctx,
7571 req->flags2 & FLAGS2_DFS_PATHNAMES,
7575 if (!NT_STATUS_IS_OK(status)) {
7576 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7577 reply_botherror(req,
7578 NT_STATUS_PATH_NOT_COVERED,
7579 ERRSRV, ERRbadpath);
7582 reply_nterror(req, status);
7586 /* Any data in this call is an EA list. */
7587 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7588 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7593 * OS/2 workplace shell seems to send SET_EA requests of "null"
7594 * length (4 bytes containing IVAL 4).
7595 * They seem to have no effect. Bug #3212. JRA.
7598 if (total_data != 4) {
7599 if (total_data < 10) {
7600 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7604 if (IVAL(pdata,0) > total_data) {
7605 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7606 IVAL(pdata,0), (unsigned int)total_data));
7607 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7611 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7614 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7618 /* If total_data == 4 Windows doesn't care what values
7619 * are placed in that field, it just ignores them.
7620 * The System i QNTC IBM SMB client puts bad values here,
7621 * so ignore them. */
7623 status = create_directory(conn, req, smb_dname);
7625 if (!NT_STATUS_IS_OK(status)) {
7626 reply_nterror(req, status);
7630 /* Try and set any given EA. */
7632 status = set_ea(conn, NULL, smb_dname, ea_list);
7633 if (!NT_STATUS_IS_OK(status)) {
7634 reply_nterror(req, status);
7639 /* Realloc the parameter and data sizes */
7640 *pparams = (char *)SMB_REALLOC(*pparams,2);
7641 if(*pparams == NULL) {
7642 reply_nterror(req, NT_STATUS_NO_MEMORY);
7649 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7652 TALLOC_FREE(smb_dname);
7656 /****************************************************************************
7657 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7658 We don't actually do this - we just send a null response.
7659 ****************************************************************************/
7661 static void call_trans2findnotifyfirst(connection_struct *conn,
7662 struct smb_request *req,
7663 char **pparams, int total_params,
7664 char **ppdata, int total_data,
7665 unsigned int max_data_bytes)
7667 char *params = *pparams;
7670 if (total_params < 6) {
7671 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7675 info_level = SVAL(params,4);
7676 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7678 switch (info_level) {
7683 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7687 /* Realloc the parameter and data sizes */
7688 *pparams = (char *)SMB_REALLOC(*pparams,6);
7689 if (*pparams == NULL) {
7690 reply_nterror(req, NT_STATUS_NO_MEMORY);
7695 SSVAL(params,0,fnf_handle);
7696 SSVAL(params,2,0); /* No changes */
7697 SSVAL(params,4,0); /* No EA errors */
7704 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7709 /****************************************************************************
7710 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7711 changes). Currently this does nothing.
7712 ****************************************************************************/
7714 static void call_trans2findnotifynext(connection_struct *conn,
7715 struct smb_request *req,
7716 char **pparams, int total_params,
7717 char **ppdata, int total_data,
7718 unsigned int max_data_bytes)
7720 char *params = *pparams;
7722 DEBUG(3,("call_trans2findnotifynext\n"));
7724 /* Realloc the parameter and data sizes */
7725 *pparams = (char *)SMB_REALLOC(*pparams,4);
7726 if (*pparams == NULL) {
7727 reply_nterror(req, NT_STATUS_NO_MEMORY);
7732 SSVAL(params,0,0); /* No changes */
7733 SSVAL(params,2,0); /* No EA errors */
7735 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7740 /****************************************************************************
7741 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7742 ****************************************************************************/
7744 static void call_trans2getdfsreferral(connection_struct *conn,
7745 struct smb_request *req,
7746 char **pparams, int total_params,
7747 char **ppdata, int total_data,
7748 unsigned int max_data_bytes)
7750 char *params = *pparams;
7751 char *pathname = NULL;
7753 int max_referral_level;
7754 NTSTATUS status = NT_STATUS_OK;
7755 TALLOC_CTX *ctx = talloc_tos();
7757 DEBUG(10,("call_trans2getdfsreferral\n"));
7759 if (total_params < 3) {
7760 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7764 max_referral_level = SVAL(params,0);
7766 if(!lp_host_msdfs()) {
7767 reply_doserror(req, ERRDOS, ERRbadfunc);
7771 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7772 total_params - 2, STR_TERMINATE);
7774 reply_nterror(req, NT_STATUS_NOT_FOUND);
7777 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7778 ppdata,&status)) < 0) {
7779 reply_nterror(req, status);
7783 SSVAL(req->inbuf, smb_flg2,
7784 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7785 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7790 #define LMCAT_SPL 0x53
7791 #define LMFUNC_GETJOBID 0x60
7793 /****************************************************************************
7794 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7795 ****************************************************************************/
7797 static void call_trans2ioctl(connection_struct *conn,
7798 struct smb_request *req,
7799 char **pparams, int total_params,
7800 char **ppdata, int total_data,
7801 unsigned int max_data_bytes)
7803 char *pdata = *ppdata;
7804 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7806 /* check for an invalid fid before proceeding */
7809 reply_doserror(req, ERRDOS, ERRbadfid);
7813 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7814 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7815 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7816 if (*ppdata == NULL) {
7817 reply_nterror(req, NT_STATUS_NO_MEMORY);
7822 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7823 CAN ACCEPT THIS IN UNICODE. JRA. */
7825 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7826 srvstr_push(pdata, req->flags2, pdata + 2,
7827 global_myname(), 15,
7828 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7829 srvstr_push(pdata, req->flags2, pdata+18,
7830 lp_servicename(SNUM(conn)), 13,
7831 STR_ASCII|STR_TERMINATE); /* Service name */
7832 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7837 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7838 reply_doserror(req, ERRSRV, ERRerror);
7841 /****************************************************************************
7842 Reply to a SMBfindclose (stop trans2 directory search).
7843 ****************************************************************************/
7845 void reply_findclose(struct smb_request *req)
7849 START_PROFILE(SMBfindclose);
7852 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7853 END_PROFILE(SMBfindclose);
7857 dptr_num = SVALS(req->vwv+0, 0);
7859 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7861 dptr_close(&dptr_num);
7863 reply_outbuf(req, 0, 0);
7865 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7867 END_PROFILE(SMBfindclose);
7871 /****************************************************************************
7872 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7873 ****************************************************************************/
7875 void reply_findnclose(struct smb_request *req)
7879 START_PROFILE(SMBfindnclose);
7882 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7883 END_PROFILE(SMBfindnclose);
7887 dptr_num = SVAL(req->vwv+0, 0);
7889 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7891 /* We never give out valid handles for a
7892 findnotifyfirst - so any dptr_num is ok here.
7895 reply_outbuf(req, 0, 0);
7897 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7899 END_PROFILE(SMBfindnclose);
7903 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7904 struct trans_state *state)
7906 if (Protocol >= PROTOCOL_NT1) {
7907 req->flags2 |= 0x40; /* IS_LONG_NAME */
7908 SSVAL(req->inbuf,smb_flg2,req->flags2);
7911 if (conn->encrypt_level == Required && !req->encrypted) {
7912 if (state->call != TRANSACT2_QFSINFO &&
7913 state->call != TRANSACT2_SETFSINFO) {
7914 DEBUG(0,("handle_trans2: encryption required "
7916 (unsigned int)state->call));
7917 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7922 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
7924 /* Now we must call the relevant TRANS2 function */
7925 switch(state->call) {
7926 case TRANSACT2_OPEN:
7928 START_PROFILE(Trans2_open);
7929 call_trans2open(conn, req,
7930 &state->param, state->total_param,
7931 &state->data, state->total_data,
7932 state->max_data_return);
7933 END_PROFILE(Trans2_open);
7937 case TRANSACT2_FINDFIRST:
7939 START_PROFILE(Trans2_findfirst);
7940 call_trans2findfirst(conn, req,
7941 &state->param, state->total_param,
7942 &state->data, state->total_data,
7943 state->max_data_return);
7944 END_PROFILE(Trans2_findfirst);
7948 case TRANSACT2_FINDNEXT:
7950 START_PROFILE(Trans2_findnext);
7951 call_trans2findnext(conn, req,
7952 &state->param, state->total_param,
7953 &state->data, state->total_data,
7954 state->max_data_return);
7955 END_PROFILE(Trans2_findnext);
7959 case TRANSACT2_QFSINFO:
7961 START_PROFILE(Trans2_qfsinfo);
7962 call_trans2qfsinfo(conn, req,
7963 &state->param, state->total_param,
7964 &state->data, state->total_data,
7965 state->max_data_return);
7966 END_PROFILE(Trans2_qfsinfo);
7970 case TRANSACT2_SETFSINFO:
7972 START_PROFILE(Trans2_setfsinfo);
7973 call_trans2setfsinfo(conn, req,
7974 &state->param, state->total_param,
7975 &state->data, state->total_data,
7976 state->max_data_return);
7977 END_PROFILE(Trans2_setfsinfo);
7981 case TRANSACT2_QPATHINFO:
7982 case TRANSACT2_QFILEINFO:
7984 START_PROFILE(Trans2_qpathinfo);
7985 call_trans2qfilepathinfo(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_qpathinfo);
7993 case TRANSACT2_SETPATHINFO:
7994 case TRANSACT2_SETFILEINFO:
7996 START_PROFILE(Trans2_setpathinfo);
7997 call_trans2setfilepathinfo(conn, req, state->call,
7998 &state->param, state->total_param,
7999 &state->data, state->total_data,
8000 state->max_data_return);
8001 END_PROFILE(Trans2_setpathinfo);
8005 case TRANSACT2_FINDNOTIFYFIRST:
8007 START_PROFILE(Trans2_findnotifyfirst);
8008 call_trans2findnotifyfirst(conn, req,
8009 &state->param, state->total_param,
8010 &state->data, state->total_data,
8011 state->max_data_return);
8012 END_PROFILE(Trans2_findnotifyfirst);
8016 case TRANSACT2_FINDNOTIFYNEXT:
8018 START_PROFILE(Trans2_findnotifynext);
8019 call_trans2findnotifynext(conn, req,
8020 &state->param, state->total_param,
8021 &state->data, state->total_data,
8022 state->max_data_return);
8023 END_PROFILE(Trans2_findnotifynext);
8027 case TRANSACT2_MKDIR:
8029 START_PROFILE(Trans2_mkdir);
8030 call_trans2mkdir(conn, req,
8031 &state->param, state->total_param,
8032 &state->data, state->total_data,
8033 state->max_data_return);
8034 END_PROFILE(Trans2_mkdir);
8038 case TRANSACT2_GET_DFS_REFERRAL:
8040 START_PROFILE(Trans2_get_dfs_referral);
8041 call_trans2getdfsreferral(conn, req,
8042 &state->param, state->total_param,
8043 &state->data, state->total_data,
8044 state->max_data_return);
8045 END_PROFILE(Trans2_get_dfs_referral);
8049 case TRANSACT2_IOCTL:
8051 START_PROFILE(Trans2_ioctl);
8052 call_trans2ioctl(conn, req,
8053 &state->param, state->total_param,
8054 &state->data, state->total_data,
8055 state->max_data_return);
8056 END_PROFILE(Trans2_ioctl);
8061 /* Error in request */
8062 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8063 reply_doserror(req, ERRSRV,ERRerror);
8067 /****************************************************************************
8068 Reply to a SMBtrans2.
8069 ****************************************************************************/
8071 void reply_trans2(struct smb_request *req)
8073 connection_struct *conn = req->conn;
8078 unsigned int tran_call;
8079 struct trans_state *state;
8082 START_PROFILE(SMBtrans2);
8084 if (req->wct < 14) {
8085 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8086 END_PROFILE(SMBtrans2);
8090 dsoff = SVAL(req->vwv+12, 0);
8091 dscnt = SVAL(req->vwv+11, 0);
8092 psoff = SVAL(req->vwv+10, 0);
8093 pscnt = SVAL(req->vwv+9, 0);
8094 tran_call = SVAL(req->vwv+14, 0);
8096 result = allow_new_trans(conn->pending_trans, req->mid);
8097 if (!NT_STATUS_IS_OK(result)) {
8098 DEBUG(2, ("Got invalid trans2 request: %s\n",
8099 nt_errstr(result)));
8100 reply_nterror(req, result);
8101 END_PROFILE(SMBtrans2);
8106 switch (tran_call) {
8107 /* List the allowed trans2 calls on IPC$ */
8108 case TRANSACT2_OPEN:
8109 case TRANSACT2_GET_DFS_REFERRAL:
8110 case TRANSACT2_QFILEINFO:
8111 case TRANSACT2_QFSINFO:
8112 case TRANSACT2_SETFSINFO:
8115 reply_doserror(req, ERRSRV, ERRaccess);
8116 END_PROFILE(SMBtrans2);
8121 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8122 DEBUG(0, ("talloc failed\n"));
8123 reply_nterror(req, NT_STATUS_NO_MEMORY);
8124 END_PROFILE(SMBtrans2);
8128 state->cmd = SMBtrans2;
8130 state->mid = req->mid;
8131 state->vuid = req->vuid;
8132 state->setup_count = SVAL(req->vwv+13, 0);
8133 state->setup = NULL;
8134 state->total_param = SVAL(req->vwv+0, 0);
8135 state->param = NULL;
8136 state->total_data = SVAL(req->vwv+1, 0);
8138 state->max_param_return = SVAL(req->vwv+2, 0);
8139 state->max_data_return = SVAL(req->vwv+3, 0);
8140 state->max_setup_return = SVAL(req->vwv+4, 0);
8141 state->close_on_completion = BITSETW(req->vwv+5, 0);
8142 state->one_way = BITSETW(req->vwv+5, 1);
8144 state->call = tran_call;
8146 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8147 is so as a sanity check */
8148 if (state->setup_count != 1) {
8150 * Need to have rc=0 for ioctl to get job id for OS/2.
8151 * Network printing will fail if function is not successful.
8152 * Similar function in reply.c will be used if protocol
8153 * is LANMAN1.0 instead of LM1.2X002.
8154 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8155 * outbuf doesn't have to be set(only job id is used).
8157 if ( (state->setup_count == 4)
8158 && (tran_call == TRANSACT2_IOCTL)
8159 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8160 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8161 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8163 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8164 DEBUG(2,("Transaction is %d\n",tran_call));
8166 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8167 END_PROFILE(SMBtrans2);
8172 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8175 if (state->total_data) {
8177 if (trans_oob(state->total_data, 0, dscnt)
8178 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8182 /* Can't use talloc here, the core routines do realloc on the
8183 * params and data. */
8184 state->data = (char *)SMB_MALLOC(state->total_data);
8185 if (state->data == NULL) {
8186 DEBUG(0,("reply_trans2: data malloc fail for %u "
8187 "bytes !\n", (unsigned int)state->total_data));
8189 reply_nterror(req, NT_STATUS_NO_MEMORY);
8190 END_PROFILE(SMBtrans2);
8194 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8197 if (state->total_param) {
8199 if (trans_oob(state->total_param, 0, pscnt)
8200 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8204 /* Can't use talloc here, the core routines do realloc on the
8205 * params and data. */
8206 state->param = (char *)SMB_MALLOC(state->total_param);
8207 if (state->param == NULL) {
8208 DEBUG(0,("reply_trans: param malloc fail for %u "
8209 "bytes !\n", (unsigned int)state->total_param));
8210 SAFE_FREE(state->data);
8212 reply_nterror(req, NT_STATUS_NO_MEMORY);
8213 END_PROFILE(SMBtrans2);
8217 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8220 state->received_data = dscnt;
8221 state->received_param = pscnt;
8223 if ((state->received_param == state->total_param) &&
8224 (state->received_data == state->total_data)) {
8226 handle_trans2(conn, req, state);
8228 SAFE_FREE(state->data);
8229 SAFE_FREE(state->param);
8231 END_PROFILE(SMBtrans2);
8235 DLIST_ADD(conn->pending_trans, state);
8237 /* We need to send an interim response then receive the rest
8238 of the parameter/data bytes */
8239 reply_outbuf(req, 0, 0);
8240 show_msg((char *)req->outbuf);
8241 END_PROFILE(SMBtrans2);
8246 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8247 SAFE_FREE(state->data);
8248 SAFE_FREE(state->param);
8250 END_PROFILE(SMBtrans2);
8251 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8255 /****************************************************************************
8256 Reply to a SMBtranss2
8257 ****************************************************************************/
8259 void reply_transs2(struct smb_request *req)
8261 connection_struct *conn = req->conn;
8262 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8263 struct trans_state *state;
8265 START_PROFILE(SMBtranss2);
8267 show_msg((char *)req->inbuf);
8270 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8271 END_PROFILE(SMBtranss2);
8275 for (state = conn->pending_trans; state != NULL;
8276 state = state->next) {
8277 if (state->mid == req->mid) {
8282 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8283 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8284 END_PROFILE(SMBtranss2);
8288 /* Revise state->total_param and state->total_data in case they have
8289 changed downwards */
8291 if (SVAL(req->vwv+0, 0) < state->total_param)
8292 state->total_param = SVAL(req->vwv+0, 0);
8293 if (SVAL(req->vwv+1, 0) < state->total_data)
8294 state->total_data = SVAL(req->vwv+1, 0);
8296 pcnt = SVAL(req->vwv+2, 0);
8297 poff = SVAL(req->vwv+3, 0);
8298 pdisp = SVAL(req->vwv+4, 0);
8300 dcnt = SVAL(req->vwv+5, 0);
8301 doff = SVAL(req->vwv+6, 0);
8302 ddisp = SVAL(req->vwv+7, 0);
8304 state->received_param += pcnt;
8305 state->received_data += dcnt;
8307 if ((state->received_data > state->total_data) ||
8308 (state->received_param > state->total_param))
8312 if (trans_oob(state->total_param, pdisp, pcnt)
8313 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8316 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8320 if (trans_oob(state->total_data, ddisp, dcnt)
8321 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8324 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8327 if ((state->received_param < state->total_param) ||
8328 (state->received_data < state->total_data)) {
8329 END_PROFILE(SMBtranss2);
8333 handle_trans2(conn, req, state);
8335 DLIST_REMOVE(conn->pending_trans, state);
8336 SAFE_FREE(state->data);
8337 SAFE_FREE(state->param);
8340 END_PROFILE(SMBtranss2);
8345 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8346 DLIST_REMOVE(conn->pending_trans, state);
8347 SAFE_FREE(state->data);
8348 SAFE_FREE(state->param);
8350 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8351 END_PROFILE(SMBtranss2);