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 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
3998 info_level, max_data_bytes));
4001 mode = dos_mode_msdfs(conn, smb_fname);
4003 mode = dos_mode(conn, smb_fname);
4006 mode = FILE_ATTRIBUTE_NORMAL;
4008 nlink = sbuf.st_ex_nlink;
4010 if (nlink && (mode&aDIR)) {
4014 if ((nlink > 0) && delete_pending) {
4018 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4019 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4020 if (*ppdata == NULL) {
4021 return NT_STATUS_NO_MEMORY;
4025 dend = dstart + data_size - 1;
4027 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4028 update_stat_ex_mtime(&sbuf, write_time_ts);
4031 create_time_ts = sbuf.st_ex_btime;
4032 mtime_ts = sbuf.st_ex_mtime;
4033 atime_ts = sbuf.st_ex_atime;
4035 if (lp_dos_filetime_resolution(SNUM(conn))) {
4036 dos_filetime_timespec(&create_time_ts);
4037 dos_filetime_timespec(&mtime_ts);
4038 dos_filetime_timespec(&atime_ts);
4041 create_time = convert_timespec_to_time_t(create_time_ts);
4042 mtime = convert_timespec_to_time_t(mtime_ts);
4043 atime = convert_timespec_to_time_t(atime_ts);
4045 p = strrchr_m(smb_fname->base_name,'/');
4047 base_name = smb_fname->base_name;
4051 /* NT expects the name to be in an exact form of the *full*
4052 filename. See the trans2 torture test */
4053 if (ISDOT(base_name)) {
4054 dos_fname = talloc_strdup(mem_ctx, "\\");
4056 return NT_STATUS_NO_MEMORY;
4059 dos_fname = talloc_asprintf(mem_ctx,
4063 return NT_STATUS_NO_MEMORY;
4065 string_replace(dos_fname, '/', '\\');
4068 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &sbuf);
4071 /* Do we have this path open ? */
4073 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4074 fsp1 = file_find_di_first(fileid);
4075 if (fsp1 && fsp1->initial_allocation_size) {
4076 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
4080 if (!(mode & aDIR)) {
4081 file_size = get_file_size_stat(&sbuf);
4085 pos = fsp->fh->position_information;
4089 access_mask = fsp->access_mask;
4091 /* GENERIC_EXECUTE mapping from Windows */
4092 access_mask = 0x12019F;
4095 /* This should be an index number - looks like
4098 I think this causes us to fail the IFSKIT
4099 BasicFileInformationTest. -tpot */
4100 file_index = ((sbuf.st_ex_ino) & UINT32_MAX); /* FileIndexLow */
4101 file_index |= ((uint64_t)((sbuf.st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
4103 switch (info_level) {
4104 case SMB_INFO_STANDARD:
4105 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4107 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4108 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4109 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4110 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4111 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4112 SSVAL(pdata,l1_attrFile,mode);
4115 case SMB_INFO_QUERY_EA_SIZE:
4117 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4118 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4120 srv_put_dos_date2(pdata,0,create_time);
4121 srv_put_dos_date2(pdata,4,atime);
4122 srv_put_dos_date2(pdata,8,mtime); /* write time */
4123 SIVAL(pdata,12,(uint32)file_size);
4124 SIVAL(pdata,16,(uint32)allocation_size);
4125 SSVAL(pdata,20,mode);
4126 SIVAL(pdata,22,ea_size);
4130 case SMB_INFO_IS_NAME_VALID:
4131 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4133 /* os/2 needs this ? really ?*/
4134 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4136 /* This is only reached for qpathinfo */
4140 case SMB_INFO_QUERY_EAS_FROM_LIST:
4142 size_t total_ea_len = 0;
4143 struct ea_list *ea_file_list = NULL;
4145 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4147 ea_file_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
4148 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4150 if (!ea_list || (total_ea_len > data_size)) {
4152 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4156 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4160 case SMB_INFO_QUERY_ALL_EAS:
4162 /* We have data_size bytes to put EA's into. */
4163 size_t total_ea_len = 0;
4165 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4167 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
4168 if (!ea_list || (total_ea_len > data_size)) {
4170 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4174 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4178 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4180 /* We have data_size bytes to put EA's into. */
4181 size_t total_ea_len = 0;
4182 struct ea_list *ea_file_list = NULL;
4184 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4186 /*TODO: add filtering and index handling */
4188 ea_file_list = get_ea_list_from_file(mem_ctx,
4192 if (!ea_file_list) {
4193 return NT_STATUS_NO_EAS_ON_FILE;
4196 status = fill_ea_chained_buffer(mem_ctx,
4200 conn, ea_file_list);
4201 if (!NT_STATUS_IS_OK(status)) {
4207 case SMB_FILE_BASIC_INFORMATION:
4208 case SMB_QUERY_FILE_BASIC_INFO:
4210 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4211 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4212 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4214 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4218 put_long_date_timespec(pdata,create_time_ts);
4219 put_long_date_timespec(pdata+8,atime_ts);
4220 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4221 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4222 SIVAL(pdata,32,mode);
4224 DEBUG(5,("SMB_QFBI - "));
4225 DEBUG(5,("create: %s ", ctime(&create_time)));
4226 DEBUG(5,("access: %s ", ctime(&atime)));
4227 DEBUG(5,("write: %s ", ctime(&mtime)));
4228 DEBUG(5,("change: %s ", ctime(&mtime)));
4229 DEBUG(5,("mode: %x\n", mode));
4232 case SMB_FILE_STANDARD_INFORMATION:
4233 case SMB_QUERY_FILE_STANDARD_INFO:
4235 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4237 SOFF_T(pdata,0,allocation_size);
4238 SOFF_T(pdata,8,file_size);
4239 SIVAL(pdata,16,nlink);
4240 SCVAL(pdata,20,delete_pending?1:0);
4241 SCVAL(pdata,21,(mode&aDIR)?1:0);
4242 SSVAL(pdata,22,0); /* Padding. */
4245 case SMB_FILE_EA_INFORMATION:
4246 case SMB_QUERY_FILE_EA_INFO:
4248 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4249 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4251 SIVAL(pdata,0,ea_size);
4255 /* Get the 8.3 name - used if NT SMB was negotiated. */
4256 case SMB_QUERY_FILE_ALT_NAME_INFO:
4257 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4260 char mangled_name[13];
4261 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4262 if (!name_to_8_3(base_name,mangled_name,
4263 True,conn->params)) {
4264 return NT_STATUS_NO_MEMORY;
4266 len = srvstr_push(dstart, flags2,
4267 pdata+4, mangled_name,
4268 PTR_DIFF(dend, pdata+4),
4270 data_size = 4 + len;
4275 case SMB_QUERY_FILE_NAME_INFO:
4279 this must be *exactly* right for ACLs on mapped drives to work
4281 len = srvstr_push(dstart, flags2,
4283 PTR_DIFF(dend, pdata+4),
4285 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4286 data_size = 4 + len;
4291 case SMB_FILE_ALLOCATION_INFORMATION:
4292 case SMB_QUERY_FILE_ALLOCATION_INFO:
4293 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4295 SOFF_T(pdata,0,allocation_size);
4298 case SMB_FILE_END_OF_FILE_INFORMATION:
4299 case SMB_QUERY_FILE_END_OF_FILEINFO:
4300 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4302 SOFF_T(pdata,0,file_size);
4305 case SMB_QUERY_FILE_ALL_INFO:
4306 case SMB_FILE_ALL_INFORMATION:
4309 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4310 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4311 put_long_date_timespec(pdata,create_time_ts);
4312 put_long_date_timespec(pdata+8,atime_ts);
4313 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4314 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4315 SIVAL(pdata,32,mode);
4316 SIVAL(pdata,36,0); /* padding. */
4318 SOFF_T(pdata,0,allocation_size);
4319 SOFF_T(pdata,8,file_size);
4320 SIVAL(pdata,16,nlink);
4321 SCVAL(pdata,20,delete_pending);
4322 SCVAL(pdata,21,(mode&aDIR)?1:0);
4325 SIVAL(pdata,0,ea_size);
4326 pdata += 4; /* EA info */
4327 len = srvstr_push(dstart, flags2,
4329 PTR_DIFF(dend, pdata+4),
4333 data_size = PTR_DIFF(pdata,(*ppdata));
4337 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4340 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4341 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4342 put_long_date_timespec(pdata+0x00,create_time_ts);
4343 put_long_date_timespec(pdata+0x08,atime_ts);
4344 put_long_date_timespec(pdata+0x10,mtime_ts); /* write time */
4345 put_long_date_timespec(pdata+0x18,mtime_ts); /* change time */
4346 SIVAL(pdata, 0x20, mode);
4347 SIVAL(pdata, 0x24, 0); /* padding. */
4348 SBVAL(pdata, 0x28, allocation_size);
4349 SBVAL(pdata, 0x30, file_size);
4350 SIVAL(pdata, 0x38, nlink);
4351 SCVAL(pdata, 0x3C, delete_pending);
4352 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4353 SSVAL(pdata, 0x3E, 0); /* padding */
4354 SBVAL(pdata, 0x40, file_index);
4355 SIVAL(pdata, 0x48, ea_size);
4356 SIVAL(pdata, 0x4C, access_mask);
4357 SBVAL(pdata, 0x50, pos);
4358 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4359 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4363 len = srvstr_push(dstart, flags2,
4365 PTR_DIFF(dend, pdata+4),
4369 data_size = PTR_DIFF(pdata,(*ppdata));
4372 case SMB_FILE_INTERNAL_INFORMATION:
4374 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4375 SBVAL(pdata, 0, file_index);
4379 case SMB_FILE_ACCESS_INFORMATION:
4380 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4381 SIVAL(pdata, 0, access_mask);
4385 case SMB_FILE_NAME_INFORMATION:
4386 /* Pathname with leading '\'. */
4389 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4390 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4391 SIVAL(pdata,0,byte_len);
4392 data_size = 4 + byte_len;
4396 case SMB_FILE_DISPOSITION_INFORMATION:
4397 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4399 SCVAL(pdata,0,delete_pending);
4402 case SMB_FILE_POSITION_INFORMATION:
4403 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4405 SOFF_T(pdata,0,pos);
4408 case SMB_FILE_MODE_INFORMATION:
4409 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4410 SIVAL(pdata,0,mode);
4414 case SMB_FILE_ALIGNMENT_INFORMATION:
4415 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4416 SIVAL(pdata,0,0); /* No alignment needed. */
4421 * NT4 server just returns "invalid query" to this - if we try
4422 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4425 /* The first statement above is false - verified using Thursby
4426 * client against NT4 -- gcolley.
4428 case SMB_QUERY_FILE_STREAM_INFO:
4429 case SMB_FILE_STREAM_INFORMATION: {
4430 unsigned int num_streams;
4431 struct stream_struct *streams;
4433 DEBUG(10,("smbd_do_qfilepathinfo: "
4434 "SMB_FILE_STREAM_INFORMATION\n"));
4436 status = SMB_VFS_STREAMINFO(
4437 conn, fsp, fname, talloc_tos(),
4438 &num_streams, &streams);
4440 if (!NT_STATUS_IS_OK(status)) {
4441 DEBUG(10, ("could not get stream info: %s\n",
4442 nt_errstr(status)));
4446 status = marshall_stream_info(num_streams, streams,
4447 pdata, max_data_bytes,
4450 if (!NT_STATUS_IS_OK(status)) {
4451 DEBUG(10, ("marshall_stream_info failed: %s\n",
4452 nt_errstr(status)));
4456 TALLOC_FREE(streams);
4460 case SMB_QUERY_COMPRESSION_INFO:
4461 case SMB_FILE_COMPRESSION_INFORMATION:
4462 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4463 SOFF_T(pdata,0,file_size);
4464 SIVAL(pdata,8,0); /* ??? */
4465 SIVAL(pdata,12,0); /* ??? */
4469 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4470 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4471 put_long_date_timespec(pdata,create_time_ts);
4472 put_long_date_timespec(pdata+8,atime_ts);
4473 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4474 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4475 SOFF_T(pdata,32,allocation_size);
4476 SOFF_T(pdata,40,file_size);
4477 SIVAL(pdata,48,mode);
4478 SIVAL(pdata,52,0); /* ??? */
4482 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4483 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4484 SIVAL(pdata,0,mode);
4490 * CIFS UNIX Extensions.
4493 case SMB_QUERY_FILE_UNIX_BASIC:
4495 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4496 data_size = PTR_DIFF(pdata,(*ppdata));
4500 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4502 for (i=0; i<100; i++)
4503 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4509 case SMB_QUERY_FILE_UNIX_INFO2:
4511 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4512 data_size = PTR_DIFF(pdata,(*ppdata));
4516 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4518 for (i=0; i<100; i++)
4519 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4525 case SMB_QUERY_FILE_UNIX_LINK:
4528 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4531 return NT_STATUS_NO_MEMORY;
4534 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4536 if(!S_ISLNK(sbuf.st_ex_mode)) {
4537 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4540 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4542 len = SMB_VFS_READLINK(conn,fname,
4545 return map_nt_error_from_unix(errno);
4548 len = srvstr_push(dstart, flags2,
4550 PTR_DIFF(dend, pdata),
4553 data_size = PTR_DIFF(pdata,(*ppdata));
4558 #if defined(HAVE_POSIX_ACLS)
4559 case SMB_QUERY_POSIX_ACL:
4561 SMB_ACL_T file_acl = NULL;
4562 SMB_ACL_T def_acl = NULL;
4563 uint16 num_file_acls = 0;
4564 uint16 num_def_acls = 0;
4566 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4567 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4569 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4572 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4573 DEBUG(5,("smbd_do_qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4575 return NT_STATUS_NOT_IMPLEMENTED;
4578 if (S_ISDIR(sbuf.st_ex_mode)) {
4579 if (fsp && fsp->is_directory) {
4581 SMB_VFS_SYS_ACL_GET_FILE(
4583 fsp->fsp_name->base_name,
4584 SMB_ACL_TYPE_DEFAULT);
4586 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4588 def_acl = free_empty_sys_acl(conn, def_acl);
4591 num_file_acls = count_acl_entries(conn, file_acl);
4592 num_def_acls = count_acl_entries(conn, def_acl);
4594 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4595 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4597 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4598 SMB_POSIX_ACL_HEADER_SIZE) ));
4600 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4603 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4605 return NT_STATUS_BUFFER_TOO_SMALL;
4608 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4609 SSVAL(pdata,2,num_file_acls);
4610 SSVAL(pdata,4,num_def_acls);
4611 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4613 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4616 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4618 return NT_STATUS_INTERNAL_ERROR;
4620 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4622 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4625 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4627 return NT_STATUS_INTERNAL_ERROR;
4631 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4634 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4636 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4642 case SMB_QUERY_POSIX_LOCK:
4647 enum brl_type lock_type;
4649 /* We need an open file with a real fd for this. */
4650 if (!fsp || fsp->is_directory || fsp->fh->fd == -1) {
4651 return NT_STATUS_INVALID_LEVEL;
4654 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4655 return NT_STATUS_INVALID_PARAMETER;
4658 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4659 case POSIX_LOCK_TYPE_READ:
4660 lock_type = READ_LOCK;
4662 case POSIX_LOCK_TYPE_WRITE:
4663 lock_type = WRITE_LOCK;
4665 case POSIX_LOCK_TYPE_UNLOCK:
4667 /* There's no point in asking for an unlock... */
4668 return NT_STATUS_INVALID_PARAMETER;
4671 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4672 #if defined(HAVE_LONGLONG)
4673 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4674 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4675 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4676 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4677 #else /* HAVE_LONGLONG */
4678 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4679 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4680 #endif /* HAVE_LONGLONG */
4682 status = query_lock(fsp,
4689 if (ERROR_WAS_LOCK_DENIED(status)) {
4690 /* Here we need to report who has it locked... */
4691 data_size = POSIX_LOCK_DATA_SIZE;
4693 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4694 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4695 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4696 #if defined(HAVE_LONGLONG)
4697 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4698 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4699 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4700 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4701 #else /* HAVE_LONGLONG */
4702 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4703 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4704 #endif /* HAVE_LONGLONG */
4706 } else if (NT_STATUS_IS_OK(status)) {
4707 /* For success we just return a copy of what we sent
4708 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4709 data_size = POSIX_LOCK_DATA_SIZE;
4710 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4711 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4719 return NT_STATUS_INVALID_LEVEL;
4722 *pdata_size = data_size;
4723 return NT_STATUS_OK;
4726 /****************************************************************************
4727 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4728 file name or file id).
4729 ****************************************************************************/
4731 static void call_trans2qfilepathinfo(connection_struct *conn,
4732 struct smb_request *req,
4733 unsigned int tran_call,
4734 char **pparams, int total_params,
4735 char **ppdata, int total_data,
4736 unsigned int max_data_bytes)
4738 char *params = *pparams;
4739 char *pdata = *ppdata;
4741 unsigned int data_size = 0;
4742 unsigned int param_size = 2;
4743 struct smb_filename *smb_fname = NULL;
4744 bool delete_pending = False;
4745 struct timespec write_time_ts;
4746 files_struct *fsp = NULL;
4747 struct file_id fileid;
4748 struct ea_list *ea_list = NULL;
4749 int lock_data_count = 0;
4750 char *lock_data = NULL;
4751 bool ms_dfs_link = false;
4752 NTSTATUS status = NT_STATUS_OK;
4755 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4759 ZERO_STRUCT(write_time_ts);
4761 if (tran_call == TRANSACT2_QFILEINFO) {
4762 if (total_params < 4) {
4763 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4768 call_trans2qpipeinfo(conn, req, tran_call,
4769 pparams, total_params,
4775 fsp = file_fsp(req, SVAL(params,0));
4776 info_level = SVAL(params,2);
4778 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
4780 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4781 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4785 /* Initial check for valid fsp ptr. */
4786 if (!check_fsp_open(conn, req, fsp)) {
4790 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
4792 if (!NT_STATUS_IS_OK(status)) {
4793 reply_nterror(req, status);
4797 if(fsp->fake_file_handle) {
4799 * This is actually for the QUOTA_FAKE_FILE --metze
4802 /* We know this name is ok, it's already passed the checks. */
4804 } else if(fsp->is_directory || fsp->fh->fd == -1) {
4806 * This is actually a QFILEINFO on a directory
4807 * handle (returned from an NT SMB). NT5.0 seems
4808 * to do this call. JRA.
4811 if (INFO_LEVEL_IS_UNIX(info_level)) {
4812 /* Always do lstat for UNIX calls. */
4813 if (SMB_VFS_LSTAT(conn, smb_fname)) {
4814 DEBUG(3,("call_trans2qfilepathinfo: "
4815 "SMB_VFS_LSTAT of %s failed "
4817 smb_fname_str_dbg(smb_fname),
4820 map_nt_error_from_unix(errno));
4823 } else if (SMB_VFS_STAT(conn, smb_fname)) {
4824 DEBUG(3,("call_trans2qfilepathinfo: "
4825 "SMB_VFS_STAT of %s failed (%s)\n",
4826 smb_fname_str_dbg(smb_fname),
4829 map_nt_error_from_unix(errno));
4833 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4834 get_file_infos(fileid, &delete_pending, &write_time_ts);
4837 * Original code - this is an open file.
4839 if (!check_fsp(conn, req, fsp)) {
4843 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
4844 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
4845 fsp->fnum, strerror(errno)));
4847 map_nt_error_from_unix(errno));
4850 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4851 get_file_infos(fileid, &delete_pending, &write_time_ts);
4858 if (total_params < 7) {
4859 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4863 info_level = SVAL(params,0);
4865 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
4867 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4868 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4872 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
4874 STR_TERMINATE, &status);
4875 if (!NT_STATUS_IS_OK(status)) {
4876 reply_nterror(req, status);
4880 status = filename_convert(req,
4882 req->flags2 & FLAGS2_DFS_PATHNAMES,
4885 if (!NT_STATUS_IS_OK(status)) {
4886 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4887 reply_botherror(req,
4888 NT_STATUS_PATH_NOT_COVERED,
4889 ERRSRV, ERRbadpath);
4892 reply_nterror(req, status);
4896 /* If this is a stream, check if there is a delete_pending. */
4897 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
4898 && is_ntfs_stream_smb_fname(smb_fname)) {
4899 struct smb_filename *smb_fname_base = NULL;
4901 /* Create an smb_filename with stream_name == NULL. */
4903 create_synthetic_smb_fname(talloc_tos(),
4904 smb_fname->base_name,
4907 if (!NT_STATUS_IS_OK(status)) {
4908 reply_nterror(req, status);
4912 if (INFO_LEVEL_IS_UNIX(info_level)) {
4913 /* Always do lstat for UNIX calls. */
4914 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
4915 DEBUG(3,("call_trans2qfilepathinfo: "
4916 "SMB_VFS_LSTAT of %s failed "
4918 smb_fname_str_dbg(smb_fname_base),
4920 TALLOC_FREE(smb_fname_base);
4922 map_nt_error_from_unix(errno));
4926 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
4927 DEBUG(3,("call_trans2qfilepathinfo: "
4928 "fileinfo of %s failed "
4930 smb_fname_str_dbg(smb_fname_base),
4932 TALLOC_FREE(smb_fname_base);
4934 map_nt_error_from_unix(errno));
4939 fileid = vfs_file_id_from_sbuf(conn,
4940 &smb_fname_base->st);
4941 TALLOC_FREE(smb_fname_base);
4942 get_file_infos(fileid, &delete_pending, NULL);
4943 if (delete_pending) {
4944 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4949 if (INFO_LEVEL_IS_UNIX(info_level)) {
4950 /* Always do lstat for UNIX calls. */
4951 if (SMB_VFS_LSTAT(conn, smb_fname)) {
4952 DEBUG(3,("call_trans2qfilepathinfo: "
4953 "SMB_VFS_LSTAT of %s failed (%s)\n",
4954 smb_fname_str_dbg(smb_fname),
4957 map_nt_error_from_unix(errno));
4961 } else if (!VALID_STAT(smb_fname->st) &&
4962 SMB_VFS_STAT(conn, smb_fname) &&
4963 (info_level != SMB_INFO_IS_NAME_VALID)) {
4964 ms_dfs_link = check_msdfs_link(conn,
4965 smb_fname->base_name,
4969 DEBUG(3,("call_trans2qfilepathinfo: "
4970 "SMB_VFS_STAT of %s failed (%s)\n",
4971 smb_fname_str_dbg(smb_fname),
4974 map_nt_error_from_unix(errno));
4979 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4980 get_file_infos(fileid, &delete_pending, &write_time_ts);
4981 if (delete_pending) {
4982 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4987 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
4988 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
4989 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4991 /* Pull out any data sent here before we realloc. */
4992 switch (info_level) {
4993 case SMB_INFO_QUERY_EAS_FROM_LIST:
4995 /* Pull any EA list from the data portion. */
4998 if (total_data < 4) {
5000 req, NT_STATUS_INVALID_PARAMETER);
5003 ea_size = IVAL(pdata,0);
5005 if (total_data > 0 && ea_size != total_data) {
5006 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5007 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5009 req, NT_STATUS_INVALID_PARAMETER);
5013 if (!lp_ea_support(SNUM(conn))) {
5014 reply_doserror(req, ERRDOS,
5015 ERReasnotsupported);
5019 /* Pull out the list of names. */
5020 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5023 req, NT_STATUS_INVALID_PARAMETER);
5029 case SMB_QUERY_POSIX_LOCK:
5031 if (fsp == NULL || fsp->fh->fd == -1) {
5032 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5036 if (total_data != POSIX_LOCK_DATA_SIZE) {
5038 req, NT_STATUS_INVALID_PARAMETER);
5042 /* Copy the lock range data. */
5043 lock_data = (char *)TALLOC_MEMDUP(
5044 req, pdata, total_data);
5046 reply_nterror(req, NT_STATUS_NO_MEMORY);
5049 lock_data_count = total_data;
5055 *pparams = (char *)SMB_REALLOC(*pparams,2);
5056 if (*pparams == NULL) {
5057 reply_nterror(req, NT_STATUS_NO_MEMORY);
5064 * draft-leach-cifs-v1-spec-02.txt
5065 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5068 * The requested information is placed in the Data portion of the
5069 * transaction response. For the information levels greater than 0x100,
5070 * the transaction response has 1 parameter word which should be
5071 * ignored by the client.
5073 * However Windows only follows this rule for the IS_NAME_VALID call.
5075 switch (info_level) {
5076 case SMB_INFO_IS_NAME_VALID:
5081 if ((info_level & 0xFF00) == 0xFF00) {
5083 * We use levels that start with 0xFF00
5084 * internally to represent SMB2 specific levels
5086 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5090 status = smbd_do_qfilepathinfo(conn, req, info_level,
5092 delete_pending, write_time_ts,
5093 ms_dfs_link, ea_list,
5094 lock_data_count, lock_data,
5095 req->flags2, max_data_bytes,
5096 ppdata, &data_size);
5097 if (!NT_STATUS_IS_OK(status)) {
5098 reply_nterror(req, status);
5102 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5108 /****************************************************************************
5109 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5111 ****************************************************************************/
5113 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5114 connection_struct *conn,
5115 const struct smb_filename *smb_fname_old,
5116 const struct smb_filename *smb_fname_new)
5118 NTSTATUS status = NT_STATUS_OK;
5120 /* source must already exist. */
5121 if (!VALID_STAT(smb_fname_old->st)) {
5122 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5125 /* Disallow if newname already exists. */
5126 if (VALID_STAT(smb_fname_new->st)) {
5127 return NT_STATUS_OBJECT_NAME_COLLISION;
5130 /* No links from a directory. */
5131 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5132 return NT_STATUS_FILE_IS_A_DIRECTORY;
5135 /* Setting a hardlink to/from a stream isn't currently supported. */
5136 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5137 is_ntfs_stream_smb_fname(smb_fname_new)) {
5138 return NT_STATUS_INVALID_PARAMETER;
5141 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5142 smb_fname_old->base_name, smb_fname_new->base_name));
5144 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5145 smb_fname_new->base_name) != 0) {
5146 status = map_nt_error_from_unix(errno);
5147 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5148 nt_errstr(status), smb_fname_old->base_name,
5149 smb_fname_new->base_name));
5154 /****************************************************************************
5155 Deal with setting the time from any of the setfilepathinfo functions.
5156 ****************************************************************************/
5158 NTSTATUS smb_set_file_time(connection_struct *conn,
5160 const struct smb_filename *smb_fname,
5161 struct smb_file_time *ft,
5162 bool setting_write_time)
5164 struct smb_filename *smb_fname_base = NULL;
5166 FILE_NOTIFY_CHANGE_LAST_ACCESS
5167 |FILE_NOTIFY_CHANGE_LAST_WRITE;
5170 if (!VALID_STAT(smb_fname->st)) {
5171 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5174 /* get some defaults (no modifications) if any info is zero or -1. */
5175 if (null_timespec(ft->atime)) {
5176 ft->atime= smb_fname->st.st_ex_atime;
5177 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5180 if (null_timespec(ft->mtime)) {
5181 ft->mtime = smb_fname->st.st_ex_mtime;
5182 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5185 if (!setting_write_time) {
5186 /* ft->mtime comes from change time, not write time. */
5187 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5190 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5191 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5192 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5193 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5194 if (!null_timespec(ft->create_time)) {
5195 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5196 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5200 * Try and set the times of this file if
5201 * they are different from the current values.
5205 struct timespec mts = smb_fname->st.st_ex_mtime;
5206 struct timespec ats = smb_fname->st.st_ex_atime;
5207 if ((timespec_compare(&ft->atime, &ats) == 0) &&
5208 (timespec_compare(&ft->mtime, &mts) == 0)) {
5209 return NT_STATUS_OK;
5213 if (setting_write_time) {
5215 * This was a Windows setfileinfo on an open file.
5216 * NT does this a lot. We also need to
5217 * set the time here, as it can be read by
5218 * FindFirst/FindNext and with the patch for bug #2045
5219 * in smbd/fileio.c it ensures that this timestamp is
5220 * kept sticky even after a write. We save the request
5221 * away and will set it on file close and after a write. JRA.
5224 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5225 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5228 if (fsp->base_fsp) {
5229 set_sticky_write_time_fsp(fsp->base_fsp,
5232 set_sticky_write_time_fsp(fsp, ft->mtime);
5235 set_sticky_write_time_path(
5236 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5241 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5243 /* Always call ntimes on the base, even if a stream was passed in. */
5244 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5245 NULL, &smb_fname->st,
5247 if (!NT_STATUS_IS_OK(status)) {
5251 if(file_ntimes(conn, smb_fname_base, ft)!=0) {
5252 TALLOC_FREE(smb_fname_base);
5253 return map_nt_error_from_unix(errno);
5255 TALLOC_FREE(smb_fname_base);
5257 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5258 smb_fname->base_name);
5259 return NT_STATUS_OK;
5262 /****************************************************************************
5263 Deal with setting the dosmode from any of the setfilepathinfo functions.
5264 ****************************************************************************/
5266 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5267 const struct smb_filename *smb_fname,
5270 struct smb_filename *smb_fname_base = NULL;
5273 if (!VALID_STAT(smb_fname->st)) {
5274 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5277 /* Always operate on the base_name, even if a stream was passed in. */
5278 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5279 NULL, &smb_fname->st,
5281 if (!NT_STATUS_IS_OK(status)) {
5286 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5293 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5295 /* check the mode isn't different, before changing it */
5296 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5297 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5298 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5299 (unsigned int)dosmode));
5301 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5303 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5305 smb_fname_str_dbg(smb_fname_base),
5307 status = map_nt_error_from_unix(errno);
5311 status = NT_STATUS_OK;
5313 TALLOC_FREE(smb_fname_base);
5317 /****************************************************************************
5318 Deal with setting the size from any of the setfilepathinfo functions.
5319 ****************************************************************************/
5321 static NTSTATUS smb_set_file_size(connection_struct *conn,
5322 struct smb_request *req,
5324 const struct smb_filename *smb_fname,
5325 const SMB_STRUCT_STAT *psbuf,
5328 NTSTATUS status = NT_STATUS_OK;
5329 struct smb_filename *smb_fname_tmp = NULL;
5330 files_struct *new_fsp = NULL;
5332 if (!VALID_STAT(*psbuf)) {
5333 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5336 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5338 if (size == get_file_size_stat(psbuf)) {
5339 return NT_STATUS_OK;
5342 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5343 smb_fname_str_dbg(smb_fname), (double)size));
5345 if (fsp && fsp->fh->fd != -1) {
5346 /* Handle based call. */
5347 if (vfs_set_filelen(fsp, size) == -1) {
5348 return map_nt_error_from_unix(errno);
5350 trigger_write_time_update_immediate(fsp);
5351 return NT_STATUS_OK;
5354 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5355 if (!NT_STATUS_IS_OK(status)) {
5359 smb_fname_tmp->st = *psbuf;
5361 status = SMB_VFS_CREATE_FILE(
5364 0, /* root_dir_fid */
5365 smb_fname_tmp, /* fname */
5366 FILE_WRITE_ATTRIBUTES, /* access_mask */
5367 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5369 FILE_OPEN, /* create_disposition*/
5370 0, /* create_options */
5371 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5372 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5373 0, /* allocation_size */
5376 &new_fsp, /* result */
5379 TALLOC_FREE(smb_fname_tmp);
5381 if (!NT_STATUS_IS_OK(status)) {
5382 /* NB. We check for open_was_deferred in the caller. */
5386 if (vfs_set_filelen(new_fsp, size) == -1) {
5387 status = map_nt_error_from_unix(errno);
5388 close_file(req, new_fsp,NORMAL_CLOSE);
5392 trigger_write_time_update_immediate(new_fsp);
5393 close_file(req, new_fsp,NORMAL_CLOSE);
5394 return NT_STATUS_OK;
5397 /****************************************************************************
5398 Deal with SMB_INFO_SET_EA.
5399 ****************************************************************************/
5401 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5405 const struct smb_filename *smb_fname)
5407 struct ea_list *ea_list = NULL;
5408 TALLOC_CTX *ctx = NULL;
5409 NTSTATUS status = NT_STATUS_OK;
5411 if (total_data < 10) {
5413 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5414 length. They seem to have no effect. Bug #3212. JRA */
5416 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5417 /* We're done. We only get EA info in this call. */
5418 return NT_STATUS_OK;
5421 return NT_STATUS_INVALID_PARAMETER;
5424 if (IVAL(pdata,0) > total_data) {
5425 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5426 IVAL(pdata,0), (unsigned int)total_data));
5427 return NT_STATUS_INVALID_PARAMETER;
5431 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5433 return NT_STATUS_INVALID_PARAMETER;
5435 status = set_ea(conn, fsp, smb_fname, ea_list);
5440 /****************************************************************************
5441 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5442 ****************************************************************************/
5444 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5448 const struct smb_filename *smb_fname)
5450 NTSTATUS status = NT_STATUS_OK;
5451 bool delete_on_close;
5454 if (total_data < 1) {
5455 return NT_STATUS_INVALID_PARAMETER;
5459 return NT_STATUS_INVALID_HANDLE;
5462 delete_on_close = (CVAL(pdata,0) ? True : False);
5463 dosmode = dos_mode(conn, smb_fname);
5465 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5466 "delete_on_close = %u\n",
5467 smb_fname_str_dbg(smb_fname),
5468 (unsigned int)dosmode,
5469 (unsigned int)delete_on_close ));
5471 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5473 if (!NT_STATUS_IS_OK(status)) {
5477 /* The set is across all open files on this dev/inode pair. */
5478 if (!set_delete_on_close(fsp, delete_on_close,
5479 &conn->server_info->utok)) {
5480 return NT_STATUS_ACCESS_DENIED;
5482 return NT_STATUS_OK;
5485 /****************************************************************************
5486 Deal with SMB_FILE_POSITION_INFORMATION.
5487 ****************************************************************************/
5489 static NTSTATUS smb_file_position_information(connection_struct *conn,
5494 uint64_t position_information;
5496 if (total_data < 8) {
5497 return NT_STATUS_INVALID_PARAMETER;
5501 /* Ignore on pathname based set. */
5502 return NT_STATUS_OK;
5505 position_information = (uint64_t)IVAL(pdata,0);
5506 #ifdef LARGE_SMB_OFF_T
5507 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5508 #else /* LARGE_SMB_OFF_T */
5509 if (IVAL(pdata,4) != 0) {
5510 /* more than 32 bits? */
5511 return NT_STATUS_INVALID_PARAMETER;
5513 #endif /* LARGE_SMB_OFF_T */
5515 DEBUG(10,("smb_file_position_information: Set file position "
5516 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5517 (double)position_information));
5518 fsp->fh->position_information = position_information;
5519 return NT_STATUS_OK;
5522 /****************************************************************************
5523 Deal with SMB_FILE_MODE_INFORMATION.
5524 ****************************************************************************/
5526 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5532 if (total_data < 4) {
5533 return NT_STATUS_INVALID_PARAMETER;
5535 mode = IVAL(pdata,0);
5536 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5537 return NT_STATUS_INVALID_PARAMETER;
5539 return NT_STATUS_OK;
5542 /****************************************************************************
5543 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5544 ****************************************************************************/
5546 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5547 struct smb_request *req,
5550 const struct smb_filename *smb_fname)
5552 char *link_target = NULL;
5553 const char *newname = smb_fname->base_name;
5554 NTSTATUS status = NT_STATUS_OK;
5555 TALLOC_CTX *ctx = talloc_tos();
5557 /* Set a symbolic link. */
5558 /* Don't allow this if follow links is false. */
5560 if (total_data == 0) {
5561 return NT_STATUS_INVALID_PARAMETER;
5564 if (!lp_symlinks(SNUM(conn))) {
5565 return NT_STATUS_ACCESS_DENIED;
5568 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5569 total_data, STR_TERMINATE);
5572 return NT_STATUS_INVALID_PARAMETER;
5575 /* !widelinks forces the target path to be within the share. */
5576 /* This means we can interpret the target as a pathname. */
5577 if (!lp_widelinks(SNUM(conn))) {
5578 char *rel_name = NULL;
5579 char *last_dirp = NULL;
5581 if (*link_target == '/') {
5582 /* No absolute paths allowed. */
5583 return NT_STATUS_ACCESS_DENIED;
5585 rel_name = talloc_strdup(ctx,newname);
5587 return NT_STATUS_NO_MEMORY;
5589 last_dirp = strrchr_m(rel_name, '/');
5591 last_dirp[1] = '\0';
5593 rel_name = talloc_strdup(ctx,"./");
5595 return NT_STATUS_NO_MEMORY;
5598 rel_name = talloc_asprintf_append(rel_name,
5602 return NT_STATUS_NO_MEMORY;
5605 status = check_name(conn, rel_name);
5606 if (!NT_STATUS_IS_OK(status)) {
5611 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5612 newname, link_target ));
5614 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5615 return map_nt_error_from_unix(errno);
5618 return NT_STATUS_OK;
5621 /****************************************************************************
5622 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5623 ****************************************************************************/
5625 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5626 struct smb_request *req,
5627 const char *pdata, int total_data,
5628 const struct smb_filename *smb_fname_new)
5630 char *oldname = NULL;
5631 struct smb_filename *smb_fname_old = NULL;
5632 TALLOC_CTX *ctx = talloc_tos();
5633 NTSTATUS status = NT_STATUS_OK;
5635 /* Set a hard link. */
5636 if (total_data == 0) {
5637 return NT_STATUS_INVALID_PARAMETER;
5640 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5641 total_data, STR_TERMINATE, &status);
5642 if (!NT_STATUS_IS_OK(status)) {
5646 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5647 smb_fname_str_dbg(smb_fname_new), oldname));
5649 status = filename_convert(ctx,
5651 req->flags2 & FLAGS2_DFS_PATHNAMES,
5654 if (!NT_STATUS_IS_OK(status)) {
5658 return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
5661 /****************************************************************************
5662 Deal with SMB_FILE_RENAME_INFORMATION.
5663 ****************************************************************************/
5665 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5666 struct smb_request *req,
5675 char *newname = NULL;
5676 char *base_name = NULL;
5677 struct smb_filename *smb_fname = NULL;
5678 bool dest_has_wcard = False;
5679 NTSTATUS status = NT_STATUS_OK;
5681 TALLOC_CTX *ctx = talloc_tos();
5683 if (total_data < 13) {
5684 return NT_STATUS_INVALID_PARAMETER;
5687 overwrite = (CVAL(pdata,0) ? True : False);
5688 root_fid = IVAL(pdata,4);
5689 len = IVAL(pdata,8);
5691 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5692 return NT_STATUS_INVALID_PARAMETER;
5695 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5698 if (!NT_STATUS_IS_OK(status)) {
5702 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5705 status = resolve_dfspath_wcard(ctx, conn,
5706 req->flags2 & FLAGS2_DFS_PATHNAMES,
5710 if (!NT_STATUS_IS_OK(status)) {
5714 /* Check the new name has no '/' characters. */
5715 if (strchr_m(newname, '/')) {
5716 return NT_STATUS_NOT_SUPPORTED;
5719 if (fsp && fsp->base_fsp) {
5720 /* newname must be a stream name. */
5721 if (newname[0] != ':') {
5722 return NT_STATUS_NOT_SUPPORTED;
5725 /* Create an smb_fname to call rename_internals_fsp() with. */
5726 status = create_synthetic_smb_fname(talloc_tos(),
5727 fsp->base_fsp->fsp_name->base_name, newname, NULL,
5729 if (!NT_STATUS_IS_OK(status)) {
5734 * Set the original last component, since
5735 * rename_internals_fsp() requires it.
5737 smb_fname->original_lcomp = talloc_strdup(smb_fname, newname);
5738 if (smb_fname->original_lcomp == NULL) {
5739 status = NT_STATUS_NO_MEMORY;
5743 /* Create a char * to call rename_internals() with. */
5744 base_name = talloc_asprintf(ctx, "%s%s",
5745 fsp->base_fsp->fsp_name->base_name,
5748 status = NT_STATUS_NO_MEMORY;
5752 /* newname must *not* be a stream name. */
5753 if (newname[0] == ':') {
5754 return NT_STATUS_NOT_SUPPORTED;
5757 /* Create the base directory. */
5758 base_name = talloc_strdup(ctx, fname);
5760 return NT_STATUS_NO_MEMORY;
5762 p = strrchr_m(base_name, '/');
5766 base_name = talloc_strdup(ctx, "./");
5768 return NT_STATUS_NO_MEMORY;
5771 /* Append the new name. */
5772 base_name = talloc_asprintf_append(base_name,
5776 return NT_STATUS_NO_MEMORY;
5779 status = unix_convert(ctx, conn, base_name, &smb_fname,
5782 /* If an error we expect this to be
5783 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5785 if (!NT_STATUS_IS_OK(status)) {
5786 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5790 /* Create an smb_fname to call rename_internals_fsp() */
5791 status = create_synthetic_smb_fname(talloc_tos(),
5794 if (!NT_STATUS_IS_OK(status)) {
5802 DEBUG(10,("smb_file_rename_information: "
5803 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5804 fsp->fnum, fsp_str_dbg(fsp), base_name));
5805 status = rename_internals_fsp(conn, fsp, smb_fname, 0,
5808 DEBUG(10,("smb_file_rename_information: "
5809 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5811 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5812 overwrite, False, dest_has_wcard,
5813 FILE_WRITE_ATTRIBUTES);
5816 TALLOC_FREE(smb_fname);
5820 /****************************************************************************
5821 Deal with SMB_SET_POSIX_ACL.
5822 ****************************************************************************/
5824 #if defined(HAVE_POSIX_ACLS)
5825 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5829 const struct smb_filename *smb_fname)
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 smb_fname ? smb_fname_str_dbg(smb_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,
5869 smb_fname->base_name, num_file_acls,
5870 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5871 return map_nt_error_from_unix(errno);
5874 if (valid_def_acls && !set_unix_posix_default_acl(conn,
5875 smb_fname->base_name, &smb_fname->st, num_def_acls,
5876 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5877 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5878 return map_nt_error_from_unix(errno);
5880 return NT_STATUS_OK;
5884 /****************************************************************************
5885 Deal with SMB_SET_POSIX_LOCK.
5886 ****************************************************************************/
5888 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5889 struct smb_request *req,
5897 bool blocking_lock = False;
5898 enum brl_type lock_type;
5900 NTSTATUS status = NT_STATUS_OK;
5902 if (fsp == NULL || fsp->fh->fd == -1) {
5903 return NT_STATUS_INVALID_HANDLE;
5906 if (total_data != POSIX_LOCK_DATA_SIZE) {
5907 return NT_STATUS_INVALID_PARAMETER;
5910 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5911 case POSIX_LOCK_TYPE_READ:
5912 lock_type = READ_LOCK;
5914 case POSIX_LOCK_TYPE_WRITE:
5915 /* Return the right POSIX-mappable error code for files opened read-only. */
5916 if (!fsp->can_write) {
5917 return NT_STATUS_INVALID_HANDLE;
5919 lock_type = WRITE_LOCK;
5921 case POSIX_LOCK_TYPE_UNLOCK:
5922 lock_type = UNLOCK_LOCK;
5925 return NT_STATUS_INVALID_PARAMETER;
5928 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5929 blocking_lock = False;
5930 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5931 blocking_lock = True;
5933 return NT_STATUS_INVALID_PARAMETER;
5936 if (!lp_blocking_locks(SNUM(conn))) {
5937 blocking_lock = False;
5940 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5941 #if defined(HAVE_LONGLONG)
5942 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5943 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5944 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5945 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5946 #else /* HAVE_LONGLONG */
5947 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5948 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5949 #endif /* HAVE_LONGLONG */
5951 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5952 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5954 (unsigned int)lock_type,
5955 (unsigned int)lock_pid,
5959 if (lock_type == UNLOCK_LOCK) {
5960 status = do_unlock(smbd_messaging_context(),
5967 uint32 block_smbpid;
5969 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5981 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5983 * A blocking lock was requested. Package up
5984 * this smb into a queued request and push it
5985 * onto the blocking lock queue.
5987 if(push_blocking_lock_request(br_lck,
5990 -1, /* infinite timeout. */
5998 TALLOC_FREE(br_lck);
6002 TALLOC_FREE(br_lck);
6008 /****************************************************************************
6009 Deal with SMB_INFO_STANDARD.
6010 ****************************************************************************/
6012 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6016 const struct smb_filename *smb_fname)
6018 struct smb_file_time ft;
6021 if (total_data < 12) {
6022 return NT_STATUS_INVALID_PARAMETER;
6026 ft.create_time = interpret_long_date(pdata);
6029 ft.atime = interpret_long_date(pdata + 8);
6032 ft.mtime = interpret_long_date(pdata + 16);
6034 DEBUG(10,("smb_set_info_standard: file %s\n",
6035 smb_fname_str_dbg(smb_fname)));
6037 return smb_set_file_time(conn, fsp, smb_fname, &ft, true);
6040 /****************************************************************************
6041 Deal with SMB_SET_FILE_BASIC_INFO.
6042 ****************************************************************************/
6044 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6048 const struct smb_filename *smb_fname)
6050 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6051 struct timespec write_time;
6052 struct timespec changed_time;
6053 struct smb_file_time ft;
6055 NTSTATUS status = NT_STATUS_OK;
6056 bool setting_write_time = true;
6060 if (total_data < 36) {
6061 return NT_STATUS_INVALID_PARAMETER;
6064 /* Set the attributes */
6065 dosmode = IVAL(pdata,32);
6066 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6067 if (!NT_STATUS_IS_OK(status)) {
6072 ft.atime = interpret_long_date(pdata+8);
6074 write_time = interpret_long_date(pdata+16);
6075 changed_time = interpret_long_date(pdata+24);
6078 ft.mtime = timespec_min(&write_time, &changed_time);
6081 ft.create_time = interpret_long_date(pdata);
6083 if ((timespec_compare(&write_time, &ft.mtime) == 1) &&
6084 !null_timespec(write_time)) {
6085 ft.mtime = write_time;
6088 /* Prefer a defined time to an undefined one. */
6089 if (null_timespec(ft.mtime)) {
6090 if (null_timespec(write_time)) {
6091 ft.mtime = changed_time;
6092 setting_write_time = false;
6094 ft.mtime = write_time;
6098 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6099 smb_fname_str_dbg(smb_fname)));
6101 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6102 setting_write_time);
6105 /****************************************************************************
6106 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6107 ****************************************************************************/
6109 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6110 struct smb_request *req,
6114 struct smb_filename *smb_fname)
6116 uint64_t allocation_size = 0;
6117 NTSTATUS status = NT_STATUS_OK;
6118 files_struct *new_fsp = NULL;
6120 if (!VALID_STAT(smb_fname->st)) {
6121 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6124 if (total_data < 8) {
6125 return NT_STATUS_INVALID_PARAMETER;
6128 allocation_size = (uint64_t)IVAL(pdata,0);
6129 #ifdef LARGE_SMB_OFF_T
6130 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6131 #else /* LARGE_SMB_OFF_T */
6132 if (IVAL(pdata,4) != 0) {
6133 /* more than 32 bits? */
6134 return NT_STATUS_INVALID_PARAMETER;
6136 #endif /* LARGE_SMB_OFF_T */
6138 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6139 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6140 (double)allocation_size));
6142 if (allocation_size) {
6143 allocation_size = smb_roundup(conn, allocation_size);
6146 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6147 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6148 (double)allocation_size));
6150 if (fsp && fsp->fh->fd != -1) {
6151 /* Open file handle. */
6152 /* Only change if needed. */
6153 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6154 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6155 return map_nt_error_from_unix(errno);
6158 /* But always update the time. */
6160 * This is equivalent to a write. Ensure it's seen immediately
6161 * if there are no pending writes.
6163 trigger_write_time_update_immediate(fsp);
6164 return NT_STATUS_OK;
6167 /* Pathname or stat or directory file. */
6168 status = SMB_VFS_CREATE_FILE(
6171 0, /* root_dir_fid */
6172 smb_fname, /* fname */
6173 FILE_WRITE_DATA, /* access_mask */
6174 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6176 FILE_OPEN, /* create_disposition*/
6177 0, /* create_options */
6178 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6179 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6180 0, /* allocation_size */
6183 &new_fsp, /* result */
6186 if (!NT_STATUS_IS_OK(status)) {
6187 /* NB. We check for open_was_deferred in the caller. */
6191 /* Only change if needed. */
6192 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6193 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6194 status = map_nt_error_from_unix(errno);
6195 close_file(req, new_fsp, NORMAL_CLOSE);
6200 /* Changing the allocation size should set the last mod time. */
6202 * This is equivalent to a write. Ensure it's seen immediately
6203 * if there are no pending writes.
6205 trigger_write_time_update_immediate(new_fsp);
6207 close_file(req, new_fsp, NORMAL_CLOSE);
6208 return NT_STATUS_OK;
6211 /****************************************************************************
6212 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6213 ****************************************************************************/
6215 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6216 struct smb_request *req,
6220 const struct smb_filename *smb_fname)
6224 if (total_data < 8) {
6225 return NT_STATUS_INVALID_PARAMETER;
6228 size = IVAL(pdata,0);
6229 #ifdef LARGE_SMB_OFF_T
6230 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6231 #else /* LARGE_SMB_OFF_T */
6232 if (IVAL(pdata,4) != 0) {
6233 /* more than 32 bits? */
6234 return NT_STATUS_INVALID_PARAMETER;
6236 #endif /* LARGE_SMB_OFF_T */
6237 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6238 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6241 return smb_set_file_size(conn, req,
6248 /****************************************************************************
6249 Allow a UNIX info mknod.
6250 ****************************************************************************/
6252 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6255 const struct smb_filename *smb_fname)
6257 uint32 file_type = IVAL(pdata,56);
6258 #if defined(HAVE_MAKEDEV)
6259 uint32 dev_major = IVAL(pdata,60);
6260 uint32 dev_minor = IVAL(pdata,68);
6262 SMB_DEV_T dev = (SMB_DEV_T)0;
6263 uint32 raw_unixmode = IVAL(pdata,84);
6267 if (total_data < 100) {
6268 return NT_STATUS_INVALID_PARAMETER;
6271 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6272 PERM_NEW_FILE, &unixmode);
6273 if (!NT_STATUS_IS_OK(status)) {
6277 #if defined(HAVE_MAKEDEV)
6278 dev = makedev(dev_major, dev_minor);
6281 switch (file_type) {
6282 #if defined(S_IFIFO)
6283 case UNIX_TYPE_FIFO:
6284 unixmode |= S_IFIFO;
6287 #if defined(S_IFSOCK)
6288 case UNIX_TYPE_SOCKET:
6289 unixmode |= S_IFSOCK;
6292 #if defined(S_IFCHR)
6293 case UNIX_TYPE_CHARDEV:
6294 unixmode |= S_IFCHR;
6297 #if defined(S_IFBLK)
6298 case UNIX_TYPE_BLKDEV:
6299 unixmode |= S_IFBLK;
6303 return NT_STATUS_INVALID_PARAMETER;
6306 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6307 "%.0f mode 0%o for file %s\n", (double)dev,
6308 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6310 /* Ok - do the mknod. */
6311 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6312 return map_nt_error_from_unix(errno);
6315 /* If any of the other "set" calls fail we
6316 * don't want to end up with a half-constructed mknod.
6319 if (lp_inherit_perms(SNUM(conn))) {
6321 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6323 return NT_STATUS_NO_MEMORY;
6325 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6327 TALLOC_FREE(parent);
6330 return NT_STATUS_OK;
6333 /****************************************************************************
6334 Deal with SMB_SET_FILE_UNIX_BASIC.
6335 ****************************************************************************/
6337 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6338 struct smb_request *req,
6342 const struct smb_filename *smb_fname)
6344 struct smb_file_time ft;
6345 uint32 raw_unixmode;
6348 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6349 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6350 NTSTATUS status = NT_STATUS_OK;
6351 bool delete_on_fail = False;
6352 enum perm_type ptype;
6353 files_struct *all_fsps = NULL;
6354 bool modify_mtime = true;
6356 SMB_STRUCT_STAT sbuf;
6360 if (total_data < 100) {
6361 return NT_STATUS_INVALID_PARAMETER;
6364 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6365 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6366 size=IVAL(pdata,0); /* first 8 Bytes are size */
6367 #ifdef LARGE_SMB_OFF_T
6368 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6369 #else /* LARGE_SMB_OFF_T */
6370 if (IVAL(pdata,4) != 0) {
6371 /* more than 32 bits? */
6372 return NT_STATUS_INVALID_PARAMETER;
6374 #endif /* LARGE_SMB_OFF_T */
6377 ft.atime = interpret_long_date(pdata+24); /* access_time */
6378 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6379 set_owner = (uid_t)IVAL(pdata,40);
6380 set_grp = (gid_t)IVAL(pdata,48);
6381 raw_unixmode = IVAL(pdata,84);
6383 if (VALID_STAT(smb_fname->st)) {
6384 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6385 ptype = PERM_EXISTING_DIR;
6387 ptype = PERM_EXISTING_FILE;
6390 ptype = PERM_NEW_FILE;
6393 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6395 if (!NT_STATUS_IS_OK(status)) {
6399 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6400 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6401 smb_fname_str_dbg(smb_fname), (double)size,
6402 (unsigned int)set_owner, (unsigned int)set_grp,
6403 (int)raw_unixmode));
6405 sbuf = smb_fname->st;
6407 if (!VALID_STAT(sbuf)) {
6408 struct smb_filename *smb_fname_tmp = NULL;
6410 * The only valid use of this is to create character and block
6411 * devices, and named pipes. This is deprecated (IMHO) and
6412 * a new info level should be used for mknod. JRA.
6415 status = smb_unix_mknod(conn,
6419 if (!NT_STATUS_IS_OK(status)) {
6423 status = copy_smb_filename(talloc_tos(), smb_fname,
6425 if (!NT_STATUS_IS_OK(status)) {
6429 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6430 status = map_nt_error_from_unix(errno);
6431 TALLOC_FREE(smb_fname_tmp);
6432 SMB_VFS_UNLINK(conn, smb_fname);
6436 sbuf = smb_fname_tmp->st;
6437 TALLOC_FREE(smb_fname_tmp);
6439 /* Ensure we don't try and change anything else. */
6440 raw_unixmode = SMB_MODE_NO_CHANGE;
6441 size = get_file_size_stat(&sbuf);
6442 ft.atime = sbuf.st_ex_atime;
6443 ft.mtime = sbuf.st_ex_mtime;
6445 * We continue here as we might want to change the
6448 delete_on_fail = True;
6452 /* Horrible backwards compatibility hack as an old server bug
6453 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6457 size = get_file_size_stat(&sbuf);
6462 * Deal with the UNIX specific mode set.
6465 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6466 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6467 "setting mode 0%o for file %s\n",
6468 (unsigned int)unixmode,
6469 smb_fname_str_dbg(smb_fname)));
6470 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6471 return map_nt_error_from_unix(errno);
6476 * Deal with the UNIX specific uid set.
6479 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6480 (sbuf.st_ex_uid != set_owner)) {
6483 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6484 "changing owner %u for path %s\n",
6485 (unsigned int)set_owner,
6486 smb_fname_str_dbg(smb_fname)));
6488 if (S_ISLNK(sbuf.st_ex_mode)) {
6489 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6490 set_owner, (gid_t)-1);
6492 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6493 set_owner, (gid_t)-1);
6497 status = map_nt_error_from_unix(errno);
6498 if (delete_on_fail) {
6499 SMB_VFS_UNLINK(conn, smb_fname);
6506 * Deal with the UNIX specific gid set.
6509 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6510 (sbuf.st_ex_gid != set_grp)) {
6511 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6512 "changing group %u for file %s\n",
6513 (unsigned int)set_owner,
6514 smb_fname_str_dbg(smb_fname)));
6515 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6517 status = map_nt_error_from_unix(errno);
6518 if (delete_on_fail) {
6519 SMB_VFS_UNLINK(conn, smb_fname);
6525 /* Deal with any size changes. */
6527 status = smb_set_file_size(conn, req,
6532 if (!NT_STATUS_IS_OK(status)) {
6536 /* Deal with any time changes. */
6537 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6538 /* No change, don't cancel anything. */
6542 id = vfs_file_id_from_sbuf(conn, &sbuf);
6543 for(all_fsps = file_find_di_first(id); all_fsps;
6544 all_fsps = file_find_di_next(all_fsps)) {
6546 * We're setting the time explicitly for UNIX.
6547 * Cancel any pending changes over all handles.
6549 all_fsps->update_write_time_on_close = false;
6550 TALLOC_FREE(all_fsps->update_write_time_event);
6554 * Override the "setting_write_time"
6555 * parameter here as it almost does what
6556 * we need. Just remember if we modified
6557 * mtime and send the notify ourselves.
6559 if (null_timespec(ft.mtime)) {
6560 modify_mtime = false;
6563 status = smb_set_file_time(conn,
6569 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6570 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6575 /****************************************************************************
6576 Deal with SMB_SET_FILE_UNIX_INFO2.
6577 ****************************************************************************/
6579 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6580 struct smb_request *req,
6584 const struct smb_filename *smb_fname)
6590 if (total_data < 116) {
6591 return NT_STATUS_INVALID_PARAMETER;
6594 /* Start by setting all the fields that are common between UNIX_BASIC
6597 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6599 if (!NT_STATUS_IS_OK(status)) {
6603 smb_fflags = IVAL(pdata, 108);
6604 smb_fmask = IVAL(pdata, 112);
6606 /* NB: We should only attempt to alter the file flags if the client
6607 * sends a non-zero mask.
6609 if (smb_fmask != 0) {
6610 int stat_fflags = 0;
6612 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6613 smb_fmask, &stat_fflags)) {
6614 /* Client asked to alter a flag we don't understand. */
6615 return NT_STATUS_INVALID_PARAMETER;
6618 if (fsp && fsp->fh->fd != -1) {
6619 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6620 return NT_STATUS_NOT_SUPPORTED;
6622 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
6623 stat_fflags) != 0) {
6624 return map_nt_error_from_unix(errno);
6629 /* XXX: need to add support for changing the create_time here. You
6630 * can do this for paths on Darwin with setattrlist(2). The right way
6631 * to hook this up is probably by extending the VFS utimes interface.
6634 return NT_STATUS_OK;
6637 /****************************************************************************
6638 Create a directory with POSIX semantics.
6639 ****************************************************************************/
6641 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6642 struct smb_request *req,
6645 struct smb_filename *smb_fname,
6646 int *pdata_return_size)
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, &smb_fname->st, raw_unixmode,
6665 PERM_NEW_DIR, &unixmode);
6666 if (!NT_STATUS_IS_OK(status)) {
6670 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6672 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6673 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
6675 status = SMB_VFS_CREATE_FILE(
6678 0, /* root_dir_fid */
6679 smb_fname, /* fname */
6680 FILE_READ_ATTRIBUTES, /* access_mask */
6681 FILE_SHARE_NONE, /* share_access */
6682 FILE_CREATE, /* create_disposition*/
6683 FILE_DIRECTORY_FILE, /* create_options */
6684 mod_unixmode, /* file_attributes */
6685 0, /* oplock_request */
6686 0, /* allocation_size */
6692 if (NT_STATUS_IS_OK(status)) {
6693 close_file(req, fsp, NORMAL_CLOSE);
6696 info_level_return = SVAL(pdata,16);
6698 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6699 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6700 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6701 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6703 *pdata_return_size = 12;
6706 /* Realloc the data size */
6707 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6708 if (*ppdata == NULL) {
6709 *pdata_return_size = 0;
6710 return NT_STATUS_NO_MEMORY;
6714 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6715 SSVAL(pdata,2,0); /* No fnum. */
6716 SIVAL(pdata,4,info); /* Was directory created. */
6718 switch (info_level_return) {
6719 case SMB_QUERY_FILE_UNIX_BASIC:
6720 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6721 SSVAL(pdata,10,0); /* Padding. */
6722 store_file_unix_basic(conn, pdata + 12, fsp,
6725 case SMB_QUERY_FILE_UNIX_INFO2:
6726 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6727 SSVAL(pdata,10,0); /* Padding. */
6728 store_file_unix_basic_info2(conn, pdata + 12, fsp,
6732 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6733 SSVAL(pdata,10,0); /* Padding. */
6740 /****************************************************************************
6741 Open/Create a file with POSIX semantics.
6742 ****************************************************************************/
6744 static NTSTATUS smb_posix_open(connection_struct *conn,
6745 struct smb_request *req,
6748 struct smb_filename *smb_fname,
6749 int *pdata_return_size)
6751 bool extended_oplock_granted = False;
6752 char *pdata = *ppdata;
6754 uint32 wire_open_mode = 0;
6755 uint32 raw_unixmode = 0;
6756 uint32 mod_unixmode = 0;
6757 uint32 create_disp = 0;
6758 uint32 access_mask = 0;
6759 uint32 create_options = 0;
6760 NTSTATUS status = NT_STATUS_OK;
6761 mode_t unixmode = (mode_t)0;
6762 files_struct *fsp = NULL;
6763 int oplock_request = 0;
6765 uint16 info_level_return = 0;
6767 if (total_data < 18) {
6768 return NT_STATUS_INVALID_PARAMETER;
6771 flags = IVAL(pdata,0);
6772 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6773 if (oplock_request) {
6774 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6777 wire_open_mode = IVAL(pdata,4);
6779 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6780 return smb_posix_mkdir(conn, req,
6787 switch (wire_open_mode & SMB_ACCMODE) {
6789 access_mask = FILE_READ_DATA;
6792 access_mask = FILE_WRITE_DATA;
6795 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6798 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6799 (unsigned int)wire_open_mode ));
6800 return NT_STATUS_INVALID_PARAMETER;
6803 wire_open_mode &= ~SMB_ACCMODE;
6805 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6806 create_disp = FILE_CREATE;
6807 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6808 create_disp = FILE_OVERWRITE_IF;
6809 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6810 create_disp = FILE_OPEN_IF;
6811 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6812 create_disp = FILE_OPEN;
6814 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6815 (unsigned int)wire_open_mode ));
6816 return NT_STATUS_INVALID_PARAMETER;
6819 raw_unixmode = IVAL(pdata,8);
6820 /* Next 4 bytes are not yet defined. */
6822 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6823 (VALID_STAT(smb_fname->st) ?
6824 PERM_EXISTING_FILE : PERM_NEW_FILE),
6827 if (!NT_STATUS_IS_OK(status)) {
6831 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6833 if (wire_open_mode & SMB_O_SYNC) {
6834 create_options |= FILE_WRITE_THROUGH;
6836 if (wire_open_mode & SMB_O_APPEND) {
6837 access_mask |= FILE_APPEND_DATA;
6839 if (wire_open_mode & SMB_O_DIRECT) {
6840 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6843 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6844 smb_fname_str_dbg(smb_fname),
6845 (unsigned int)wire_open_mode,
6846 (unsigned int)unixmode ));
6848 status = SMB_VFS_CREATE_FILE(
6851 0, /* root_dir_fid */
6852 smb_fname, /* fname */
6853 access_mask, /* access_mask */
6854 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6856 create_disp, /* create_disposition*/
6857 FILE_NON_DIRECTORY_FILE, /* create_options */
6858 mod_unixmode, /* file_attributes */
6859 oplock_request, /* oplock_request */
6860 0, /* allocation_size */
6866 if (!NT_STATUS_IS_OK(status)) {
6870 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6871 extended_oplock_granted = True;
6874 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6875 extended_oplock_granted = True;
6878 info_level_return = SVAL(pdata,16);
6880 /* Allocate the correct return size. */
6882 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6883 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6884 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6885 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6887 *pdata_return_size = 12;
6890 /* Realloc the data size */
6891 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6892 if (*ppdata == NULL) {
6893 close_file(req, fsp, ERROR_CLOSE);
6894 *pdata_return_size = 0;
6895 return NT_STATUS_NO_MEMORY;
6899 if (extended_oplock_granted) {
6900 if (flags & REQUEST_BATCH_OPLOCK) {
6901 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6903 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6905 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6906 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6908 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6911 SSVAL(pdata,2,fsp->fnum);
6912 SIVAL(pdata,4,info); /* Was file created etc. */
6914 switch (info_level_return) {
6915 case SMB_QUERY_FILE_UNIX_BASIC:
6916 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6917 SSVAL(pdata,10,0); /* padding. */
6918 store_file_unix_basic(conn, pdata + 12, fsp,
6921 case SMB_QUERY_FILE_UNIX_INFO2:
6922 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6923 SSVAL(pdata,10,0); /* padding. */
6924 store_file_unix_basic_info2(conn, pdata + 12, fsp,
6928 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6929 SSVAL(pdata,10,0); /* padding. */
6932 return NT_STATUS_OK;
6935 /****************************************************************************
6936 Delete a file with POSIX semantics.
6937 ****************************************************************************/
6939 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6940 struct smb_request *req,
6943 struct smb_filename *smb_fname)
6945 NTSTATUS status = NT_STATUS_OK;
6946 files_struct *fsp = NULL;
6950 int create_options = 0;
6952 struct share_mode_lock *lck = NULL;
6954 if (total_data < 2) {
6955 return NT_STATUS_INVALID_PARAMETER;
6958 flags = SVAL(pdata,0);
6960 if (!VALID_STAT(smb_fname->st)) {
6961 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6964 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6965 !VALID_STAT_OF_DIR(smb_fname->st)) {
6966 return NT_STATUS_NOT_A_DIRECTORY;
6969 DEBUG(10,("smb_posix_unlink: %s %s\n",
6970 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6971 smb_fname_str_dbg(smb_fname)));
6973 if (VALID_STAT_OF_DIR(smb_fname->st)) {
6974 create_options |= FILE_DIRECTORY_FILE;
6977 status = SMB_VFS_CREATE_FILE(
6980 0, /* root_dir_fid */
6981 smb_fname, /* fname */
6982 DELETE_ACCESS, /* access_mask */
6983 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6985 FILE_OPEN, /* create_disposition*/
6986 create_options, /* create_options */
6987 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
6988 0, /* oplock_request */
6989 0, /* allocation_size */
6995 if (!NT_STATUS_IS_OK(status)) {
7000 * Don't lie to client. If we can't really delete due to
7001 * non-POSIX opens return SHARING_VIOLATION.
7004 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7007 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7008 "lock for file %s\n", fsp_str_dbg(fsp)));
7009 close_file(req, fsp, NORMAL_CLOSE);
7010 return NT_STATUS_INVALID_PARAMETER;
7014 * See if others still have the file open. If this is the case, then
7015 * don't delete. If all opens are POSIX delete we can set the delete
7016 * on close disposition.
7018 for (i=0; i<lck->num_share_modes; i++) {
7019 struct share_mode_entry *e = &lck->share_modes[i];
7020 if (is_valid_share_mode_entry(e)) {
7021 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7024 /* Fail with sharing violation. */
7025 close_file(req, fsp, NORMAL_CLOSE);
7027 return NT_STATUS_SHARING_VIOLATION;
7032 * Set the delete on close.
7034 status = smb_set_file_disposition_info(conn,
7040 if (!NT_STATUS_IS_OK(status)) {
7041 close_file(req, fsp, NORMAL_CLOSE);
7046 return close_file(req, fsp, NORMAL_CLOSE);
7049 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7050 struct smb_request *req,
7051 TALLOC_CTX *mem_ctx,
7052 uint16_t info_level,
7054 struct smb_filename *smb_fname,
7055 char **ppdata, int total_data,
7058 char *pdata = *ppdata;
7060 NTSTATUS status = NT_STATUS_OK;
7061 int data_return_size = 0;
7065 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7066 return NT_STATUS_INVALID_LEVEL;
7069 if (!CAN_WRITE(conn)) {
7070 /* Allow POSIX opens. The open path will deny
7071 * any non-readonly opens. */
7072 if (info_level != SMB_POSIX_PATH_OPEN) {
7073 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7077 status = get_full_smb_filename(mem_ctx, smb_fname, &fname);
7078 if (!NT_STATUS_IS_OK(status)) {
7082 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7083 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7084 fsp ? fsp->fnum : -1, info_level, total_data));
7086 switch (info_level) {
7088 case SMB_INFO_STANDARD:
7090 status = smb_set_info_standard(conn,
7098 case SMB_INFO_SET_EA:
7100 status = smb_info_set_ea(conn,
7108 case SMB_SET_FILE_BASIC_INFO:
7109 case SMB_FILE_BASIC_INFORMATION:
7111 status = smb_set_file_basic_info(conn,
7119 case SMB_FILE_ALLOCATION_INFORMATION:
7120 case SMB_SET_FILE_ALLOCATION_INFO:
7122 status = smb_set_file_allocation_info(conn, req,
7130 case SMB_FILE_END_OF_FILE_INFORMATION:
7131 case SMB_SET_FILE_END_OF_FILE_INFO:
7133 status = smb_set_file_end_of_file_info(conn, req,
7141 case SMB_FILE_DISPOSITION_INFORMATION:
7142 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7145 /* JRA - We used to just ignore this on a path ?
7146 * Shouldn't this be invalid level on a pathname
7149 if (tran_call != TRANSACT2_SETFILEINFO) {
7150 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7153 status = smb_set_file_disposition_info(conn,
7161 case SMB_FILE_POSITION_INFORMATION:
7163 status = smb_file_position_information(conn,
7170 /* From tridge Samba4 :
7171 * MODE_INFORMATION in setfileinfo (I have no
7172 * idea what "mode information" on a file is - it takes a value of 0,
7173 * 2, 4 or 6. What could it be?).
7176 case SMB_FILE_MODE_INFORMATION:
7178 status = smb_file_mode_information(conn,
7185 * CIFS UNIX extensions.
7188 case SMB_SET_FILE_UNIX_BASIC:
7190 status = smb_set_file_unix_basic(conn, req,
7198 case SMB_SET_FILE_UNIX_INFO2:
7200 status = smb_set_file_unix_info2(conn, req,
7208 case SMB_SET_FILE_UNIX_LINK:
7211 /* We must have a pathname for this. */
7212 return NT_STATUS_INVALID_LEVEL;
7214 status = smb_set_file_unix_link(conn, req, pdata,
7215 total_data, smb_fname);
7219 case SMB_SET_FILE_UNIX_HLINK:
7222 /* We must have a pathname for this. */
7223 return NT_STATUS_INVALID_LEVEL;
7225 status = smb_set_file_unix_hlink(conn, req,
7231 case SMB_FILE_RENAME_INFORMATION:
7233 status = smb_file_rename_information(conn, req,
7239 #if defined(HAVE_POSIX_ACLS)
7240 case SMB_SET_POSIX_ACL:
7242 status = smb_set_posix_acl(conn,
7251 case SMB_SET_POSIX_LOCK:
7254 return NT_STATUS_INVALID_LEVEL;
7256 status = smb_set_posix_lock(conn, req,
7257 pdata, total_data, fsp);
7261 case SMB_POSIX_PATH_OPEN:
7264 /* We must have a pathname for this. */
7265 return NT_STATUS_INVALID_LEVEL;
7268 status = smb_posix_open(conn, req,
7276 case SMB_POSIX_PATH_UNLINK:
7279 /* We must have a pathname for this. */
7280 return NT_STATUS_INVALID_LEVEL;
7283 status = smb_posix_unlink(conn, req,
7291 return NT_STATUS_INVALID_LEVEL;
7294 if (!NT_STATUS_IS_OK(status)) {
7298 *ret_data_size = data_return_size;
7299 return NT_STATUS_OK;
7302 /****************************************************************************
7303 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7304 ****************************************************************************/
7306 static void call_trans2setfilepathinfo(connection_struct *conn,
7307 struct smb_request *req,
7308 unsigned int tran_call,
7309 char **pparams, int total_params,
7310 char **ppdata, int total_data,
7311 unsigned int max_data_bytes)
7313 char *params = *pparams;
7314 char *pdata = *ppdata;
7316 struct smb_filename *smb_fname = NULL;
7317 files_struct *fsp = NULL;
7318 NTSTATUS status = NT_STATUS_OK;
7319 int data_return_size = 0;
7322 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7326 if (tran_call == TRANSACT2_SETFILEINFO) {
7327 if (total_params < 4) {
7328 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7332 fsp = file_fsp(req, SVAL(params,0));
7333 /* Basic check for non-null fsp. */
7334 if (!check_fsp_open(conn, req, fsp)) {
7337 info_level = SVAL(params,2);
7339 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7341 if (!NT_STATUS_IS_OK(status)) {
7342 reply_nterror(req, status);
7346 if(fsp->is_directory || fsp->fh->fd == -1) {
7348 * This is actually a SETFILEINFO on a directory
7349 * handle (returned from an NT SMB). NT5.0 seems
7350 * to do this call. JRA.
7352 if (INFO_LEVEL_IS_UNIX(info_level)) {
7353 /* Always do lstat for UNIX calls. */
7354 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7355 DEBUG(3,("call_trans2setfilepathinfo: "
7356 "SMB_VFS_LSTAT of %s failed "
7358 smb_fname_str_dbg(smb_fname),
7360 reply_nterror(req, map_nt_error_from_unix(errno));
7364 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7365 DEBUG(3,("call_trans2setfilepathinfo: "
7366 "fileinfo of %s failed (%s)\n",
7367 smb_fname_str_dbg(smb_fname),
7369 reply_nterror(req, map_nt_error_from_unix(errno));
7373 } else if (fsp->print_file) {
7375 * Doing a DELETE_ON_CLOSE should cancel a print job.
7377 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7378 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
7380 DEBUG(3,("call_trans2setfilepathinfo: "
7381 "Cancelling print job (%s)\n",
7385 send_trans2_replies(conn, req, params, 2,
7390 reply_doserror(req, ERRDOS, ERRbadpath);
7395 * Original code - this is an open file.
7397 if (!check_fsp(conn, req, fsp)) {
7401 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7402 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7403 "of fnum %d failed (%s)\n", fsp->fnum,
7405 reply_nterror(req, map_nt_error_from_unix(errno));
7413 if (total_params < 7) {
7414 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7418 info_level = SVAL(params,0);
7419 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
7420 total_params - 6, STR_TERMINATE,
7422 if (!NT_STATUS_IS_OK(status)) {
7423 reply_nterror(req, status);
7427 status = filename_convert(req, conn,
7428 req->flags2 & FLAGS2_DFS_PATHNAMES,
7431 if (!NT_STATUS_IS_OK(status)) {
7432 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7433 reply_botherror(req,
7434 NT_STATUS_PATH_NOT_COVERED,
7435 ERRSRV, ERRbadpath);
7438 reply_nterror(req, status);
7442 if (INFO_LEVEL_IS_UNIX(info_level)) {
7444 * For CIFS UNIX extensions the target name may not exist.
7447 /* Always do lstat for UNIX calls. */
7448 SMB_VFS_LSTAT(conn, smb_fname);
7450 } else if (!VALID_STAT(smb_fname->st) &&
7451 SMB_VFS_STAT(conn, smb_fname)) {
7452 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7454 smb_fname_str_dbg(smb_fname),
7456 reply_nterror(req, map_nt_error_from_unix(errno));
7461 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7462 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
7463 fsp ? fsp->fnum : -1, info_level,total_data));
7465 /* Realloc the parameter size */
7466 *pparams = (char *)SMB_REALLOC(*pparams,2);
7467 if (*pparams == NULL) {
7468 reply_nterror(req, NT_STATUS_NO_MEMORY);
7475 status = smbd_do_setfilepathinfo(conn, req, req,
7481 if (!NT_STATUS_IS_OK(status)) {
7482 if (open_was_deferred(req->mid)) {
7483 /* We have re-scheduled this call. */
7486 if (blocking_lock_was_deferred(req->mid)) {
7487 /* We have re-scheduled this call. */
7490 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7491 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7492 ERRSRV, ERRbadpath);
7495 if (info_level == SMB_POSIX_PATH_OPEN) {
7496 reply_openerror(req, status);
7500 reply_nterror(req, status);
7504 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7510 /****************************************************************************
7511 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7512 ****************************************************************************/
7514 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7515 char **pparams, int total_params,
7516 char **ppdata, int total_data,
7517 unsigned int max_data_bytes)
7519 struct smb_filename *smb_dname = NULL;
7520 char *params = *pparams;
7521 char *pdata = *ppdata;
7522 char *directory = NULL;
7523 NTSTATUS status = NT_STATUS_OK;
7524 struct ea_list *ea_list = NULL;
7525 TALLOC_CTX *ctx = talloc_tos();
7527 if (!CAN_WRITE(conn)) {
7528 reply_doserror(req, ERRSRV, ERRaccess);
7532 if (total_params < 5) {
7533 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7537 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7538 total_params - 4, STR_TERMINATE,
7540 if (!NT_STATUS_IS_OK(status)) {
7541 reply_nterror(req, status);
7545 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7547 status = filename_convert(ctx,
7549 req->flags2 & FLAGS2_DFS_PATHNAMES,
7553 if (!NT_STATUS_IS_OK(status)) {
7554 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7555 reply_botherror(req,
7556 NT_STATUS_PATH_NOT_COVERED,
7557 ERRSRV, ERRbadpath);
7560 reply_nterror(req, status);
7564 /* Any data in this call is an EA list. */
7565 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7566 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7571 * OS/2 workplace shell seems to send SET_EA requests of "null"
7572 * length (4 bytes containing IVAL 4).
7573 * They seem to have no effect. Bug #3212. JRA.
7576 if (total_data != 4) {
7577 if (total_data < 10) {
7578 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7582 if (IVAL(pdata,0) > total_data) {
7583 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7584 IVAL(pdata,0), (unsigned int)total_data));
7585 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7589 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7592 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7596 /* If total_data == 4 Windows doesn't care what values
7597 * are placed in that field, it just ignores them.
7598 * The System i QNTC IBM SMB client puts bad values here,
7599 * so ignore them. */
7601 status = create_directory(conn, req, smb_dname);
7603 if (!NT_STATUS_IS_OK(status)) {
7604 reply_nterror(req, status);
7608 /* Try and set any given EA. */
7610 status = set_ea(conn, NULL, smb_dname, ea_list);
7611 if (!NT_STATUS_IS_OK(status)) {
7612 reply_nterror(req, status);
7617 /* Realloc the parameter and data sizes */
7618 *pparams = (char *)SMB_REALLOC(*pparams,2);
7619 if(*pparams == NULL) {
7620 reply_nterror(req, NT_STATUS_NO_MEMORY);
7627 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7630 TALLOC_FREE(smb_dname);
7634 /****************************************************************************
7635 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7636 We don't actually do this - we just send a null response.
7637 ****************************************************************************/
7639 static void call_trans2findnotifyfirst(connection_struct *conn,
7640 struct smb_request *req,
7641 char **pparams, int total_params,
7642 char **ppdata, int total_data,
7643 unsigned int max_data_bytes)
7645 char *params = *pparams;
7648 if (total_params < 6) {
7649 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7653 info_level = SVAL(params,4);
7654 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7656 switch (info_level) {
7661 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7665 /* Realloc the parameter and data sizes */
7666 *pparams = (char *)SMB_REALLOC(*pparams,6);
7667 if (*pparams == NULL) {
7668 reply_nterror(req, NT_STATUS_NO_MEMORY);
7673 SSVAL(params,0,fnf_handle);
7674 SSVAL(params,2,0); /* No changes */
7675 SSVAL(params,4,0); /* No EA errors */
7682 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7687 /****************************************************************************
7688 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7689 changes). Currently this does nothing.
7690 ****************************************************************************/
7692 static void call_trans2findnotifynext(connection_struct *conn,
7693 struct smb_request *req,
7694 char **pparams, int total_params,
7695 char **ppdata, int total_data,
7696 unsigned int max_data_bytes)
7698 char *params = *pparams;
7700 DEBUG(3,("call_trans2findnotifynext\n"));
7702 /* Realloc the parameter and data sizes */
7703 *pparams = (char *)SMB_REALLOC(*pparams,4);
7704 if (*pparams == NULL) {
7705 reply_nterror(req, NT_STATUS_NO_MEMORY);
7710 SSVAL(params,0,0); /* No changes */
7711 SSVAL(params,2,0); /* No EA errors */
7713 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7718 /****************************************************************************
7719 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7720 ****************************************************************************/
7722 static void call_trans2getdfsreferral(connection_struct *conn,
7723 struct smb_request *req,
7724 char **pparams, int total_params,
7725 char **ppdata, int total_data,
7726 unsigned int max_data_bytes)
7728 char *params = *pparams;
7729 char *pathname = NULL;
7731 int max_referral_level;
7732 NTSTATUS status = NT_STATUS_OK;
7733 TALLOC_CTX *ctx = talloc_tos();
7735 DEBUG(10,("call_trans2getdfsreferral\n"));
7737 if (total_params < 3) {
7738 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7742 max_referral_level = SVAL(params,0);
7744 if(!lp_host_msdfs()) {
7745 reply_doserror(req, ERRDOS, ERRbadfunc);
7749 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7750 total_params - 2, STR_TERMINATE);
7752 reply_nterror(req, NT_STATUS_NOT_FOUND);
7755 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7756 ppdata,&status)) < 0) {
7757 reply_nterror(req, status);
7761 SSVAL(req->inbuf, smb_flg2,
7762 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7763 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7768 #define LMCAT_SPL 0x53
7769 #define LMFUNC_GETJOBID 0x60
7771 /****************************************************************************
7772 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7773 ****************************************************************************/
7775 static void call_trans2ioctl(connection_struct *conn,
7776 struct smb_request *req,
7777 char **pparams, int total_params,
7778 char **ppdata, int total_data,
7779 unsigned int max_data_bytes)
7781 char *pdata = *ppdata;
7782 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7784 /* check for an invalid fid before proceeding */
7787 reply_doserror(req, ERRDOS, ERRbadfid);
7791 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7792 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7793 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7794 if (*ppdata == NULL) {
7795 reply_nterror(req, NT_STATUS_NO_MEMORY);
7800 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7801 CAN ACCEPT THIS IN UNICODE. JRA. */
7803 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7804 srvstr_push(pdata, req->flags2, pdata + 2,
7805 global_myname(), 15,
7806 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7807 srvstr_push(pdata, req->flags2, pdata+18,
7808 lp_servicename(SNUM(conn)), 13,
7809 STR_ASCII|STR_TERMINATE); /* Service name */
7810 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7815 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7816 reply_doserror(req, ERRSRV, ERRerror);
7819 /****************************************************************************
7820 Reply to a SMBfindclose (stop trans2 directory search).
7821 ****************************************************************************/
7823 void reply_findclose(struct smb_request *req)
7827 START_PROFILE(SMBfindclose);
7830 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7831 END_PROFILE(SMBfindclose);
7835 dptr_num = SVALS(req->vwv+0, 0);
7837 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7839 dptr_close(&dptr_num);
7841 reply_outbuf(req, 0, 0);
7843 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7845 END_PROFILE(SMBfindclose);
7849 /****************************************************************************
7850 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7851 ****************************************************************************/
7853 void reply_findnclose(struct smb_request *req)
7857 START_PROFILE(SMBfindnclose);
7860 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7861 END_PROFILE(SMBfindnclose);
7865 dptr_num = SVAL(req->vwv+0, 0);
7867 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7869 /* We never give out valid handles for a
7870 findnotifyfirst - so any dptr_num is ok here.
7873 reply_outbuf(req, 0, 0);
7875 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7877 END_PROFILE(SMBfindnclose);
7881 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7882 struct trans_state *state)
7884 if (Protocol >= PROTOCOL_NT1) {
7885 req->flags2 |= 0x40; /* IS_LONG_NAME */
7886 SSVAL(req->inbuf,smb_flg2,req->flags2);
7889 if (conn->encrypt_level == Required && !req->encrypted) {
7890 if (state->call != TRANSACT2_QFSINFO &&
7891 state->call != TRANSACT2_SETFSINFO) {
7892 DEBUG(0,("handle_trans2: encryption required "
7894 (unsigned int)state->call));
7895 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7900 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
7902 /* Now we must call the relevant TRANS2 function */
7903 switch(state->call) {
7904 case TRANSACT2_OPEN:
7906 START_PROFILE(Trans2_open);
7907 call_trans2open(conn, req,
7908 &state->param, state->total_param,
7909 &state->data, state->total_data,
7910 state->max_data_return);
7911 END_PROFILE(Trans2_open);
7915 case TRANSACT2_FINDFIRST:
7917 START_PROFILE(Trans2_findfirst);
7918 call_trans2findfirst(conn, req,
7919 &state->param, state->total_param,
7920 &state->data, state->total_data,
7921 state->max_data_return);
7922 END_PROFILE(Trans2_findfirst);
7926 case TRANSACT2_FINDNEXT:
7928 START_PROFILE(Trans2_findnext);
7929 call_trans2findnext(conn, req,
7930 &state->param, state->total_param,
7931 &state->data, state->total_data,
7932 state->max_data_return);
7933 END_PROFILE(Trans2_findnext);
7937 case TRANSACT2_QFSINFO:
7939 START_PROFILE(Trans2_qfsinfo);
7940 call_trans2qfsinfo(conn, req,
7941 &state->param, state->total_param,
7942 &state->data, state->total_data,
7943 state->max_data_return);
7944 END_PROFILE(Trans2_qfsinfo);
7948 case TRANSACT2_SETFSINFO:
7950 START_PROFILE(Trans2_setfsinfo);
7951 call_trans2setfsinfo(conn, req,
7952 &state->param, state->total_param,
7953 &state->data, state->total_data,
7954 state->max_data_return);
7955 END_PROFILE(Trans2_setfsinfo);
7959 case TRANSACT2_QPATHINFO:
7960 case TRANSACT2_QFILEINFO:
7962 START_PROFILE(Trans2_qpathinfo);
7963 call_trans2qfilepathinfo(conn, req, state->call,
7964 &state->param, state->total_param,
7965 &state->data, state->total_data,
7966 state->max_data_return);
7967 END_PROFILE(Trans2_qpathinfo);
7971 case TRANSACT2_SETPATHINFO:
7972 case TRANSACT2_SETFILEINFO:
7974 START_PROFILE(Trans2_setpathinfo);
7975 call_trans2setfilepathinfo(conn, req, state->call,
7976 &state->param, state->total_param,
7977 &state->data, state->total_data,
7978 state->max_data_return);
7979 END_PROFILE(Trans2_setpathinfo);
7983 case TRANSACT2_FINDNOTIFYFIRST:
7985 START_PROFILE(Trans2_findnotifyfirst);
7986 call_trans2findnotifyfirst(conn, req,
7987 &state->param, state->total_param,
7988 &state->data, state->total_data,
7989 state->max_data_return);
7990 END_PROFILE(Trans2_findnotifyfirst);
7994 case TRANSACT2_FINDNOTIFYNEXT:
7996 START_PROFILE(Trans2_findnotifynext);
7997 call_trans2findnotifynext(conn, req,
7998 &state->param, state->total_param,
7999 &state->data, state->total_data,
8000 state->max_data_return);
8001 END_PROFILE(Trans2_findnotifynext);
8005 case TRANSACT2_MKDIR:
8007 START_PROFILE(Trans2_mkdir);
8008 call_trans2mkdir(conn, req,
8009 &state->param, state->total_param,
8010 &state->data, state->total_data,
8011 state->max_data_return);
8012 END_PROFILE(Trans2_mkdir);
8016 case TRANSACT2_GET_DFS_REFERRAL:
8018 START_PROFILE(Trans2_get_dfs_referral);
8019 call_trans2getdfsreferral(conn, req,
8020 &state->param, state->total_param,
8021 &state->data, state->total_data,
8022 state->max_data_return);
8023 END_PROFILE(Trans2_get_dfs_referral);
8027 case TRANSACT2_IOCTL:
8029 START_PROFILE(Trans2_ioctl);
8030 call_trans2ioctl(conn, req,
8031 &state->param, state->total_param,
8032 &state->data, state->total_data,
8033 state->max_data_return);
8034 END_PROFILE(Trans2_ioctl);
8039 /* Error in request */
8040 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8041 reply_doserror(req, ERRSRV,ERRerror);
8045 /****************************************************************************
8046 Reply to a SMBtrans2.
8047 ****************************************************************************/
8049 void reply_trans2(struct smb_request *req)
8051 connection_struct *conn = req->conn;
8056 unsigned int tran_call;
8057 struct trans_state *state;
8060 START_PROFILE(SMBtrans2);
8062 if (req->wct < 14) {
8063 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8064 END_PROFILE(SMBtrans2);
8068 dsoff = SVAL(req->vwv+12, 0);
8069 dscnt = SVAL(req->vwv+11, 0);
8070 psoff = SVAL(req->vwv+10, 0);
8071 pscnt = SVAL(req->vwv+9, 0);
8072 tran_call = SVAL(req->vwv+14, 0);
8074 result = allow_new_trans(conn->pending_trans, req->mid);
8075 if (!NT_STATUS_IS_OK(result)) {
8076 DEBUG(2, ("Got invalid trans2 request: %s\n",
8077 nt_errstr(result)));
8078 reply_nterror(req, result);
8079 END_PROFILE(SMBtrans2);
8084 switch (tran_call) {
8085 /* List the allowed trans2 calls on IPC$ */
8086 case TRANSACT2_OPEN:
8087 case TRANSACT2_GET_DFS_REFERRAL:
8088 case TRANSACT2_QFILEINFO:
8089 case TRANSACT2_QFSINFO:
8090 case TRANSACT2_SETFSINFO:
8093 reply_doserror(req, ERRSRV, ERRaccess);
8094 END_PROFILE(SMBtrans2);
8099 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8100 DEBUG(0, ("talloc failed\n"));
8101 reply_nterror(req, NT_STATUS_NO_MEMORY);
8102 END_PROFILE(SMBtrans2);
8106 state->cmd = SMBtrans2;
8108 state->mid = req->mid;
8109 state->vuid = req->vuid;
8110 state->setup_count = SVAL(req->vwv+13, 0);
8111 state->setup = NULL;
8112 state->total_param = SVAL(req->vwv+0, 0);
8113 state->param = NULL;
8114 state->total_data = SVAL(req->vwv+1, 0);
8116 state->max_param_return = SVAL(req->vwv+2, 0);
8117 state->max_data_return = SVAL(req->vwv+3, 0);
8118 state->max_setup_return = SVAL(req->vwv+4, 0);
8119 state->close_on_completion = BITSETW(req->vwv+5, 0);
8120 state->one_way = BITSETW(req->vwv+5, 1);
8122 state->call = tran_call;
8124 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8125 is so as a sanity check */
8126 if (state->setup_count != 1) {
8128 * Need to have rc=0 for ioctl to get job id for OS/2.
8129 * Network printing will fail if function is not successful.
8130 * Similar function in reply.c will be used if protocol
8131 * is LANMAN1.0 instead of LM1.2X002.
8132 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8133 * outbuf doesn't have to be set(only job id is used).
8135 if ( (state->setup_count == 4)
8136 && (tran_call == TRANSACT2_IOCTL)
8137 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8138 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8139 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8141 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8142 DEBUG(2,("Transaction is %d\n",tran_call));
8144 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8145 END_PROFILE(SMBtrans2);
8150 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8153 if (state->total_data) {
8155 if (trans_oob(state->total_data, 0, dscnt)
8156 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8160 /* Can't use talloc here, the core routines do realloc on the
8161 * params and data. */
8162 state->data = (char *)SMB_MALLOC(state->total_data);
8163 if (state->data == NULL) {
8164 DEBUG(0,("reply_trans2: data malloc fail for %u "
8165 "bytes !\n", (unsigned int)state->total_data));
8167 reply_nterror(req, NT_STATUS_NO_MEMORY);
8168 END_PROFILE(SMBtrans2);
8172 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8175 if (state->total_param) {
8177 if (trans_oob(state->total_param, 0, pscnt)
8178 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8182 /* Can't use talloc here, the core routines do realloc on the
8183 * params and data. */
8184 state->param = (char *)SMB_MALLOC(state->total_param);
8185 if (state->param == NULL) {
8186 DEBUG(0,("reply_trans: param malloc fail for %u "
8187 "bytes !\n", (unsigned int)state->total_param));
8188 SAFE_FREE(state->data);
8190 reply_nterror(req, NT_STATUS_NO_MEMORY);
8191 END_PROFILE(SMBtrans2);
8195 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8198 state->received_data = dscnt;
8199 state->received_param = pscnt;
8201 if ((state->received_param == state->total_param) &&
8202 (state->received_data == state->total_data)) {
8204 handle_trans2(conn, req, state);
8206 SAFE_FREE(state->data);
8207 SAFE_FREE(state->param);
8209 END_PROFILE(SMBtrans2);
8213 DLIST_ADD(conn->pending_trans, state);
8215 /* We need to send an interim response then receive the rest
8216 of the parameter/data bytes */
8217 reply_outbuf(req, 0, 0);
8218 show_msg((char *)req->outbuf);
8219 END_PROFILE(SMBtrans2);
8224 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8225 SAFE_FREE(state->data);
8226 SAFE_FREE(state->param);
8228 END_PROFILE(SMBtrans2);
8229 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8233 /****************************************************************************
8234 Reply to a SMBtranss2
8235 ****************************************************************************/
8237 void reply_transs2(struct smb_request *req)
8239 connection_struct *conn = req->conn;
8240 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8241 struct trans_state *state;
8243 START_PROFILE(SMBtranss2);
8245 show_msg((char *)req->inbuf);
8248 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8249 END_PROFILE(SMBtranss2);
8253 for (state = conn->pending_trans; state != NULL;
8254 state = state->next) {
8255 if (state->mid == req->mid) {
8260 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8261 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8262 END_PROFILE(SMBtranss2);
8266 /* Revise state->total_param and state->total_data in case they have
8267 changed downwards */
8269 if (SVAL(req->vwv+0, 0) < state->total_param)
8270 state->total_param = SVAL(req->vwv+0, 0);
8271 if (SVAL(req->vwv+1, 0) < state->total_data)
8272 state->total_data = SVAL(req->vwv+1, 0);
8274 pcnt = SVAL(req->vwv+2, 0);
8275 poff = SVAL(req->vwv+3, 0);
8276 pdisp = SVAL(req->vwv+4, 0);
8278 dcnt = SVAL(req->vwv+5, 0);
8279 doff = SVAL(req->vwv+6, 0);
8280 ddisp = SVAL(req->vwv+7, 0);
8282 state->received_param += pcnt;
8283 state->received_data += dcnt;
8285 if ((state->received_data > state->total_data) ||
8286 (state->received_param > state->total_param))
8290 if (trans_oob(state->total_param, pdisp, pcnt)
8291 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8294 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8298 if (trans_oob(state->total_data, ddisp, dcnt)
8299 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8302 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8305 if ((state->received_param < state->total_param) ||
8306 (state->received_data < state->total_data)) {
8307 END_PROFILE(SMBtranss2);
8311 handle_trans2(conn, req, state);
8313 DLIST_REMOVE(conn->pending_trans, state);
8314 SAFE_FREE(state->data);
8315 SAFE_FREE(state->param);
8318 END_PROFILE(SMBtranss2);
8323 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8324 DLIST_REMOVE(conn->pending_trans, state);
8325 SAFE_FREE(state->data);
8326 SAFE_FREE(state->param);
8328 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8329 END_PROFILE(SMBtranss2);