2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "smbd/globals.h"
29 #include "../libcli/auth/libcli_auth.h"
31 extern enum protocol_types Protocol;
33 #define DIR_ENTRY_SAFETY_MARGIN 4096
35 static char *store_file_unix_basic(connection_struct *conn,
38 const SMB_STRUCT_STAT *psbuf);
40 static char *store_file_unix_basic_info2(connection_struct *conn,
43 const SMB_STRUCT_STAT *psbuf);
45 /********************************************************************
46 Roundup a value to the nearest allocation roundup size boundary.
47 Only do this for Windows clients.
48 ********************************************************************/
50 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
52 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
54 /* Only roundup for Windows clients. */
55 enum remote_arch_types ra_type = get_remote_arch();
56 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
57 val = SMB_ROUNDUP(val,rval);
62 /****************************************************************************
63 Utility functions for dealing with extended attributes.
64 ****************************************************************************/
66 /****************************************************************************
67 Refuse to allow clients to overwrite our private xattrs.
68 ****************************************************************************/
70 static bool samba_private_attr_name(const char *unix_ea_name)
72 static const char * const prohibited_ea_names[] = {
73 SAMBA_POSIX_INHERITANCE_EA_NAME,
74 SAMBA_XATTR_DOS_ATTRIB,
80 for (i = 0; prohibited_ea_names[i]; i++) {
81 if (strequal( prohibited_ea_names[i], unix_ea_name))
84 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
85 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
91 /****************************************************************************
92 Get one EA value. Fill in a struct ea_struct.
93 ****************************************************************************/
95 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
96 files_struct *fsp, const char *fname,
97 const char *ea_name, struct ea_struct *pea)
99 /* Get the value of this xattr. Max size is 64k. */
100 size_t attr_size = 256;
106 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
108 return NT_STATUS_NO_MEMORY;
111 if (fsp && fsp->fh->fd != -1) {
112 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
114 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
117 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
123 return map_nt_error_from_unix(errno);
126 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
127 dump_data(10, (uint8 *)val, sizeret);
130 if (strnequal(ea_name, "user.", 5)) {
131 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
133 pea->name = talloc_strdup(mem_ctx, ea_name);
135 if (pea->name == NULL) {
137 return NT_STATUS_NO_MEMORY;
139 pea->value.data = (unsigned char *)val;
140 pea->value.length = (size_t)sizeret;
144 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
145 files_struct *fsp, const char *fname,
146 char ***pnames, size_t *pnum_names)
148 /* Get a list of all xattrs. Max namesize is 64k. */
149 size_t ea_namelist_size = 1024;
150 char *ea_namelist = NULL;
155 ssize_t sizeret = -1;
157 if (!lp_ea_support(SNUM(conn))) {
164 * TALLOC the result early to get the talloc hierarchy right.
167 names = TALLOC_ARRAY(mem_ctx, char *, 1);
169 DEBUG(0, ("talloc failed\n"));
170 return NT_STATUS_NO_MEMORY;
173 while (ea_namelist_size <= 65536) {
175 ea_namelist = TALLOC_REALLOC_ARRAY(
176 names, ea_namelist, char, ea_namelist_size);
177 if (ea_namelist == NULL) {
178 DEBUG(0, ("talloc failed\n"));
180 return NT_STATUS_NO_MEMORY;
183 if (fsp && fsp->fh->fd != -1) {
184 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
187 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
191 if ((sizeret == -1) && (errno == ERANGE)) {
192 ea_namelist_size *= 2;
201 return map_nt_error_from_unix(errno);
204 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
205 (unsigned int)sizeret));
215 * Ensure the result is 0-terminated
218 if (ea_namelist[sizeret-1] != '\0') {
220 return NT_STATUS_INTERNAL_ERROR;
228 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
232 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
234 DEBUG(0, ("talloc failed\n"));
236 return NT_STATUS_NO_MEMORY;
242 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
243 names[num_names++] = p;
247 *pnum_names = num_names;
251 /****************************************************************************
252 Return a linked list of the total EA's. Plus the total size
253 ****************************************************************************/
255 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
256 const char *fname, size_t *pea_total_len)
258 /* Get a list of all xattrs. Max namesize is 64k. */
261 struct ea_list *ea_list_head = NULL;
266 if (!lp_ea_support(SNUM(conn))) {
270 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
273 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
277 for (i=0; i<num_names; i++) {
278 struct ea_list *listp;
281 if (strnequal(names[i], "system.", 7)
282 || samba_private_attr_name(names[i]))
285 listp = TALLOC_P(mem_ctx, struct ea_list);
290 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
296 push_ascii_fstring(dos_ea_name, listp->ea.name);
299 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
301 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
302 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
303 (unsigned int)listp->ea.value.length));
305 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
309 /* Add on 4 for total length. */
310 if (*pea_total_len) {
314 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
315 (unsigned int)*pea_total_len));
320 /****************************************************************************
321 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
323 ****************************************************************************/
325 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
326 connection_struct *conn, struct ea_list *ea_list)
328 unsigned int ret_data_size = 4;
331 SMB_ASSERT(total_data_size >= 4);
333 if (!lp_ea_support(SNUM(conn))) {
338 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
341 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
342 dos_namelen = strlen(dos_ea_name);
343 if (dos_namelen > 255 || dos_namelen == 0) {
346 if (ea_list->ea.value.length > 65535) {
349 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
353 /* We know we have room. */
354 SCVAL(p,0,ea_list->ea.flags);
355 SCVAL(p,1,dos_namelen);
356 SSVAL(p,2,ea_list->ea.value.length);
357 fstrcpy(p+4, dos_ea_name);
358 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
360 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
361 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
364 ret_data_size = PTR_DIFF(p, pdata);
365 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
366 SIVAL(pdata,0,ret_data_size);
367 return ret_data_size;
370 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
372 unsigned int total_data_size,
373 unsigned int *ret_data_size,
374 connection_struct *conn,
375 struct ea_list *ea_list)
377 uint8_t *p = (uint8_t *)pdata;
378 uint8_t *last_start = NULL;
382 if (!lp_ea_support(SNUM(conn))) {
383 return NT_STATUS_NO_EAS_ON_FILE;
386 for (; ea_list; ea_list = ea_list->next) {
392 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
396 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
397 dos_namelen = strlen(dos_ea_name);
398 if (dos_namelen > 255 || dos_namelen == 0) {
399 return NT_STATUS_INTERNAL_ERROR;
401 if (ea_list->ea.value.length > 65535) {
402 return NT_STATUS_INTERNAL_ERROR;
405 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
408 size_t pad = 4 - (this_size % 4);
412 if (this_size > total_data_size) {
413 return NT_STATUS_INFO_LENGTH_MISMATCH;
416 /* We know we have room. */
417 SIVAL(p, 0x00, 0); /* next offset */
418 SCVAL(p, 0x04, ea_list->ea.flags);
419 SCVAL(p, 0x05, dos_namelen);
420 SSVAL(p, 0x06, ea_list->ea.value.length);
421 fstrcpy((char *)(p+0x08), dos_ea_name);
422 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
424 total_data_size -= this_size;
428 *ret_data_size = PTR_DIFF(p, pdata);
429 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
433 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
435 size_t total_ea_len = 0;
436 TALLOC_CTX *mem_ctx = NULL;
438 if (!lp_ea_support(SNUM(conn))) {
441 mem_ctx = talloc_tos();
442 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
446 /****************************************************************************
447 Ensure the EA name is case insensitive by matching any existing EA name.
448 ****************************************************************************/
450 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
453 TALLOC_CTX *mem_ctx = talloc_tos();
454 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
456 for (; ea_list; ea_list = ea_list->next) {
457 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
458 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
459 &unix_ea_name[5], ea_list->ea.name));
460 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
466 /****************************************************************************
467 Set or delete an extended attribute.
468 ****************************************************************************/
470 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
471 const struct smb_filename *smb_fname, struct ea_list *ea_list)
475 if (!lp_ea_support(SNUM(conn))) {
476 return NT_STATUS_EAS_NOT_SUPPORTED;
479 /* For now setting EAs on streams isn't supported. */
480 fname = smb_fname->base_name;
482 for (;ea_list; ea_list = ea_list->next) {
484 fstring unix_ea_name;
486 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
487 fstrcat(unix_ea_name, ea_list->ea.name);
489 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
491 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
493 if (samba_private_attr_name(unix_ea_name)) {
494 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
495 return NT_STATUS_ACCESS_DENIED;
498 if (ea_list->ea.value.length == 0) {
499 /* Remove the attribute. */
500 if (fsp && (fsp->fh->fd != -1)) {
501 DEBUG(10,("set_ea: deleting ea name %s on "
502 "file %s by file descriptor.\n",
503 unix_ea_name, fsp_str_dbg(fsp)));
504 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
506 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
507 unix_ea_name, fname));
508 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
511 /* Removing a non existent attribute always succeeds. */
512 if (ret == -1 && errno == ENOATTR) {
513 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
519 if (fsp && (fsp->fh->fd != -1)) {
520 DEBUG(10,("set_ea: setting ea name %s on file "
521 "%s by file descriptor.\n",
522 unix_ea_name, fsp_str_dbg(fsp)));
523 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
524 ea_list->ea.value.data, ea_list->ea.value.length, 0);
526 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
527 unix_ea_name, fname));
528 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
529 ea_list->ea.value.data, ea_list->ea.value.length, 0);
535 if (errno == ENOTSUP) {
536 return NT_STATUS_EAS_NOT_SUPPORTED;
539 return map_nt_error_from_unix(errno);
545 /****************************************************************************
546 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
547 ****************************************************************************/
549 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
551 struct ea_list *ea_list_head = NULL;
552 size_t converted_size, offset = 0;
554 while (offset + 2 < data_size) {
555 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
556 unsigned int namelen = CVAL(pdata,offset);
558 offset++; /* Go past the namelen byte. */
560 /* integer wrap paranioa. */
561 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
562 (offset > data_size) || (namelen > data_size) ||
563 (offset + namelen >= data_size)) {
566 /* Ensure the name is null terminated. */
567 if (pdata[offset + namelen] != '\0') {
570 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
572 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
573 "failed: %s", strerror(errno)));
579 offset += (namelen + 1); /* Go past the name + terminating zero. */
580 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
581 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
587 /****************************************************************************
588 Read one EA list entry from the buffer.
589 ****************************************************************************/
591 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
593 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
595 unsigned int namelen;
596 size_t converted_size;
606 eal->ea.flags = CVAL(pdata,0);
607 namelen = CVAL(pdata,1);
608 val_len = SVAL(pdata,2);
610 if (4 + namelen + 1 + val_len > data_size) {
614 /* Ensure the name is null terminated. */
615 if (pdata[namelen + 4] != '\0') {
618 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
619 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
626 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
627 if (!eal->ea.value.data) {
631 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
633 /* Ensure we're null terminated just in case we print the value. */
634 eal->ea.value.data[val_len] = '\0';
635 /* But don't count the null. */
636 eal->ea.value.length--;
639 *pbytes_used = 4 + namelen + 1 + val_len;
642 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
643 dump_data(10, eal->ea.value.data, eal->ea.value.length);
648 /****************************************************************************
649 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
650 ****************************************************************************/
652 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
654 struct ea_list *ea_list_head = NULL;
656 size_t bytes_used = 0;
658 while (offset < data_size) {
659 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
665 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
666 offset += bytes_used;
672 /****************************************************************************
673 Count the total EA size needed.
674 ****************************************************************************/
676 static size_t ea_list_size(struct ea_list *ealist)
679 struct ea_list *listp;
682 for (listp = ealist; listp; listp = listp->next) {
683 push_ascii_fstring(dos_ea_name, listp->ea.name);
684 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
686 /* Add on 4 for total length. */
694 /****************************************************************************
695 Return a union of EA's from a file list and a list of names.
696 The TALLOC context for the two lists *MUST* be identical as we steal
697 memory from one list to add to another. JRA.
698 ****************************************************************************/
700 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
702 struct ea_list *nlistp, *flistp;
704 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
705 for (flistp = file_list; flistp; flistp = flistp->next) {
706 if (strequal(nlistp->ea.name, flistp->ea.name)) {
712 /* Copy the data from this entry. */
713 nlistp->ea.flags = flistp->ea.flags;
714 nlistp->ea.value = flistp->ea.value;
717 nlistp->ea.flags = 0;
718 ZERO_STRUCT(nlistp->ea.value);
722 *total_ea_len = ea_list_size(name_list);
726 /****************************************************************************
727 Send the required number of replies back.
728 We assume all fields other than the data fields are
729 set correctly for the type of call.
730 HACK ! Always assumes smb_setup field is zero.
731 ****************************************************************************/
733 void send_trans2_replies(connection_struct *conn,
734 struct smb_request *req,
741 /* As we are using a protocol > LANMAN1 then the max_send
742 variable must have been set in the sessetupX call.
743 This takes precedence over the max_xmit field in the
744 global struct. These different max_xmit variables should
745 be merged as this is now too confusing */
747 int data_to_send = datasize;
748 int params_to_send = paramsize;
750 const char *pp = params;
751 const char *pd = pdata;
752 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
753 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
754 int data_alignment_offset = 0;
755 bool overflow = False;
756 struct smbd_server_connection *sconn = smbd_server_conn;
757 int max_send = sconn->smb1.sessions.max_send;
759 /* Modify the data_to_send and datasize and set the error if
760 we're trying to send more than max_data_bytes. We still send
761 the part of the packet(s) that fit. Strange, but needed
764 if (max_data_bytes > 0 && datasize > max_data_bytes) {
765 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
766 max_data_bytes, datasize ));
767 datasize = data_to_send = max_data_bytes;
771 /* If there genuinely are no parameters or data to send just send the empty packet */
773 if(params_to_send == 0 && data_to_send == 0) {
774 reply_outbuf(req, 10, 0);
775 show_msg((char *)req->outbuf);
776 if (!srv_send_smb(smbd_server_fd(),
779 IS_CONN_ENCRYPTED(conn),
781 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
783 TALLOC_FREE(req->outbuf);
787 /* When sending params and data ensure that both are nicely aligned */
788 /* Only do this alignment when there is also data to send - else
789 can cause NT redirector problems. */
791 if (((params_to_send % 4) != 0) && (data_to_send != 0))
792 data_alignment_offset = 4 - (params_to_send % 4);
794 /* Space is bufsize minus Netbios over TCP header minus SMB header */
795 /* The alignment_offset is to align the param bytes on an even byte
796 boundary. NT 4.0 Beta needs this to work correctly. */
798 useable_space = max_send - (smb_size
801 + data_alignment_offset);
803 if (useable_space < 0) {
804 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
805 "= %d!!!", useable_space));
806 exit_server_cleanly("send_trans2_replies: Not enough space");
809 while (params_to_send || data_to_send) {
810 /* Calculate whether we will totally or partially fill this packet */
812 total_sent_thistime = params_to_send + data_to_send;
814 /* We can never send more than useable_space */
816 * Note that 'useable_space' does not include the alignment offsets,
817 * but we must include the alignment offsets in the calculation of
818 * the length of the data we send over the wire, as the alignment offsets
819 * are sent here. Fix from Marc_Jacobsen@hp.com.
822 total_sent_thistime = MIN(total_sent_thistime, useable_space);
824 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
825 + data_alignment_offset);
828 * We might have SMBtrans2s in req which was transferred to
829 * the outbuf, fix that.
831 SCVAL(req->outbuf, smb_com, SMBtrans2);
833 /* Set total params and data to be sent */
834 SSVAL(req->outbuf,smb_tprcnt,paramsize);
835 SSVAL(req->outbuf,smb_tdrcnt,datasize);
837 /* Calculate how many parameters and data we can fit into
838 * this packet. Parameters get precedence
841 params_sent_thistime = MIN(params_to_send,useable_space);
842 data_sent_thistime = useable_space - params_sent_thistime;
843 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
845 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
847 /* smb_proff is the offset from the start of the SMB header to the
848 parameter bytes, however the first 4 bytes of outbuf are
849 the Netbios over TCP header. Thus use smb_base() to subtract
850 them from the calculation */
852 SSVAL(req->outbuf,smb_proff,
853 ((smb_buf(req->outbuf)+alignment_offset)
854 - smb_base(req->outbuf)));
856 if(params_sent_thistime == 0)
857 SSVAL(req->outbuf,smb_prdisp,0);
859 /* Absolute displacement of param bytes sent in this packet */
860 SSVAL(req->outbuf,smb_prdisp,pp - params);
862 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
863 if(data_sent_thistime == 0) {
864 SSVAL(req->outbuf,smb_droff,0);
865 SSVAL(req->outbuf,smb_drdisp, 0);
867 /* The offset of the data bytes is the offset of the
868 parameter bytes plus the number of parameters being sent this time */
869 SSVAL(req->outbuf, smb_droff,
870 ((smb_buf(req->outbuf)+alignment_offset)
871 - smb_base(req->outbuf))
872 + params_sent_thistime + data_alignment_offset);
873 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
876 /* Initialize the padding for alignment */
878 if (alignment_offset != 0) {
879 memset(smb_buf(req->outbuf), 0, alignment_offset);
882 /* Copy the param bytes into the packet */
884 if(params_sent_thistime) {
885 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
886 params_sent_thistime);
889 /* Copy in the data bytes */
890 if(data_sent_thistime) {
891 if (data_alignment_offset != 0) {
892 memset((smb_buf(req->outbuf)+alignment_offset+
893 params_sent_thistime), 0,
894 data_alignment_offset);
896 memcpy(smb_buf(req->outbuf)+alignment_offset
897 +params_sent_thistime+data_alignment_offset,
898 pd,data_sent_thistime);
901 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
902 params_sent_thistime, data_sent_thistime, useable_space));
903 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
904 params_to_send, data_to_send, paramsize, datasize));
907 error_packet_set((char *)req->outbuf,
908 ERRDOS,ERRbufferoverflow,
909 STATUS_BUFFER_OVERFLOW,
913 /* Send the packet */
914 show_msg((char *)req->outbuf);
915 if (!srv_send_smb(smbd_server_fd(),
918 IS_CONN_ENCRYPTED(conn),
920 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
922 TALLOC_FREE(req->outbuf);
924 pp += params_sent_thistime;
925 pd += data_sent_thistime;
927 params_to_send -= params_sent_thistime;
928 data_to_send -= data_sent_thistime;
931 if(params_to_send < 0 || data_to_send < 0) {
932 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
933 params_to_send, data_to_send));
941 /****************************************************************************
942 Reply to a TRANSACT2_OPEN.
943 ****************************************************************************/
945 static void call_trans2open(connection_struct *conn,
946 struct smb_request *req,
947 char **pparams, int total_params,
948 char **ppdata, int total_data,
949 unsigned int max_data_bytes)
951 struct smb_filename *smb_fname = NULL;
952 char *params = *pparams;
953 char *pdata = *ppdata;
958 bool return_additional_info;
971 struct ea_list *ea_list = NULL;
976 uint32 create_disposition;
977 uint32 create_options = 0;
978 TALLOC_CTX *ctx = talloc_tos();
981 * Ensure we have enough parameters to perform the operation.
984 if (total_params < 29) {
985 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
989 flags = SVAL(params, 0);
990 deny_mode = SVAL(params, 2);
991 open_attr = SVAL(params,6);
992 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
993 if (oplock_request) {
994 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
998 return_additional_info = BITSETW(params,0);
999 open_sattr = SVAL(params, 4);
1000 open_time = make_unix_date3(params+8);
1002 open_ofun = SVAL(params,12);
1003 open_size = IVAL(params,14);
1004 pname = ¶ms[28];
1007 reply_doserror(req, ERRSRV, ERRaccess);
1011 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1012 total_params - 28, STR_TERMINATE,
1014 if (!NT_STATUS_IS_OK(status)) {
1015 reply_nterror(req, status);
1019 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1020 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1021 (unsigned int)open_ofun, open_size));
1023 status = filename_convert(ctx,
1025 req->flags2 & FLAGS2_DFS_PATHNAMES,
1030 if (!NT_STATUS_IS_OK(status)) {
1031 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1032 reply_botherror(req,
1033 NT_STATUS_PATH_NOT_COVERED,
1034 ERRSRV, ERRbadpath);
1037 reply_nterror(req, status);
1041 if (open_ofun == 0) {
1042 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1046 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, open_ofun,
1047 &access_mask, &share_mode,
1048 &create_disposition,
1050 reply_doserror(req, ERRDOS, ERRbadaccess);
1054 /* Any data in this call is an EA list. */
1055 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
1056 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1060 if (total_data != 4) {
1061 if (total_data < 10) {
1062 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1066 if (IVAL(pdata,0) > total_data) {
1067 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1068 IVAL(pdata,0), (unsigned int)total_data));
1069 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1073 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1076 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1079 } else if (IVAL(pdata,0) != 4) {
1080 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1084 status = SMB_VFS_CREATE_FILE(
1087 0, /* root_dir_fid */
1088 smb_fname, /* fname */
1089 access_mask, /* access_mask */
1090 share_mode, /* share_access */
1091 create_disposition, /* create_disposition*/
1092 create_options, /* create_options */
1093 open_attr, /* file_attributes */
1094 oplock_request, /* oplock_request */
1095 open_size, /* allocation_size */
1097 ea_list, /* ea_list */
1099 &smb_action); /* psbuf */
1101 if (!NT_STATUS_IS_OK(status)) {
1102 if (open_was_deferred(req->mid)) {
1103 /* We have re-scheduled this call. */
1106 reply_openerror(req, status);
1110 size = get_file_size_stat(&smb_fname->st);
1111 fattr = dos_mode(conn, smb_fname);
1112 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1113 inode = smb_fname->st.st_ex_ino;
1115 close_file(req, fsp, ERROR_CLOSE);
1116 reply_doserror(req, ERRDOS,ERRnoaccess);
1120 /* Realloc the size of parameters and data we will return */
1121 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1122 if(*pparams == NULL ) {
1123 reply_nterror(req, NT_STATUS_NO_MEMORY);
1128 SSVAL(params,0,fsp->fnum);
1129 SSVAL(params,2,fattr);
1130 srv_put_dos_date2(params,4, mtime);
1131 SIVAL(params,8, (uint32)size);
1132 SSVAL(params,12,deny_mode);
1133 SSVAL(params,14,0); /* open_type - file or directory. */
1134 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1136 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1137 smb_action |= EXTENDED_OPLOCK_GRANTED;
1140 SSVAL(params,18,smb_action);
1143 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1145 SIVAL(params,20,inode);
1146 SSVAL(params,24,0); /* Padding. */
1148 uint32 ea_size = estimate_ea_size(conn, fsp,
1149 fsp->fsp_name->base_name);
1150 SIVAL(params, 26, ea_size);
1152 SIVAL(params, 26, 0);
1155 /* Send the required number of replies */
1156 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1158 TALLOC_FREE(smb_fname);
1161 /*********************************************************
1162 Routine to check if a given string matches exactly.
1163 as a special case a mask of "." does NOT match. That
1164 is required for correct wildcard semantics
1165 Case can be significant or not.
1166 **********************************************************/
1168 static bool exact_match(bool has_wild,
1169 bool case_sensitive,
1173 if (mask[0] == '.' && mask[1] == 0) {
1181 if (case_sensitive) {
1182 return strcmp(str,mask)==0;
1184 return StrCaseCmp(str,mask) == 0;
1188 /****************************************************************************
1189 Return the filetype for UNIX extensions.
1190 ****************************************************************************/
1192 static uint32 unix_filetype(mode_t mode)
1195 return UNIX_TYPE_FILE;
1196 else if(S_ISDIR(mode))
1197 return UNIX_TYPE_DIR;
1199 else if(S_ISLNK(mode))
1200 return UNIX_TYPE_SYMLINK;
1203 else if(S_ISCHR(mode))
1204 return UNIX_TYPE_CHARDEV;
1207 else if(S_ISBLK(mode))
1208 return UNIX_TYPE_BLKDEV;
1211 else if(S_ISFIFO(mode))
1212 return UNIX_TYPE_FIFO;
1215 else if(S_ISSOCK(mode))
1216 return UNIX_TYPE_SOCKET;
1219 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1220 return UNIX_TYPE_UNKNOWN;
1223 /****************************************************************************
1224 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1225 ****************************************************************************/
1227 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1229 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1230 const SMB_STRUCT_STAT *psbuf,
1232 enum perm_type ptype,
1237 if (perms == SMB_MODE_NO_CHANGE) {
1238 if (!VALID_STAT(*psbuf)) {
1239 return NT_STATUS_INVALID_PARAMETER;
1241 *ret_perms = psbuf->st_ex_mode;
1242 return NT_STATUS_OK;
1246 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1247 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1248 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1249 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1250 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1251 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1252 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1253 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1254 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1256 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1259 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1262 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1267 /* Apply mode mask */
1268 ret &= lp_create_mask(SNUM(conn));
1269 /* Add in force bits */
1270 ret |= lp_force_create_mode(SNUM(conn));
1273 ret &= lp_dir_mask(SNUM(conn));
1274 /* Add in force bits */
1275 ret |= lp_force_dir_mode(SNUM(conn));
1277 case PERM_EXISTING_FILE:
1278 /* Apply mode mask */
1279 ret &= lp_security_mask(SNUM(conn));
1280 /* Add in force bits */
1281 ret |= lp_force_security_mode(SNUM(conn));
1283 case PERM_EXISTING_DIR:
1284 /* Apply mode mask */
1285 ret &= lp_dir_security_mask(SNUM(conn));
1286 /* Add in force bits */
1287 ret |= lp_force_dir_security_mode(SNUM(conn));
1292 return NT_STATUS_OK;
1295 /****************************************************************************
1296 Needed to show the msdfs symlinks as directories. Modifies psbuf
1297 to be a directory if it's a msdfs link.
1298 ****************************************************************************/
1300 static bool check_msdfs_link(connection_struct *conn,
1301 const char *pathname,
1302 SMB_STRUCT_STAT *psbuf)
1304 int saved_errno = errno;
1305 if(lp_host_msdfs() &&
1306 lp_msdfs_root(SNUM(conn)) &&
1307 is_msdfs_link(conn, pathname, psbuf)) {
1309 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1312 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1313 errno = saved_errno;
1316 errno = saved_errno;
1321 /****************************************************************************
1322 Get a level dependent lanman2 dir entry.
1323 ****************************************************************************/
1325 struct smbd_dirptr_lanman2_state {
1326 connection_struct *conn;
1327 uint32_t info_level;
1328 bool check_mangled_names;
1330 bool got_exact_match;
1333 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1339 struct smbd_dirptr_lanman2_state *state =
1340 (struct smbd_dirptr_lanman2_state *)private_data;
1342 char mangled_name[13]; /* mangled 8.3 name. */
1346 /* Mangle fname if it's an illegal name. */
1347 if (mangle_must_mangle(dname, state->conn->params)) {
1348 ok = name_to_8_3(dname, mangled_name,
1349 true, state->conn->params);
1353 fname = mangled_name;
1358 got_match = exact_match(state->has_wild,
1359 state->conn->case_sensitive,
1361 state->got_exact_match = got_match;
1363 got_match = mask_match(fname, mask,
1364 state->conn->case_sensitive);
1367 if(!got_match && state->check_mangled_names &&
1368 !mangle_is_8_3(fname, false, state->conn->params)) {
1370 * It turns out that NT matches wildcards against
1371 * both long *and* short names. This may explain some
1372 * of the wildcard wierdness from old DOS clients
1373 * that some people have been seeing.... JRA.
1375 /* Force the mangling into 8.3. */
1376 ok = name_to_8_3(fname, mangled_name,
1377 false, state->conn->params);
1382 got_match = exact_match(state->has_wild,
1383 state->conn->case_sensitive,
1384 mangled_name, mask);
1385 state->got_exact_match = got_match;
1387 got_match = mask_match(mangled_name, mask,
1388 state->conn->case_sensitive);
1396 *_fname = talloc_strdup(ctx, fname);
1397 if (*_fname == NULL) {
1404 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1406 struct smb_filename *smb_fname,
1409 struct smbd_dirptr_lanman2_state *state =
1410 (struct smbd_dirptr_lanman2_state *)private_data;
1411 bool ms_dfs_link = false;
1414 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1415 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1416 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1417 "Couldn't lstat [%s] (%s)\n",
1418 smb_fname_str_dbg(smb_fname),
1422 } else if (!VALID_STAT(smb_fname->st) &&
1423 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1424 /* Needed to show the msdfs symlinks as
1427 ms_dfs_link = check_msdfs_link(state->conn,
1428 smb_fname->base_name,
1431 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1432 "Couldn't stat [%s] (%s)\n",
1433 smb_fname_str_dbg(smb_fname),
1440 mode = dos_mode_msdfs(state->conn, smb_fname);
1442 mode = dos_mode(state->conn, smb_fname);
1449 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1450 connection_struct *conn,
1451 struct dptr_struct *dirptr,
1453 const char *path_mask,
1456 int requires_resume_key,
1462 int space_remaining,
1464 bool *got_exact_match,
1465 int *last_entry_off,
1466 struct ea_list *name_list)
1468 const char *mask = NULL;
1469 char *p, *q, *pdata = *ppdata;
1473 SMB_OFF_T file_size = 0;
1474 uint64_t allocation_size = 0;
1476 struct timespec mdate_ts, adate_ts, create_date_ts;
1477 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1479 char *last_entry_ptr;
1481 uint32 nt_extmode; /* Used for NT connections instead of mode */
1483 struct smb_filename *smb_fname = NULL;
1484 struct smbd_dirptr_lanman2_state state;
1489 state.info_level = info_level;
1490 state.check_mangled_names = lp_manglednames(conn->params);
1491 state.has_wild = dptr_has_wild(dirptr);
1492 state.got_exact_match = false;
1494 *out_of_space = False;
1495 *got_exact_match = False;
1497 ZERO_STRUCT(mdate_ts);
1498 ZERO_STRUCT(adate_ts);
1499 ZERO_STRUCT(create_date_ts);
1501 p = strrchr_m(path_mask,'/');
1512 ok = smbd_dirptr_get_entry(ctx,
1518 smbd_dirptr_lanman2_match_fn,
1519 smbd_dirptr_lanman2_mode_fn,
1529 *got_exact_match = state.got_exact_match;
1531 if (!(mode & aDIR)) {
1532 file_size = get_file_size_stat(&smb_fname->st);
1534 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1536 mdate_ts = smb_fname->st.st_ex_mtime;
1537 adate_ts = smb_fname->st.st_ex_atime;
1538 create_date_ts = smb_fname->st.st_ex_btime;
1540 if (lp_dos_filetime_resolution(SNUM(conn))) {
1541 dos_filetime_timespec(&create_date_ts);
1542 dos_filetime_timespec(&mdate_ts);
1543 dos_filetime_timespec(&adate_ts);
1546 create_date = convert_timespec_to_time_t(create_date_ts);
1547 mdate = convert_timespec_to_time_t(mdate_ts);
1548 adate = convert_timespec_to_time_t(adate_ts);
1553 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1555 switch (info_level) {
1556 case SMB_FIND_INFO_STANDARD:
1557 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1558 if(requires_resume_key) {
1562 srv_put_dos_date2(p,0,create_date);
1563 srv_put_dos_date2(p,4,adate);
1564 srv_put_dos_date2(p,8,mdate);
1565 SIVAL(p,12,(uint32)file_size);
1566 SIVAL(p,16,(uint32)allocation_size);
1570 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1571 p += ucs2_align(base_data, p, 0);
1573 len = srvstr_push(base_data, flags2, p,
1574 fname, PTR_DIFF(end_data, p),
1576 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1578 SCVAL(nameptr, -1, len - 2);
1580 SCVAL(nameptr, -1, 0);
1584 SCVAL(nameptr, -1, len - 1);
1586 SCVAL(nameptr, -1, 0);
1592 case SMB_FIND_EA_SIZE:
1593 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1594 if(requires_resume_key) {
1598 srv_put_dos_date2(p,0,create_date);
1599 srv_put_dos_date2(p,4,adate);
1600 srv_put_dos_date2(p,8,mdate);
1601 SIVAL(p,12,(uint32)file_size);
1602 SIVAL(p,16,(uint32)allocation_size);
1605 unsigned int ea_size = estimate_ea_size(conn, NULL,
1606 smb_fname->base_name);
1607 SIVAL(p,22,ea_size); /* Extended attributes */
1611 len = srvstr_push(base_data, flags2,
1612 p, fname, PTR_DIFF(end_data, p),
1613 STR_TERMINATE | STR_NOALIGN);
1614 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1627 SCVAL(nameptr,0,len);
1629 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1632 case SMB_FIND_EA_LIST:
1634 struct ea_list *file_list = NULL;
1637 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1640 TALLOC_FREE(smb_fname);
1643 if(requires_resume_key) {
1647 srv_put_dos_date2(p,0,create_date);
1648 srv_put_dos_date2(p,4,adate);
1649 srv_put_dos_date2(p,8,mdate);
1650 SIVAL(p,12,(uint32)file_size);
1651 SIVAL(p,16,(uint32)allocation_size);
1653 p += 22; /* p now points to the EA area. */
1655 file_list = get_ea_list_from_file(ctx, conn, NULL,
1656 smb_fname->base_name,
1658 name_list = ea_list_union(name_list, file_list, &ea_len);
1660 /* We need to determine if this entry will fit in the space available. */
1661 /* Max string size is 255 bytes. */
1662 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1664 TALLOC_FREE(smb_fname);
1665 /* Move the dirptr back to prev_dirpos */
1666 dptr_SeekDir(dirptr, prev_dirpos);
1667 *out_of_space = True;
1668 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1669 return False; /* Not finished - just out of space */
1672 /* Push the ea_data followed by the name. */
1673 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1675 len = srvstr_push(base_data, flags2,
1676 p + 1, fname, PTR_DIFF(end_data, p+1),
1677 STR_TERMINATE | STR_NOALIGN);
1678 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1691 SCVAL(nameptr,0,len);
1693 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1697 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1698 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1699 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1701 SIVAL(p,0,reskey); p += 4;
1702 put_long_date_timespec(p,create_date_ts); p += 8;
1703 put_long_date_timespec(p,adate_ts); p += 8;
1704 put_long_date_timespec(p,mdate_ts); p += 8;
1705 put_long_date_timespec(p,mdate_ts); p += 8;
1706 SOFF_T(p,0,file_size); p += 8;
1707 SOFF_T(p,0,allocation_size); p += 8;
1708 SIVAL(p,0,nt_extmode); p += 4;
1709 q = p; p += 4; /* q is placeholder for name length. */
1711 unsigned int ea_size = estimate_ea_size(conn, NULL,
1712 smb_fname->base_name);
1713 SIVAL(p,0,ea_size); /* Extended attributes */
1716 /* Clear the short name buffer. This is
1717 * IMPORTANT as not doing so will trigger
1718 * a Win2k client bug. JRA.
1720 if (!was_8_3 && state.check_mangled_names) {
1721 char mangled_name[13]; /* mangled 8.3 name. */
1722 if (!name_to_8_3(fname,mangled_name,True,
1724 /* Error - mangle failed ! */
1725 memset(mangled_name,'\0',12);
1727 mangled_name[12] = 0;
1728 len = srvstr_push(base_data, flags2,
1729 p+2, mangled_name, 24,
1730 STR_UPPER|STR_UNICODE);
1732 memset(p + 2 + len,'\0',24 - len);
1739 len = srvstr_push(base_data, flags2, p,
1740 fname, PTR_DIFF(end_data, p),
1741 STR_TERMINATE_ASCII);
1744 SIVAL(p,0,0); /* Ensure any padding is null. */
1745 len = PTR_DIFF(p, pdata);
1746 len = (len + 3) & ~3;
1751 case SMB_FIND_FILE_DIRECTORY_INFO:
1752 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1754 SIVAL(p,0,reskey); p += 4;
1755 put_long_date_timespec(p,create_date_ts); p += 8;
1756 put_long_date_timespec(p,adate_ts); p += 8;
1757 put_long_date_timespec(p,mdate_ts); p += 8;
1758 put_long_date_timespec(p,mdate_ts); p += 8;
1759 SOFF_T(p,0,file_size); p += 8;
1760 SOFF_T(p,0,allocation_size); p += 8;
1761 SIVAL(p,0,nt_extmode); p += 4;
1762 len = srvstr_push(base_data, flags2,
1763 p + 4, fname, PTR_DIFF(end_data, p+4),
1764 STR_TERMINATE_ASCII);
1767 SIVAL(p,0,0); /* Ensure any padding is null. */
1768 len = PTR_DIFF(p, pdata);
1769 len = (len + 3) & ~3;
1774 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1775 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1777 SIVAL(p,0,reskey); p += 4;
1778 put_long_date_timespec(p,create_date_ts); p += 8;
1779 put_long_date_timespec(p,adate_ts); p += 8;
1780 put_long_date_timespec(p,mdate_ts); p += 8;
1781 put_long_date_timespec(p,mdate_ts); p += 8;
1782 SOFF_T(p,0,file_size); p += 8;
1783 SOFF_T(p,0,allocation_size); p += 8;
1784 SIVAL(p,0,nt_extmode); p += 4;
1785 q = p; p += 4; /* q is placeholder for name length. */
1787 unsigned int ea_size = estimate_ea_size(conn, NULL,
1788 smb_fname->base_name);
1789 SIVAL(p,0,ea_size); /* Extended attributes */
1792 len = srvstr_push(base_data, flags2, p,
1793 fname, PTR_DIFF(end_data, p),
1794 STR_TERMINATE_ASCII);
1798 SIVAL(p,0,0); /* Ensure any padding is null. */
1799 len = PTR_DIFF(p, pdata);
1800 len = (len + 3) & ~3;
1805 case SMB_FIND_FILE_NAMES_INFO:
1806 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1808 SIVAL(p,0,reskey); p += 4;
1810 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1811 acl on a dir (tridge) */
1812 len = srvstr_push(base_data, flags2, p,
1813 fname, PTR_DIFF(end_data, p),
1814 STR_TERMINATE_ASCII);
1817 SIVAL(p,0,0); /* Ensure any padding is null. */
1818 len = PTR_DIFF(p, pdata);
1819 len = (len + 3) & ~3;
1824 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1825 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1827 SIVAL(p,0,reskey); p += 4;
1828 put_long_date_timespec(p,create_date_ts); p += 8;
1829 put_long_date_timespec(p,adate_ts); p += 8;
1830 put_long_date_timespec(p,mdate_ts); p += 8;
1831 put_long_date_timespec(p,mdate_ts); p += 8;
1832 SOFF_T(p,0,file_size); p += 8;
1833 SOFF_T(p,0,allocation_size); p += 8;
1834 SIVAL(p,0,nt_extmode); p += 4;
1835 q = p; p += 4; /* q is placeholder for name length. */
1837 unsigned int ea_size = estimate_ea_size(conn, NULL,
1838 smb_fname->base_name);
1839 SIVAL(p,0,ea_size); /* Extended attributes */
1842 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1843 SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
1844 SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
1845 len = srvstr_push(base_data, flags2, p,
1846 fname, PTR_DIFF(end_data, p),
1847 STR_TERMINATE_ASCII);
1850 SIVAL(p,0,0); /* Ensure any padding is null. */
1851 len = PTR_DIFF(p, pdata);
1852 len = (len + 3) & ~3;
1857 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1858 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1859 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1861 SIVAL(p,0,reskey); p += 4;
1862 put_long_date_timespec(p,create_date_ts); p += 8;
1863 put_long_date_timespec(p,adate_ts); p += 8;
1864 put_long_date_timespec(p,mdate_ts); p += 8;
1865 put_long_date_timespec(p,mdate_ts); p += 8;
1866 SOFF_T(p,0,file_size); p += 8;
1867 SOFF_T(p,0,allocation_size); p += 8;
1868 SIVAL(p,0,nt_extmode); p += 4;
1869 q = p; p += 4; /* q is placeholder for name length */
1871 unsigned int ea_size = estimate_ea_size(conn, NULL,
1872 smb_fname->base_name);
1873 SIVAL(p,0,ea_size); /* Extended attributes */
1876 /* Clear the short name buffer. This is
1877 * IMPORTANT as not doing so will trigger
1878 * a Win2k client bug. JRA.
1880 if (!was_8_3 && state.check_mangled_names) {
1881 char mangled_name[13]; /* mangled 8.3 name. */
1882 if (!name_to_8_3(fname,mangled_name,True,
1884 /* Error - mangle failed ! */
1885 memset(mangled_name,'\0',12);
1887 mangled_name[12] = 0;
1888 len = srvstr_push(base_data, flags2,
1889 p+2, mangled_name, 24,
1890 STR_UPPER|STR_UNICODE);
1893 memset(p + 2 + len,'\0',24 - len);
1900 SSVAL(p,0,0); p += 2; /* Reserved ? */
1901 SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
1902 SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
1903 len = srvstr_push(base_data, flags2, p,
1904 fname, PTR_DIFF(end_data, p),
1905 STR_TERMINATE_ASCII);
1908 SIVAL(p,0,0); /* Ensure any padding is null. */
1909 len = PTR_DIFF(p, pdata);
1910 len = (len + 3) & ~3;
1915 /* CIFS UNIX Extension. */
1917 case SMB_FIND_FILE_UNIX:
1918 case SMB_FIND_FILE_UNIX_INFO2:
1920 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1922 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1924 if (info_level == SMB_FIND_FILE_UNIX) {
1925 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1926 p = store_file_unix_basic(conn, p,
1927 NULL, &smb_fname->st);
1928 len = srvstr_push(base_data, flags2, p,
1929 fname, PTR_DIFF(end_data, p),
1932 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1933 p = store_file_unix_basic_info2(conn, p,
1934 NULL, &smb_fname->st);
1937 len = srvstr_push(base_data, flags2, p, fname,
1938 PTR_DIFF(end_data, p), 0);
1939 SIVAL(nameptr, 0, len);
1943 SIVAL(p,0,0); /* Ensure any padding is null. */
1945 len = PTR_DIFF(p, pdata);
1946 len = (len + 3) & ~3;
1947 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1949 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1955 TALLOC_FREE(smb_fname);
1960 TALLOC_FREE(smb_fname);
1962 if (PTR_DIFF(p,pdata) > space_remaining) {
1963 /* Move the dirptr back to prev_dirpos */
1964 dptr_SeekDir(dirptr, prev_dirpos);
1965 *out_of_space = True;
1966 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1967 return False; /* Not finished - just out of space */
1970 /* Setup the last entry pointer, as an offset from base_data */
1971 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1972 /* Advance the data pointer to the next slot */
1978 /****************************************************************************
1979 Reply to a TRANS2_FINDFIRST.
1980 ****************************************************************************/
1982 static void call_trans2findfirst(connection_struct *conn,
1983 struct smb_request *req,
1984 char **pparams, int total_params,
1985 char **ppdata, int total_data,
1986 unsigned int max_data_bytes)
1988 /* We must be careful here that we don't return more than the
1989 allowed number of data bytes. If this means returning fewer than
1990 maxentries then so be it. We assume that the redirector has
1991 enough room for the fixed number of parameter bytes it has
1993 struct smb_filename *smb_dname = NULL;
1994 char *params = *pparams;
1995 char *pdata = *ppdata;
1999 uint16 findfirst_flags;
2000 bool close_after_first;
2002 bool requires_resume_key;
2004 char *directory = NULL;
2007 int last_entry_off=0;
2011 bool finished = False;
2012 bool dont_descend = False;
2013 bool out_of_space = False;
2014 int space_remaining;
2015 bool mask_contains_wcard = False;
2016 struct ea_list *ea_list = NULL;
2017 NTSTATUS ntstatus = NT_STATUS_OK;
2018 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2019 TALLOC_CTX *ctx = talloc_tos();
2020 struct dptr_struct *dirptr = NULL;
2021 struct smbd_server_connection *sconn = smbd_server_conn;
2023 if (total_params < 13) {
2024 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2028 dirtype = SVAL(params,0);
2029 maxentries = SVAL(params,2);
2030 findfirst_flags = SVAL(params,4);
2031 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2032 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2033 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2034 info_level = SVAL(params,6);
2036 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2037 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2038 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2039 info_level, max_data_bytes));
2042 /* W2K3 seems to treat zero as 1. */
2046 switch (info_level) {
2047 case SMB_FIND_INFO_STANDARD:
2048 case SMB_FIND_EA_SIZE:
2049 case SMB_FIND_EA_LIST:
2050 case SMB_FIND_FILE_DIRECTORY_INFO:
2051 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2052 case SMB_FIND_FILE_NAMES_INFO:
2053 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2054 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2055 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2057 case SMB_FIND_FILE_UNIX:
2058 case SMB_FIND_FILE_UNIX_INFO2:
2059 /* Always use filesystem for UNIX mtime query. */
2060 ask_sharemode = false;
2061 if (!lp_unix_extensions()) {
2062 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2067 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2071 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2072 params+12, total_params - 12,
2073 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2074 if (!NT_STATUS_IS_OK(ntstatus)) {
2075 reply_nterror(req, ntstatus);
2079 ntstatus = filename_convert(ctx, conn,
2080 req->flags2 & FLAGS2_DFS_PATHNAMES,
2083 UCF_ALWAYS_ALLOW_WCARD_LCOMP),
2084 &mask_contains_wcard,
2086 if (!NT_STATUS_IS_OK(ntstatus)) {
2087 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2088 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2089 ERRSRV, ERRbadpath);
2092 reply_nterror(req, ntstatus);
2096 mask = smb_dname->original_lcomp;
2098 directory = smb_dname->base_name;
2100 p = strrchr_m(directory,'/');
2102 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2103 if((directory[0] == '.') && (directory[1] == '\0')) {
2104 mask = talloc_strdup(ctx,"*");
2106 reply_nterror(req, NT_STATUS_NO_MEMORY);
2109 mask_contains_wcard = True;
2111 directory = talloc_strdup(talloc_tos(), "./");
2113 reply_nterror(req, NT_STATUS_NO_MEMORY);
2120 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2122 if (info_level == SMB_FIND_EA_LIST) {
2125 if (total_data < 4) {
2126 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2130 ea_size = IVAL(pdata,0);
2131 if (ea_size != total_data) {
2132 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2133 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2134 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2138 if (!lp_ea_support(SNUM(conn))) {
2139 reply_doserror(req, ERRDOS, ERReasnotsupported);
2143 /* Pull out the list of names. */
2144 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2146 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2151 *ppdata = (char *)SMB_REALLOC(
2152 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2153 if(*ppdata == NULL ) {
2154 reply_nterror(req, NT_STATUS_NO_MEMORY);
2158 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2160 /* Realloc the params space */
2161 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2162 if (*pparams == NULL) {
2163 reply_nterror(req, NT_STATUS_NO_MEMORY);
2168 /* Save the wildcard match and attribs we are using on this directory -
2169 needed as lanman2 assumes these are being saved between calls */
2171 ntstatus = dptr_create(conn,
2177 mask_contains_wcard,
2181 if (!NT_STATUS_IS_OK(ntstatus)) {
2182 reply_nterror(req, ntstatus);
2186 dptr_num = dptr_dnum(dirptr);
2187 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2189 /* Initialize per TRANS2_FIND_FIRST operation data */
2190 dptr_init_search_op(dirptr);
2192 /* We don't need to check for VOL here as this is returned by
2193 a different TRANS2 call. */
2195 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2196 directory,lp_dontdescend(SNUM(conn))));
2197 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2198 dont_descend = True;
2201 space_remaining = max_data_bytes;
2202 out_of_space = False;
2204 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2205 bool got_exact_match = False;
2207 /* this is a heuristic to avoid seeking the dirptr except when
2208 absolutely necessary. It allows for a filename of about 40 chars */
2209 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2210 out_of_space = True;
2213 finished = !get_lanman2_dir_entry(ctx,
2217 mask,dirtype,info_level,
2218 requires_resume_key,dont_descend,
2221 space_remaining, &out_of_space,
2223 &last_entry_off, ea_list);
2226 if (finished && out_of_space)
2229 if (!finished && !out_of_space)
2233 * As an optimisation if we know we aren't looking
2234 * for a wildcard name (ie. the name matches the wildcard exactly)
2235 * then we can finish on any (first) match.
2236 * This speeds up large directory searches. JRA.
2242 /* Ensure space_remaining never goes -ve. */
2243 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2244 space_remaining = 0;
2245 out_of_space = true;
2247 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2251 /* Check if we can close the dirptr */
2252 if(close_after_first || (finished && close_if_end)) {
2253 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2254 dptr_close(sconn, &dptr_num);
2258 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2259 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2260 * the protocol level is less than NT1. Tested with smbclient. JRA.
2261 * This should fix the OS/2 client bug #2335.
2264 if(numentries == 0) {
2265 dptr_close(sconn, &dptr_num);
2266 if (Protocol < PROTOCOL_NT1) {
2267 reply_doserror(req, ERRDOS, ERRnofiles);
2270 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2271 ERRDOS, ERRbadfile);
2276 /* At this point pdata points to numentries directory entries. */
2278 /* Set up the return parameter block */
2279 SSVAL(params,0,dptr_num);
2280 SSVAL(params,2,numentries);
2281 SSVAL(params,4,finished);
2282 SSVAL(params,6,0); /* Never an EA error */
2283 SSVAL(params,8,last_entry_off);
2285 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2288 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2289 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2291 reply_nterror(req, NT_STATUS_NO_MEMORY);
2295 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2296 smb_fn_name(req->cmd),
2297 mask, directory, dirtype, numentries ) );
2300 * Force a name mangle here to ensure that the
2301 * mask as an 8.3 name is top of the mangled cache.
2302 * The reasons for this are subtle. Don't remove
2303 * this code unless you know what you are doing
2304 * (see PR#13758). JRA.
2307 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2308 char mangled_name[13];
2309 name_to_8_3(mask, mangled_name, True, conn->params);
2312 TALLOC_FREE(smb_dname);
2316 /****************************************************************************
2317 Reply to a TRANS2_FINDNEXT.
2318 ****************************************************************************/
2320 static void call_trans2findnext(connection_struct *conn,
2321 struct smb_request *req,
2322 char **pparams, int total_params,
2323 char **ppdata, int total_data,
2324 unsigned int max_data_bytes)
2326 /* We must be careful here that we don't return more than the
2327 allowed number of data bytes. If this means returning fewer than
2328 maxentries then so be it. We assume that the redirector has
2329 enough room for the fixed number of parameter bytes it has
2331 char *params = *pparams;
2332 char *pdata = *ppdata;
2338 uint16 findnext_flags;
2339 bool close_after_request;
2341 bool requires_resume_key;
2343 bool mask_contains_wcard = False;
2344 char *resume_name = NULL;
2345 const char *mask = NULL;
2346 const char *directory = NULL;
2350 int i, last_entry_off=0;
2351 bool finished = False;
2352 bool dont_descend = False;
2353 bool out_of_space = False;
2354 int space_remaining;
2355 struct ea_list *ea_list = NULL;
2356 NTSTATUS ntstatus = NT_STATUS_OK;
2357 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2358 TALLOC_CTX *ctx = talloc_tos();
2359 struct dptr_struct *dirptr;
2360 struct smbd_server_connection *sconn = smbd_server_conn;
2362 if (total_params < 13) {
2363 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2367 dptr_num = SVAL(params,0);
2368 maxentries = SVAL(params,2);
2369 info_level = SVAL(params,4);
2370 resume_key = IVAL(params,6);
2371 findnext_flags = SVAL(params,10);
2372 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2373 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2374 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2375 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2377 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2379 total_params - 12, STR_TERMINATE, &ntstatus,
2380 &mask_contains_wcard);
2381 if (!NT_STATUS_IS_OK(ntstatus)) {
2382 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2383 complain (it thinks we're asking for the directory above the shared
2384 path or an invalid name). Catch this as the resume name is only compared, never used in
2385 a file access. JRA. */
2386 srvstr_pull_talloc(ctx, params, req->flags2,
2387 &resume_name, params+12,
2391 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2392 reply_nterror(req, ntstatus);
2397 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2398 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2399 resume_key = %d resume name = %s continue=%d level = %d\n",
2400 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2401 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2404 /* W2K3 seems to treat zero as 1. */
2408 switch (info_level) {
2409 case SMB_FIND_INFO_STANDARD:
2410 case SMB_FIND_EA_SIZE:
2411 case SMB_FIND_EA_LIST:
2412 case SMB_FIND_FILE_DIRECTORY_INFO:
2413 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2414 case SMB_FIND_FILE_NAMES_INFO:
2415 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2416 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2417 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2419 case SMB_FIND_FILE_UNIX:
2420 case SMB_FIND_FILE_UNIX_INFO2:
2421 /* Always use filesystem for UNIX mtime query. */
2422 ask_sharemode = false;
2423 if (!lp_unix_extensions()) {
2424 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2429 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2433 if (info_level == SMB_FIND_EA_LIST) {
2436 if (total_data < 4) {
2437 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2441 ea_size = IVAL(pdata,0);
2442 if (ea_size != total_data) {
2443 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2444 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2445 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2449 if (!lp_ea_support(SNUM(conn))) {
2450 reply_doserror(req, ERRDOS, ERReasnotsupported);
2454 /* Pull out the list of names. */
2455 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2457 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2462 *ppdata = (char *)SMB_REALLOC(
2463 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2464 if(*ppdata == NULL) {
2465 reply_nterror(req, NT_STATUS_NO_MEMORY);
2470 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2472 /* Realloc the params space */
2473 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2474 if(*pparams == NULL ) {
2475 reply_nterror(req, NT_STATUS_NO_MEMORY);
2481 /* Check that the dptr is valid */
2482 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2483 reply_doserror(req, ERRDOS, ERRnofiles);
2487 directory = dptr_path(sconn, dptr_num);
2489 /* Get the wildcard mask from the dptr */
2490 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2491 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2492 reply_doserror(req, ERRDOS, ERRnofiles);
2498 /* Get the attr mask from the dptr */
2499 dirtype = dptr_attr(sconn, dptr_num);
2501 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2502 dptr_num, mask, dirtype,
2504 dptr_TellDir(dirptr)));
2506 /* Initialize per TRANS2_FIND_NEXT operation data */
2507 dptr_init_search_op(dirptr);
2509 /* We don't need to check for VOL here as this is returned by
2510 a different TRANS2 call. */
2512 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2513 directory,lp_dontdescend(SNUM(conn))));
2514 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2515 dont_descend = True;
2518 space_remaining = max_data_bytes;
2519 out_of_space = False;
2522 * Seek to the correct position. We no longer use the resume key but
2523 * depend on the last file name instead.
2526 if(*resume_name && !continue_bit) {
2529 long current_pos = 0;
2531 * Remember, name_to_8_3 is called by
2532 * get_lanman2_dir_entry(), so the resume name
2533 * could be mangled. Ensure we check the unmangled name.
2536 if (mangle_is_mangled(resume_name, conn->params)) {
2537 char *new_resume_name = NULL;
2538 mangle_lookup_name_from_8_3(ctx,
2542 if (new_resume_name) {
2543 resume_name = new_resume_name;
2548 * Fix for NT redirector problem triggered by resume key indexes
2549 * changing between directory scans. We now return a resume key of 0
2550 * and instead look for the filename to continue from (also given
2551 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2552 * findfirst/findnext (as is usual) then the directory pointer
2553 * should already be at the correct place.
2556 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
2557 } /* end if resume_name && !continue_bit */
2559 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2560 bool got_exact_match = False;
2562 /* this is a heuristic to avoid seeking the dirptr except when
2563 absolutely necessary. It allows for a filename of about 40 chars */
2564 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2565 out_of_space = True;
2568 finished = !get_lanman2_dir_entry(ctx,
2572 mask,dirtype,info_level,
2573 requires_resume_key,dont_descend,
2576 space_remaining, &out_of_space,
2578 &last_entry_off, ea_list);
2581 if (finished && out_of_space)
2584 if (!finished && !out_of_space)
2588 * As an optimisation if we know we aren't looking
2589 * for a wildcard name (ie. the name matches the wildcard exactly)
2590 * then we can finish on any (first) match.
2591 * This speeds up large directory searches. JRA.
2597 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2600 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2601 smb_fn_name(req->cmd),
2602 mask, directory, dirtype, numentries ) );
2604 /* Check if we can close the dirptr */
2605 if(close_after_request || (finished && close_if_end)) {
2606 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2607 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2610 /* Set up the return parameter block */
2611 SSVAL(params,0,numentries);
2612 SSVAL(params,2,finished);
2613 SSVAL(params,4,0); /* Never an EA error */
2614 SSVAL(params,6,last_entry_off);
2616 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2622 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2624 E_md4hash(lp_servicename(SNUM(conn)),objid);
2628 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2630 SMB_ASSERT(extended_info != NULL);
2632 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2633 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2634 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2635 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2636 #ifdef SAMBA_VERSION_REVISION
2637 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2639 extended_info->samba_subversion = 0;
2640 #ifdef SAMBA_VERSION_RC_RELEASE
2641 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2643 #ifdef SAMBA_VERSION_PRE_RELEASE
2644 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2647 #ifdef SAMBA_VERSION_VENDOR_PATCH
2648 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2650 extended_info->samba_gitcommitdate = 0;
2651 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2652 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2655 memset(extended_info->samba_version_string, 0,
2656 sizeof(extended_info->samba_version_string));
2658 snprintf (extended_info->samba_version_string,
2659 sizeof(extended_info->samba_version_string),
2660 "%s", samba_version_string());
2663 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2664 TALLOC_CTX *mem_ctx,
2665 uint16_t info_level,
2667 unsigned int max_data_bytes,
2671 char *pdata, *end_data;
2672 int data_len = 0, len;
2673 const char *vname = volume_label(SNUM(conn));
2674 int snum = SNUM(conn);
2675 char *fstype = lp_fstype(SNUM(conn));
2676 uint32 additional_flags = 0;
2677 struct smb_filename *smb_fname_dot = NULL;
2682 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2683 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2684 "info level (0x%x) on IPC$.\n",
2685 (unsigned int)info_level));
2686 return NT_STATUS_ACCESS_DENIED;
2690 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2692 status = create_synthetic_smb_fname(talloc_tos(), ".", NULL, NULL,
2694 if (!NT_STATUS_IS_OK(status)) {
2698 if(SMB_VFS_STAT(conn, smb_fname_dot) != 0) {
2699 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2700 TALLOC_FREE(smb_fname_dot);
2701 return map_nt_error_from_unix(errno);
2704 st = smb_fname_dot->st;
2705 TALLOC_FREE(smb_fname_dot);
2707 *ppdata = (char *)SMB_REALLOC(
2708 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2709 if (*ppdata == NULL) {
2710 return NT_STATUS_NO_MEMORY;
2714 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2715 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2717 switch (info_level) {
2718 case SMB_INFO_ALLOCATION:
2720 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2722 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2723 return map_nt_error_from_unix(errno);
2726 block_size = lp_block_size(snum);
2727 if (bsize < block_size) {
2728 uint64_t factor = block_size/bsize;
2733 if (bsize > block_size) {
2734 uint64_t factor = bsize/block_size;
2739 bytes_per_sector = 512;
2740 sectors_per_unit = bsize/bytes_per_sector;
2742 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2743 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2744 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2746 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2747 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2748 SIVAL(pdata,l1_cUnit,dsize);
2749 SIVAL(pdata,l1_cUnitAvail,dfree);
2750 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2754 case SMB_INFO_VOLUME:
2755 /* Return volume name */
2757 * Add volume serial number - hash of a combination of
2758 * the called hostname and the service name.
2760 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2762 * Win2k3 and previous mess this up by sending a name length
2763 * one byte short. I believe only older clients (OS/2 Win9x) use
2764 * this call so try fixing this by adding a terminating null to
2765 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2769 pdata+l2_vol_szVolLabel, vname,
2770 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2771 STR_NOALIGN|STR_TERMINATE);
2772 SCVAL(pdata,l2_vol_cch,len);
2773 data_len = l2_vol_szVolLabel + len;
2774 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
2775 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2779 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2780 case SMB_FS_ATTRIBUTE_INFORMATION:
2782 additional_flags = 0;
2783 #if defined(HAVE_SYS_QUOTAS)
2784 additional_flags |= FILE_VOLUME_QUOTAS;
2787 if(lp_nt_acl_support(SNUM(conn))) {
2788 additional_flags |= FILE_PERSISTENT_ACLS;
2791 /* Capabilities are filled in at connection time through STATVFS call */
2792 additional_flags |= conn->fs_capabilities;
2794 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2795 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2796 additional_flags); /* FS ATTRIBUTES */
2798 SIVAL(pdata,4,255); /* Max filename component length */
2799 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2800 and will think we can't do long filenames */
2801 len = srvstr_push(pdata, flags2, pdata+12, fstype,
2802 PTR_DIFF(end_data, pdata+12),
2805 data_len = 12 + len;
2808 case SMB_QUERY_FS_LABEL_INFO:
2809 case SMB_FS_LABEL_INFORMATION:
2810 len = srvstr_push(pdata, flags2, pdata+4, vname,
2811 PTR_DIFF(end_data, pdata+4), 0);
2816 case SMB_QUERY_FS_VOLUME_INFO:
2817 case SMB_FS_VOLUME_INFORMATION:
2820 * Add volume serial number - hash of a combination of
2821 * the called hostname and the service name.
2823 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2824 (str_checksum(get_local_machine_name())<<16));
2826 /* Max label len is 32 characters. */
2827 len = srvstr_push(pdata, flags2, pdata+18, vname,
2828 PTR_DIFF(end_data, pdata+18),
2830 SIVAL(pdata,12,len);
2833 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2834 (int)strlen(vname),vname, lp_servicename(snum)));
2837 case SMB_QUERY_FS_SIZE_INFO:
2838 case SMB_FS_SIZE_INFORMATION:
2840 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2842 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2843 return map_nt_error_from_unix(errno);
2845 block_size = lp_block_size(snum);
2846 if (bsize < block_size) {
2847 uint64_t factor = block_size/bsize;
2852 if (bsize > block_size) {
2853 uint64_t factor = bsize/block_size;
2858 bytes_per_sector = 512;
2859 sectors_per_unit = bsize/bytes_per_sector;
2860 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2861 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2862 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2863 SBIG_UINT(pdata,0,dsize);
2864 SBIG_UINT(pdata,8,dfree);
2865 SIVAL(pdata,16,sectors_per_unit);
2866 SIVAL(pdata,20,bytes_per_sector);
2870 case SMB_FS_FULL_SIZE_INFORMATION:
2872 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2874 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2875 return map_nt_error_from_unix(errno);
2877 block_size = lp_block_size(snum);
2878 if (bsize < block_size) {
2879 uint64_t factor = block_size/bsize;
2884 if (bsize > block_size) {
2885 uint64_t factor = bsize/block_size;
2890 bytes_per_sector = 512;
2891 sectors_per_unit = bsize/bytes_per_sector;
2892 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2893 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2894 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2895 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2896 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2897 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2898 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2899 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2903 case SMB_QUERY_FS_DEVICE_INFO:
2904 case SMB_FS_DEVICE_INFORMATION:
2906 SIVAL(pdata,0,0); /* dev type */
2907 SIVAL(pdata,4,0); /* characteristics */
2910 #ifdef HAVE_SYS_QUOTAS
2911 case SMB_FS_QUOTA_INFORMATION:
2913 * what we have to send --metze:
2915 * Unknown1: 24 NULL bytes
2916 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2917 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2918 * Quota Flags: 2 byte :
2919 * Unknown3: 6 NULL bytes
2923 * details for Quota Flags:
2925 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2926 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2927 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2928 * 0x0001 Enable Quotas: enable quota for this fs
2932 /* we need to fake up a fsp here,
2933 * because its not send in this call
2936 SMB_NTQUOTA_STRUCT quotas;
2939 ZERO_STRUCT(quotas);
2945 if (conn->server_info->utok.uid != sec_initial_uid()) {
2946 DEBUG(0,("set_user_quota: access_denied "
2947 "service [%s] user [%s]\n",
2948 lp_servicename(SNUM(conn)),
2949 conn->server_info->unix_name));
2950 return NT_STATUS_ACCESS_DENIED;
2953 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2954 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2955 return map_nt_error_from_unix(errno);
2960 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
2961 lp_servicename(SNUM(conn))));
2963 /* Unknown1 24 NULL bytes*/
2964 SBIG_UINT(pdata,0,(uint64_t)0);
2965 SBIG_UINT(pdata,8,(uint64_t)0);
2966 SBIG_UINT(pdata,16,(uint64_t)0);
2968 /* Default Soft Quota 8 bytes */
2969 SBIG_UINT(pdata,24,quotas.softlim);
2971 /* Default Hard Quota 8 bytes */
2972 SBIG_UINT(pdata,32,quotas.hardlim);
2974 /* Quota flag 2 bytes */
2975 SSVAL(pdata,40,quotas.qflags);
2977 /* Unknown3 6 NULL bytes */
2983 #endif /* HAVE_SYS_QUOTAS */
2984 case SMB_FS_OBJECTID_INFORMATION:
2986 unsigned char objid[16];
2987 struct smb_extended_info extended_info;
2988 memcpy(pdata,create_volume_objectid(conn, objid),16);
2989 samba_extended_info_version (&extended_info);
2990 SIVAL(pdata,16,extended_info.samba_magic);
2991 SIVAL(pdata,20,extended_info.samba_version);
2992 SIVAL(pdata,24,extended_info.samba_subversion);
2993 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2994 memcpy(pdata+36,extended_info.samba_version_string,28);
3000 * Query the version and capabilities of the CIFS UNIX extensions
3004 case SMB_QUERY_CIFS_UNIX_INFO:
3006 bool large_write = lp_min_receive_file_size() &&
3007 !srv_is_signing_active(smbd_server_conn);
3008 bool large_read = !srv_is_signing_active(smbd_server_conn);
3009 int encrypt_caps = 0;
3011 if (!lp_unix_extensions()) {
3012 return NT_STATUS_INVALID_LEVEL;
3015 switch (conn->encrypt_level) {
3021 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3024 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3025 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3026 large_write = false;
3032 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3033 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3035 /* We have POSIX ACLs, pathname, encryption,
3036 * large read/write, and locking capability. */
3038 SBIG_UINT(pdata,4,((uint64_t)(
3039 CIFS_UNIX_POSIX_ACLS_CAP|
3040 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3041 CIFS_UNIX_FCNTL_LOCKS_CAP|
3042 CIFS_UNIX_EXTATTR_CAP|
3043 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3045 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3047 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3051 case SMB_QUERY_POSIX_FS_INFO:
3054 vfs_statvfs_struct svfs;
3056 if (!lp_unix_extensions()) {
3057 return NT_STATUS_INVALID_LEVEL;
3060 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3064 SIVAL(pdata,0,svfs.OptimalTransferSize);
3065 SIVAL(pdata,4,svfs.BlockSize);
3066 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3067 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3068 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3069 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3070 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3071 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3072 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3074 } else if (rc == EOPNOTSUPP) {
3075 return NT_STATUS_INVALID_LEVEL;
3076 #endif /* EOPNOTSUPP */
3078 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3079 return NT_STATUS_DOS(ERRSRV, ERRerror);
3084 case SMB_QUERY_POSIX_WHOAMI:
3090 if (!lp_unix_extensions()) {
3091 return NT_STATUS_INVALID_LEVEL;
3094 if (max_data_bytes < 40) {
3095 return NT_STATUS_BUFFER_TOO_SMALL;
3098 /* We ARE guest if global_sid_Builtin_Guests is
3099 * in our list of SIDs.
3101 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3102 conn->server_info->ptok)) {
3103 flags |= SMB_WHOAMI_GUEST;
3106 /* We are NOT guest if global_sid_Authenticated_Users
3107 * is in our list of SIDs.
3109 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3110 conn->server_info->ptok)) {
3111 flags &= ~SMB_WHOAMI_GUEST;
3114 /* NOTE: 8 bytes for UID/GID, irrespective of native
3115 * platform size. This matches
3116 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3118 data_len = 4 /* flags */
3125 + 4 /* pad/reserved */
3126 + (conn->server_info->utok.ngroups * 8)
3128 + (conn->server_info->ptok->num_sids *
3132 SIVAL(pdata, 0, flags);
3133 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3135 (uint64_t)conn->server_info->utok.uid);
3136 SBIG_UINT(pdata, 16,
3137 (uint64_t)conn->server_info->utok.gid);
3140 if (data_len >= max_data_bytes) {
3141 /* Potential overflow, skip the GIDs and SIDs. */
3143 SIVAL(pdata, 24, 0); /* num_groups */
3144 SIVAL(pdata, 28, 0); /* num_sids */
3145 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3146 SIVAL(pdata, 36, 0); /* reserved */
3152 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3153 SIVAL(pdata, 28, conn->server_info->num_sids);
3155 /* We walk the SID list twice, but this call is fairly
3156 * infrequent, and I don't expect that it's performance
3157 * sensitive -- jpeach
3159 for (i = 0, sid_bytes = 0;
3160 i < conn->server_info->ptok->num_sids; ++i) {
3161 sid_bytes += ndr_size_dom_sid(
3162 &conn->server_info->ptok->user_sids[i],
3167 /* SID list byte count */
3168 SIVAL(pdata, 32, sid_bytes);
3170 /* 4 bytes pad/reserved - must be zero */
3171 SIVAL(pdata, 36, 0);
3175 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3176 SBIG_UINT(pdata, data_len,
3177 (uint64_t)conn->server_info->utok.groups[i]);
3183 i < conn->server_info->ptok->num_sids; ++i) {
3184 int sid_len = ndr_size_dom_sid(
3185 &conn->server_info->ptok->user_sids[i],
3189 sid_linearize(pdata + data_len, sid_len,
3190 &conn->server_info->ptok->user_sids[i]);
3191 data_len += sid_len;
3197 case SMB_MAC_QUERY_FS_INFO:
3199 * Thursby MAC extension... ONLY on NTFS filesystems
3200 * once we do streams then we don't need this
3202 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3204 SIVAL(pdata,84,0x100); /* Don't support mac... */
3209 return NT_STATUS_INVALID_LEVEL;
3212 *ret_data_len = data_len;
3213 return NT_STATUS_OK;
3216 /****************************************************************************
3217 Reply to a TRANS2_QFSINFO (query filesystem info).
3218 ****************************************************************************/
3220 static void call_trans2qfsinfo(connection_struct *conn,
3221 struct smb_request *req,
3222 char **pparams, int total_params,
3223 char **ppdata, int total_data,
3224 unsigned int max_data_bytes)
3226 char *params = *pparams;
3227 uint16_t info_level;
3231 if (total_params < 2) {
3232 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3236 info_level = SVAL(params,0);
3238 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3239 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3240 DEBUG(0,("call_trans2qfsinfo: encryption required "
3241 "and info level 0x%x sent.\n",
3242 (unsigned int)info_level));
3243 exit_server_cleanly("encryption required "
3249 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3251 status = smbd_do_qfsinfo(conn, req,
3256 if (!NT_STATUS_IS_OK(status)) {
3257 reply_nterror(req, status);
3261 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3264 DEBUG( 4, ( "%s info_level = %d\n",
3265 smb_fn_name(req->cmd), info_level) );
3270 /****************************************************************************
3271 Reply to a TRANS2_SETFSINFO (set filesystem info).
3272 ****************************************************************************/
3274 static void call_trans2setfsinfo(connection_struct *conn,
3275 struct smb_request *req,
3276 char **pparams, int total_params,
3277 char **ppdata, int total_data,
3278 unsigned int max_data_bytes)
3280 char *pdata = *ppdata;
3281 char *params = *pparams;
3284 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3287 if (total_params < 4) {
3288 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3290 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3294 info_level = SVAL(params,2);
3297 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3298 info_level != SMB_SET_CIFS_UNIX_INFO) {
3299 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3300 "info level (0x%x) on IPC$.\n",
3301 (unsigned int)info_level));
3302 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3307 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3308 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3309 DEBUG(0,("call_trans2setfsinfo: encryption required "
3310 "and info level 0x%x sent.\n",
3311 (unsigned int)info_level));
3312 exit_server_cleanly("encryption required "
3318 switch(info_level) {
3319 case SMB_SET_CIFS_UNIX_INFO:
3321 uint16 client_unix_major;
3322 uint16 client_unix_minor;
3323 uint32 client_unix_cap_low;
3324 uint32 client_unix_cap_high;
3326 if (!lp_unix_extensions()) {
3328 NT_STATUS_INVALID_LEVEL);
3332 /* There should be 12 bytes of capabilities set. */
3333 if (total_data < 8) {
3336 NT_STATUS_INVALID_PARAMETER);
3339 client_unix_major = SVAL(pdata,0);
3340 client_unix_minor = SVAL(pdata,2);
3341 client_unix_cap_low = IVAL(pdata,4);
3342 client_unix_cap_high = IVAL(pdata,8);
3343 /* Just print these values for now. */
3344 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3345 cap_low = 0x%x, cap_high = 0x%x\n",
3346 (unsigned int)client_unix_major,
3347 (unsigned int)client_unix_minor,
3348 (unsigned int)client_unix_cap_low,
3349 (unsigned int)client_unix_cap_high ));
3351 /* Here is where we must switch to posix pathname processing... */
3352 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3353 lp_set_posix_pathnames();
3354 mangle_change_to_posix();
3357 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3358 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3359 /* Client that knows how to do posix locks,
3360 * but not posix open/mkdir operations. Set a
3361 * default type for read/write checks. */
3363 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3369 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3372 size_t param_len = 0;
3373 size_t data_len = total_data;
3375 if (!lp_unix_extensions()) {
3378 NT_STATUS_INVALID_LEVEL);
3382 if (lp_smb_encrypt(SNUM(conn)) == false) {
3385 NT_STATUS_NOT_SUPPORTED);
3389 DEBUG( 4,("call_trans2setfsinfo: "
3390 "request transport encryption.\n"));
3392 status = srv_request_encryption_setup(conn,
3393 (unsigned char **)ppdata,
3395 (unsigned char **)pparams,
3398 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3399 !NT_STATUS_IS_OK(status)) {
3400 reply_nterror(req, status);
3404 send_trans2_replies(conn, req,
3411 if (NT_STATUS_IS_OK(status)) {
3412 /* Server-side transport
3413 * encryption is now *on*. */
3414 status = srv_encryption_start(conn);
3415 if (!NT_STATUS_IS_OK(status)) {
3416 exit_server_cleanly(
3417 "Failure in setting "
3418 "up encrypted transport");
3424 case SMB_FS_QUOTA_INFORMATION:
3426 files_struct *fsp = NULL;
3427 SMB_NTQUOTA_STRUCT quotas;
3429 ZERO_STRUCT(quotas);
3432 if ((conn->server_info->utok.uid != sec_initial_uid())
3433 ||!CAN_WRITE(conn)) {
3434 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3435 lp_servicename(SNUM(conn)),
3436 conn->server_info->unix_name));
3437 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3441 /* note: normaly there're 48 bytes,
3442 * but we didn't use the last 6 bytes for now
3445 fsp = file_fsp(req, SVAL(params,0));
3447 if (!check_fsp_ntquota_handle(conn, req,
3449 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3451 req, NT_STATUS_INVALID_HANDLE);
3455 if (total_data < 42) {
3456 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3460 NT_STATUS_INVALID_PARAMETER);
3464 /* unknown_1 24 NULL bytes in pdata*/
3466 /* the soft quotas 8 bytes (uint64_t)*/
3467 quotas.softlim = (uint64_t)IVAL(pdata,24);
3468 #ifdef LARGE_SMB_OFF_T
3469 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3470 #else /* LARGE_SMB_OFF_T */
3471 if ((IVAL(pdata,28) != 0)&&
3472 ((quotas.softlim != 0xFFFFFFFF)||
3473 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3474 /* more than 32 bits? */
3477 NT_STATUS_INVALID_PARAMETER);
3480 #endif /* LARGE_SMB_OFF_T */
3482 /* the hard quotas 8 bytes (uint64_t)*/
3483 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3484 #ifdef LARGE_SMB_OFF_T
3485 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3486 #else /* LARGE_SMB_OFF_T */
3487 if ((IVAL(pdata,36) != 0)&&
3488 ((quotas.hardlim != 0xFFFFFFFF)||
3489 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3490 /* more than 32 bits? */
3493 NT_STATUS_INVALID_PARAMETER);
3496 #endif /* LARGE_SMB_OFF_T */
3498 /* quota_flags 2 bytes **/
3499 quotas.qflags = SVAL(pdata,40);
3501 /* unknown_2 6 NULL bytes follow*/
3503 /* now set the quotas */
3504 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3505 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3506 reply_nterror(req, map_nt_error_from_unix(errno));
3513 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3515 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3521 * sending this reply works fine,
3522 * but I'm not sure it's the same
3523 * like windows do...
3526 reply_outbuf(req, 10, 0);
3529 #if defined(HAVE_POSIX_ACLS)
3530 /****************************************************************************
3531 Utility function to count the number of entries in a POSIX acl.
3532 ****************************************************************************/
3534 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3536 unsigned int ace_count = 0;
3537 int entry_id = SMB_ACL_FIRST_ENTRY;
3538 SMB_ACL_ENTRY_T entry;
3540 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3542 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3543 entry_id = SMB_ACL_NEXT_ENTRY;
3550 /****************************************************************************
3551 Utility function to marshall a POSIX acl into wire format.
3552 ****************************************************************************/
3554 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3556 int entry_id = SMB_ACL_FIRST_ENTRY;
3557 SMB_ACL_ENTRY_T entry;
3559 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3560 SMB_ACL_TAG_T tagtype;
3561 SMB_ACL_PERMSET_T permset;
3562 unsigned char perms = 0;
3563 unsigned int own_grp;
3566 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3567 entry_id = SMB_ACL_NEXT_ENTRY;
3570 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3571 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3575 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3576 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3580 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3581 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3582 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3584 SCVAL(pdata,1,perms);
3587 case SMB_ACL_USER_OBJ:
3588 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3589 own_grp = (unsigned int)pst->st_ex_uid;
3590 SIVAL(pdata,2,own_grp);
3595 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3597 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3600 own_grp = (unsigned int)*puid;
3601 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3602 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3603 SIVAL(pdata,2,own_grp);
3607 case SMB_ACL_GROUP_OBJ:
3608 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3609 own_grp = (unsigned int)pst->st_ex_gid;
3610 SIVAL(pdata,2,own_grp);
3615 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3617 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3620 own_grp = (unsigned int)*pgid;
3621 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3622 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3623 SIVAL(pdata,2,own_grp);
3628 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3629 SIVAL(pdata,2,0xFFFFFFFF);
3630 SIVAL(pdata,6,0xFFFFFFFF);
3633 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3634 SIVAL(pdata,2,0xFFFFFFFF);
3635 SIVAL(pdata,6,0xFFFFFFFF);
3638 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3641 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3648 /****************************************************************************
3649 Store the FILE_UNIX_BASIC info.
3650 ****************************************************************************/
3652 static char *store_file_unix_basic(connection_struct *conn,
3655 const SMB_STRUCT_STAT *psbuf)
3657 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3658 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3660 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3663 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3666 put_long_date_timespec(pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3667 put_long_date_timespec(pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3668 put_long_date_timespec(pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3671 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3675 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3679 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3682 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3686 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3690 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */
3693 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3697 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3704 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3705 * the chflags(2) (or equivalent) flags.
3707 * XXX: this really should be behind the VFS interface. To do this, we would
3708 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3709 * Each VFS module could then implement its own mapping as appropriate for the
3710 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3712 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3716 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3720 { UF_IMMUTABLE, EXT_IMMUTABLE },
3724 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3728 { UF_HIDDEN, EXT_HIDDEN },
3731 /* Do not remove. We need to guarantee that this array has at least one
3732 * entry to build on HP-UX.
3738 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3739 uint32 *smb_fflags, uint32 *smb_fmask)
3743 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3744 *smb_fmask |= info2_flags_map[i].smb_fflag;
3745 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3746 *smb_fflags |= info2_flags_map[i].smb_fflag;
3751 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3752 const uint32 smb_fflags,
3753 const uint32 smb_fmask,
3756 uint32 max_fmask = 0;
3759 *stat_fflags = psbuf->st_ex_flags;
3761 /* For each flags requested in smb_fmask, check the state of the
3762 * corresponding flag in smb_fflags and set or clear the matching
3766 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3767 max_fmask |= info2_flags_map[i].smb_fflag;
3768 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3769 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3770 *stat_fflags |= info2_flags_map[i].stat_fflag;
3772 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3777 /* If smb_fmask is asking to set any bits that are not supported by
3778 * our flag mappings, we should fail.
3780 if ((smb_fmask & max_fmask) != smb_fmask) {
3788 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3789 * of file flags and birth (create) time.
3791 static char *store_file_unix_basic_info2(connection_struct *conn,
3794 const SMB_STRUCT_STAT *psbuf)
3796 uint32 file_flags = 0;
3797 uint32 flags_mask = 0;
3799 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3801 /* Create (birth) time 64 bit */
3802 put_long_date_timespec(pdata, psbuf->st_ex_btime);
3805 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3806 SIVAL(pdata, 0, file_flags); /* flags */
3807 SIVAL(pdata, 4, flags_mask); /* mask */
3813 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3814 const struct stream_struct *streams,
3816 unsigned int max_data_bytes,
3817 unsigned int *data_size)
3820 unsigned int ofs = 0;
3822 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3823 unsigned int next_offset;
3825 smb_ucs2_t *namebuf;
3827 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3828 streams[i].name, &namelen) ||
3831 return NT_STATUS_INVALID_PARAMETER;
3835 * name_buf is now null-terminated, we need to marshall as not
3841 SIVAL(data, ofs+4, namelen);
3842 SOFF_T(data, ofs+8, streams[i].size);
3843 SOFF_T(data, ofs+16, streams[i].alloc_size);
3844 memcpy(data+ofs+24, namebuf, namelen);
3845 TALLOC_FREE(namebuf);
3847 next_offset = ofs + 24 + namelen;
3849 if (i == num_streams-1) {
3850 SIVAL(data, ofs, 0);
3853 unsigned int align = ndr_align_size(next_offset, 8);
3855 memset(data+next_offset, 0, align);
3856 next_offset += align;
3858 SIVAL(data, ofs, next_offset - ofs);
3867 return NT_STATUS_OK;
3870 /****************************************************************************
3871 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3872 ****************************************************************************/
3874 static void call_trans2qpipeinfo(connection_struct *conn,
3875 struct smb_request *req,
3876 unsigned int tran_call,
3877 char **pparams, int total_params,
3878 char **ppdata, int total_data,
3879 unsigned int max_data_bytes)
3881 char *params = *pparams;
3882 char *pdata = *ppdata;
3883 unsigned int data_size = 0;
3884 unsigned int param_size = 2;
3889 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3893 if (total_params < 4) {
3894 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3898 fsp = file_fsp(req, SVAL(params,0));
3899 if (!fsp_is_np(fsp)) {
3900 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3904 info_level = SVAL(params,2);
3906 *pparams = (char *)SMB_REALLOC(*pparams,2);
3907 if (*pparams == NULL) {
3908 reply_nterror(req, NT_STATUS_NO_MEMORY);
3913 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3914 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3915 if (*ppdata == NULL ) {
3916 reply_nterror(req, NT_STATUS_NO_MEMORY);
3921 switch (info_level) {
3922 case SMB_FILE_STANDARD_INFORMATION:
3924 SOFF_T(pdata,0,4096LL);
3931 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3935 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3941 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
3942 TALLOC_CTX *mem_ctx,
3943 uint16_t info_level,
3945 const struct smb_filename *smb_fname,
3946 bool delete_pending,
3947 struct timespec write_time_ts,
3949 struct ea_list *ea_list,
3950 int lock_data_count,
3953 unsigned int max_data_bytes,
3955 unsigned int *pdata_size)
3957 char *pdata = *ppdata;
3958 char *dstart, *dend;
3959 unsigned int data_size;
3960 struct timespec create_time_ts, mtime_ts, atime_ts;
3961 time_t create_time, mtime, atime;
3962 SMB_STRUCT_STAT sbuf;
3969 uint64_t file_size = 0;
3971 uint64_t allocation_size = 0;
3972 uint64_t file_index = 0;
3973 uint32_t access_mask = 0;
3975 sbuf = smb_fname->st;
3977 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3978 return NT_STATUS_INVALID_LEVEL;
3981 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
3982 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
3983 info_level, max_data_bytes));
3986 mode = dos_mode_msdfs(conn, smb_fname);
3988 mode = dos_mode(conn, smb_fname);
3991 mode = FILE_ATTRIBUTE_NORMAL;
3993 nlink = sbuf.st_ex_nlink;
3995 if (nlink && (mode&aDIR)) {
3999 if ((nlink > 0) && delete_pending) {
4003 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4004 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4005 if (*ppdata == NULL) {
4006 return NT_STATUS_NO_MEMORY;
4010 dend = dstart + data_size - 1;
4012 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4013 update_stat_ex_mtime(&sbuf, write_time_ts);
4016 create_time_ts = sbuf.st_ex_btime;
4017 mtime_ts = sbuf.st_ex_mtime;
4018 atime_ts = sbuf.st_ex_atime;
4020 if (lp_dos_filetime_resolution(SNUM(conn))) {
4021 dos_filetime_timespec(&create_time_ts);
4022 dos_filetime_timespec(&mtime_ts);
4023 dos_filetime_timespec(&atime_ts);
4026 create_time = convert_timespec_to_time_t(create_time_ts);
4027 mtime = convert_timespec_to_time_t(mtime_ts);
4028 atime = convert_timespec_to_time_t(atime_ts);
4030 p = strrchr_m(smb_fname->base_name,'/');
4032 base_name = smb_fname->base_name;
4036 /* NT expects the name to be in an exact form of the *full*
4037 filename. See the trans2 torture test */
4038 if (ISDOT(base_name)) {
4039 dos_fname = talloc_strdup(mem_ctx, "\\");
4041 return NT_STATUS_NO_MEMORY;
4044 dos_fname = talloc_asprintf(mem_ctx,
4046 smb_fname->base_name);
4048 return NT_STATUS_NO_MEMORY;
4050 if (is_ntfs_stream_smb_fname(smb_fname)) {
4051 dos_fname = talloc_asprintf(dos_fname, "%s",
4052 smb_fname->stream_name);
4054 return NT_STATUS_NO_MEMORY;
4058 string_replace(dos_fname, '/', '\\');
4061 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &sbuf);
4064 /* Do we have this path open ? */
4066 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4067 fsp1 = file_find_di_first(fileid);
4068 if (fsp1 && fsp1->initial_allocation_size) {
4069 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
4073 if (!(mode & aDIR)) {
4074 file_size = get_file_size_stat(&sbuf);
4078 pos = fsp->fh->position_information;
4082 access_mask = fsp->access_mask;
4084 /* GENERIC_EXECUTE mapping from Windows */
4085 access_mask = 0x12019F;
4088 /* This should be an index number - looks like
4091 I think this causes us to fail the IFSKIT
4092 BasicFileInformationTest. -tpot */
4093 file_index = ((sbuf.st_ex_ino) & UINT32_MAX); /* FileIndexLow */
4094 file_index |= ((uint64_t)((sbuf.st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
4096 switch (info_level) {
4097 case SMB_INFO_STANDARD:
4098 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4100 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4101 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4102 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4103 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4104 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4105 SSVAL(pdata,l1_attrFile,mode);
4108 case SMB_INFO_QUERY_EA_SIZE:
4110 unsigned int ea_size =
4111 estimate_ea_size(conn, fsp,
4112 smb_fname->base_name);
4113 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4115 srv_put_dos_date2(pdata,0,create_time);
4116 srv_put_dos_date2(pdata,4,atime);
4117 srv_put_dos_date2(pdata,8,mtime); /* write time */
4118 SIVAL(pdata,12,(uint32)file_size);
4119 SIVAL(pdata,16,(uint32)allocation_size);
4120 SSVAL(pdata,20,mode);
4121 SIVAL(pdata,22,ea_size);
4125 case SMB_INFO_IS_NAME_VALID:
4126 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4128 /* os/2 needs this ? really ?*/
4129 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4131 /* This is only reached for qpathinfo */
4135 case SMB_INFO_QUERY_EAS_FROM_LIST:
4137 size_t total_ea_len = 0;
4138 struct ea_list *ea_file_list = NULL;
4140 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4143 get_ea_list_from_file(mem_ctx, conn, fsp,
4144 smb_fname->base_name,
4146 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4148 if (!ea_list || (total_ea_len > data_size)) {
4150 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4154 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4158 case SMB_INFO_QUERY_ALL_EAS:
4160 /* We have data_size bytes to put EA's into. */
4161 size_t total_ea_len = 0;
4163 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4165 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4166 smb_fname->base_name,
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 */
4189 get_ea_list_from_file(mem_ctx, conn, fsp,
4190 smb_fname->base_name,
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 =
4249 estimate_ea_size(conn, fsp, smb_fname->base_name);
4250 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4252 SIVAL(pdata,0,ea_size);
4256 /* Get the 8.3 name - used if NT SMB was negotiated. */
4257 case SMB_QUERY_FILE_ALT_NAME_INFO:
4258 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4261 char mangled_name[13];
4262 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4263 if (!name_to_8_3(base_name,mangled_name,
4264 True,conn->params)) {
4265 return NT_STATUS_NO_MEMORY;
4267 len = srvstr_push(dstart, flags2,
4268 pdata+4, mangled_name,
4269 PTR_DIFF(dend, pdata+4),
4271 data_size = 4 + len;
4276 case SMB_QUERY_FILE_NAME_INFO:
4280 this must be *exactly* right for ACLs on mapped drives to work
4282 len = srvstr_push(dstart, flags2,
4284 PTR_DIFF(dend, pdata+4),
4286 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4287 data_size = 4 + len;
4292 case SMB_FILE_ALLOCATION_INFORMATION:
4293 case SMB_QUERY_FILE_ALLOCATION_INFO:
4294 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4296 SOFF_T(pdata,0,allocation_size);
4299 case SMB_FILE_END_OF_FILE_INFORMATION:
4300 case SMB_QUERY_FILE_END_OF_FILEINFO:
4301 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4303 SOFF_T(pdata,0,file_size);
4306 case SMB_QUERY_FILE_ALL_INFO:
4307 case SMB_FILE_ALL_INFORMATION:
4310 unsigned int ea_size =
4311 estimate_ea_size(conn, fsp, smb_fname->base_name);
4312 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4313 put_long_date_timespec(pdata,create_time_ts);
4314 put_long_date_timespec(pdata+8,atime_ts);
4315 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4316 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4317 SIVAL(pdata,32,mode);
4318 SIVAL(pdata,36,0); /* padding. */
4320 SOFF_T(pdata,0,allocation_size);
4321 SOFF_T(pdata,8,file_size);
4322 SIVAL(pdata,16,nlink);
4323 SCVAL(pdata,20,delete_pending);
4324 SCVAL(pdata,21,(mode&aDIR)?1:0);
4327 SIVAL(pdata,0,ea_size);
4328 pdata += 4; /* EA info */
4329 len = srvstr_push(dstart, flags2,
4331 PTR_DIFF(dend, pdata+4),
4335 data_size = PTR_DIFF(pdata,(*ppdata));
4339 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4342 unsigned int ea_size =
4343 estimate_ea_size(conn, fsp, smb_fname->base_name);
4344 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4345 put_long_date_timespec(pdata+0x00,create_time_ts);
4346 put_long_date_timespec(pdata+0x08,atime_ts);
4347 put_long_date_timespec(pdata+0x10,mtime_ts); /* write time */
4348 put_long_date_timespec(pdata+0x18,mtime_ts); /* change time */
4349 SIVAL(pdata, 0x20, mode);
4350 SIVAL(pdata, 0x24, 0); /* padding. */
4351 SBVAL(pdata, 0x28, allocation_size);
4352 SBVAL(pdata, 0x30, file_size);
4353 SIVAL(pdata, 0x38, nlink);
4354 SCVAL(pdata, 0x3C, delete_pending);
4355 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4356 SSVAL(pdata, 0x3E, 0); /* padding */
4357 SBVAL(pdata, 0x40, file_index);
4358 SIVAL(pdata, 0x48, ea_size);
4359 SIVAL(pdata, 0x4C, access_mask);
4360 SBVAL(pdata, 0x50, pos);
4361 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4362 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4366 len = srvstr_push(dstart, flags2,
4368 PTR_DIFF(dend, pdata+4),
4372 data_size = PTR_DIFF(pdata,(*ppdata));
4375 case SMB_FILE_INTERNAL_INFORMATION:
4377 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4378 SBVAL(pdata, 0, file_index);
4382 case SMB_FILE_ACCESS_INFORMATION:
4383 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4384 SIVAL(pdata, 0, access_mask);
4388 case SMB_FILE_NAME_INFORMATION:
4389 /* Pathname with leading '\'. */
4392 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4393 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4394 SIVAL(pdata,0,byte_len);
4395 data_size = 4 + byte_len;
4399 case SMB_FILE_DISPOSITION_INFORMATION:
4400 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4402 SCVAL(pdata,0,delete_pending);
4405 case SMB_FILE_POSITION_INFORMATION:
4406 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4408 SOFF_T(pdata,0,pos);
4411 case SMB_FILE_MODE_INFORMATION:
4412 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4413 SIVAL(pdata,0,mode);
4417 case SMB_FILE_ALIGNMENT_INFORMATION:
4418 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4419 SIVAL(pdata,0,0); /* No alignment needed. */
4424 * NT4 server just returns "invalid query" to this - if we try
4425 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4428 /* The first statement above is false - verified using Thursby
4429 * client against NT4 -- gcolley.
4431 case SMB_QUERY_FILE_STREAM_INFO:
4432 case SMB_FILE_STREAM_INFORMATION: {
4433 unsigned int num_streams;
4434 struct stream_struct *streams;
4436 DEBUG(10,("smbd_do_qfilepathinfo: "
4437 "SMB_FILE_STREAM_INFORMATION\n"));
4439 if (is_ntfs_stream_smb_fname(smb_fname)) {
4440 return NT_STATUS_INVALID_PARAMETER;
4443 status = SMB_VFS_STREAMINFO(
4444 conn, fsp, smb_fname->base_name, talloc_tos(),
4445 &num_streams, &streams);
4447 if (!NT_STATUS_IS_OK(status)) {
4448 DEBUG(10, ("could not get stream info: %s\n",
4449 nt_errstr(status)));
4453 status = marshall_stream_info(num_streams, streams,
4454 pdata, max_data_bytes,
4457 if (!NT_STATUS_IS_OK(status)) {
4458 DEBUG(10, ("marshall_stream_info failed: %s\n",
4459 nt_errstr(status)));
4463 TALLOC_FREE(streams);
4467 case SMB_QUERY_COMPRESSION_INFO:
4468 case SMB_FILE_COMPRESSION_INFORMATION:
4469 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4470 SOFF_T(pdata,0,file_size);
4471 SIVAL(pdata,8,0); /* ??? */
4472 SIVAL(pdata,12,0); /* ??? */
4476 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4477 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4478 put_long_date_timespec(pdata,create_time_ts);
4479 put_long_date_timespec(pdata+8,atime_ts);
4480 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4481 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4482 SOFF_T(pdata,32,allocation_size);
4483 SOFF_T(pdata,40,file_size);
4484 SIVAL(pdata,48,mode);
4485 SIVAL(pdata,52,0); /* ??? */
4489 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4490 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4491 SIVAL(pdata,0,mode);
4497 * CIFS UNIX Extensions.
4500 case SMB_QUERY_FILE_UNIX_BASIC:
4502 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4503 data_size = PTR_DIFF(pdata,(*ppdata));
4507 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4509 for (i=0; i<100; i++)
4510 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4516 case SMB_QUERY_FILE_UNIX_INFO2:
4518 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4519 data_size = PTR_DIFF(pdata,(*ppdata));
4523 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4525 for (i=0; i<100; i++)
4526 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4532 case SMB_QUERY_FILE_UNIX_LINK:
4535 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4538 return NT_STATUS_NO_MEMORY;
4541 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4543 if(!S_ISLNK(sbuf.st_ex_mode)) {
4544 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4547 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4549 len = SMB_VFS_READLINK(conn,
4550 smb_fname->base_name,
4553 return map_nt_error_from_unix(errno);
4556 len = srvstr_push(dstart, flags2,
4558 PTR_DIFF(dend, pdata),
4561 data_size = PTR_DIFF(pdata,(*ppdata));
4566 #if defined(HAVE_POSIX_ACLS)
4567 case SMB_QUERY_POSIX_ACL:
4569 SMB_ACL_T file_acl = NULL;
4570 SMB_ACL_T def_acl = NULL;
4571 uint16 num_file_acls = 0;
4572 uint16 num_def_acls = 0;
4574 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4575 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4578 SMB_VFS_SYS_ACL_GET_FILE(conn,
4579 smb_fname->base_name,
4580 SMB_ACL_TYPE_ACCESS);
4583 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4584 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4585 "not implemented on "
4586 "filesystem containing %s\n",
4587 smb_fname->base_name));
4588 return NT_STATUS_NOT_IMPLEMENTED;
4591 if (S_ISDIR(sbuf.st_ex_mode)) {
4592 if (fsp && fsp->is_directory) {
4594 SMB_VFS_SYS_ACL_GET_FILE(
4596 fsp->fsp_name->base_name,
4597 SMB_ACL_TYPE_DEFAULT);
4600 SMB_VFS_SYS_ACL_GET_FILE(
4602 smb_fname->base_name,
4603 SMB_ACL_TYPE_DEFAULT);
4605 def_acl = free_empty_sys_acl(conn, def_acl);
4608 num_file_acls = count_acl_entries(conn, file_acl);
4609 num_def_acls = count_acl_entries(conn, def_acl);
4611 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4612 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4614 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4615 SMB_POSIX_ACL_HEADER_SIZE) ));
4617 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4620 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4622 return NT_STATUS_BUFFER_TOO_SMALL;
4625 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4626 SSVAL(pdata,2,num_file_acls);
4627 SSVAL(pdata,4,num_def_acls);
4628 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4630 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4633 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4635 return NT_STATUS_INTERNAL_ERROR;
4637 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4639 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4642 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4644 return NT_STATUS_INTERNAL_ERROR;
4648 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4651 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4653 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4659 case SMB_QUERY_POSIX_LOCK:
4664 enum brl_type lock_type;
4666 /* We need an open file with a real fd for this. */
4667 if (!fsp || fsp->is_directory || fsp->fh->fd == -1) {
4668 return NT_STATUS_INVALID_LEVEL;
4671 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4672 return NT_STATUS_INVALID_PARAMETER;
4675 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4676 case POSIX_LOCK_TYPE_READ:
4677 lock_type = READ_LOCK;
4679 case POSIX_LOCK_TYPE_WRITE:
4680 lock_type = WRITE_LOCK;
4682 case POSIX_LOCK_TYPE_UNLOCK:
4684 /* There's no point in asking for an unlock... */
4685 return NT_STATUS_INVALID_PARAMETER;
4688 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4689 #if defined(HAVE_LONGLONG)
4690 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4691 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4692 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4693 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4694 #else /* HAVE_LONGLONG */
4695 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4696 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4697 #endif /* HAVE_LONGLONG */
4699 status = query_lock(fsp,
4706 if (ERROR_WAS_LOCK_DENIED(status)) {
4707 /* Here we need to report who has it locked... */
4708 data_size = POSIX_LOCK_DATA_SIZE;
4710 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4711 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4712 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4713 #if defined(HAVE_LONGLONG)
4714 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4715 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4716 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4717 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4718 #else /* HAVE_LONGLONG */
4719 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4720 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4721 #endif /* HAVE_LONGLONG */
4723 } else if (NT_STATUS_IS_OK(status)) {
4724 /* For success we just return a copy of what we sent
4725 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4726 data_size = POSIX_LOCK_DATA_SIZE;
4727 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4728 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4736 return NT_STATUS_INVALID_LEVEL;
4739 *pdata_size = data_size;
4740 return NT_STATUS_OK;
4743 /****************************************************************************
4744 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4745 file name or file id).
4746 ****************************************************************************/
4748 static void call_trans2qfilepathinfo(connection_struct *conn,
4749 struct smb_request *req,
4750 unsigned int tran_call,
4751 char **pparams, int total_params,
4752 char **ppdata, int total_data,
4753 unsigned int max_data_bytes)
4755 char *params = *pparams;
4756 char *pdata = *ppdata;
4758 unsigned int data_size = 0;
4759 unsigned int param_size = 2;
4760 struct smb_filename *smb_fname = NULL;
4761 bool delete_pending = False;
4762 struct timespec write_time_ts;
4763 files_struct *fsp = NULL;
4764 struct file_id fileid;
4765 struct ea_list *ea_list = NULL;
4766 int lock_data_count = 0;
4767 char *lock_data = NULL;
4768 bool ms_dfs_link = false;
4769 NTSTATUS status = NT_STATUS_OK;
4772 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4776 ZERO_STRUCT(write_time_ts);
4778 if (tran_call == TRANSACT2_QFILEINFO) {
4779 if (total_params < 4) {
4780 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4785 call_trans2qpipeinfo(conn, req, tran_call,
4786 pparams, total_params,
4792 fsp = file_fsp(req, SVAL(params,0));
4793 info_level = SVAL(params,2);
4795 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
4797 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4798 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4802 /* Initial check for valid fsp ptr. */
4803 if (!check_fsp_open(conn, req, fsp)) {
4807 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
4809 if (!NT_STATUS_IS_OK(status)) {
4810 reply_nterror(req, status);
4814 if(fsp->fake_file_handle) {
4816 * This is actually for the QUOTA_FAKE_FILE --metze
4819 /* We know this name is ok, it's already passed the checks. */
4821 } else if(fsp->is_directory || fsp->fh->fd == -1) {
4823 * This is actually a QFILEINFO on a directory
4824 * handle (returned from an NT SMB). NT5.0 seems
4825 * to do this call. JRA.
4828 if (INFO_LEVEL_IS_UNIX(info_level)) {
4829 /* Always do lstat for UNIX calls. */
4830 if (SMB_VFS_LSTAT(conn, smb_fname)) {
4831 DEBUG(3,("call_trans2qfilepathinfo: "
4832 "SMB_VFS_LSTAT of %s failed "
4834 smb_fname_str_dbg(smb_fname),
4837 map_nt_error_from_unix(errno));
4840 } else if (SMB_VFS_STAT(conn, smb_fname)) {
4841 DEBUG(3,("call_trans2qfilepathinfo: "
4842 "SMB_VFS_STAT of %s failed (%s)\n",
4843 smb_fname_str_dbg(smb_fname),
4846 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);
4854 * Original code - this is an open file.
4856 if (!check_fsp(conn, req, fsp)) {
4860 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
4861 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
4862 fsp->fnum, strerror(errno)));
4864 map_nt_error_from_unix(errno));
4867 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4868 get_file_infos(fileid, &delete_pending, &write_time_ts);
4875 if (total_params < 7) {
4876 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4880 info_level = SVAL(params,0);
4882 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
4884 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4885 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4889 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
4891 STR_TERMINATE, &status);
4892 if (!NT_STATUS_IS_OK(status)) {
4893 reply_nterror(req, status);
4897 status = filename_convert(req,
4899 req->flags2 & FLAGS2_DFS_PATHNAMES,
4904 if (!NT_STATUS_IS_OK(status)) {
4905 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4906 reply_botherror(req,
4907 NT_STATUS_PATH_NOT_COVERED,
4908 ERRSRV, ERRbadpath);
4911 reply_nterror(req, status);
4915 /* If this is a stream, check if there is a delete_pending. */
4916 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
4917 && is_ntfs_stream_smb_fname(smb_fname)) {
4918 struct smb_filename *smb_fname_base = NULL;
4920 /* Create an smb_filename with stream_name == NULL. */
4922 create_synthetic_smb_fname(talloc_tos(),
4923 smb_fname->base_name,
4926 if (!NT_STATUS_IS_OK(status)) {
4927 reply_nterror(req, status);
4931 if (INFO_LEVEL_IS_UNIX(info_level)) {
4932 /* Always do lstat for UNIX calls. */
4933 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
4934 DEBUG(3,("call_trans2qfilepathinfo: "
4935 "SMB_VFS_LSTAT of %s failed "
4937 smb_fname_str_dbg(smb_fname_base),
4939 TALLOC_FREE(smb_fname_base);
4941 map_nt_error_from_unix(errno));
4945 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
4946 DEBUG(3,("call_trans2qfilepathinfo: "
4947 "fileinfo of %s failed "
4949 smb_fname_str_dbg(smb_fname_base),
4951 TALLOC_FREE(smb_fname_base);
4953 map_nt_error_from_unix(errno));
4958 fileid = vfs_file_id_from_sbuf(conn,
4959 &smb_fname_base->st);
4960 TALLOC_FREE(smb_fname_base);
4961 get_file_infos(fileid, &delete_pending, NULL);
4962 if (delete_pending) {
4963 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4968 if (INFO_LEVEL_IS_UNIX(info_level)) {
4969 /* Always do lstat for UNIX calls. */
4970 if (SMB_VFS_LSTAT(conn, smb_fname)) {
4971 DEBUG(3,("call_trans2qfilepathinfo: "
4972 "SMB_VFS_LSTAT of %s failed (%s)\n",
4973 smb_fname_str_dbg(smb_fname),
4976 map_nt_error_from_unix(errno));
4980 } else if (!VALID_STAT(smb_fname->st) &&
4981 SMB_VFS_STAT(conn, smb_fname) &&
4982 (info_level != SMB_INFO_IS_NAME_VALID)) {
4983 ms_dfs_link = check_msdfs_link(conn,
4984 smb_fname->base_name,
4988 DEBUG(3,("call_trans2qfilepathinfo: "
4989 "SMB_VFS_STAT of %s failed (%s)\n",
4990 smb_fname_str_dbg(smb_fname),
4993 map_nt_error_from_unix(errno));
4998 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4999 get_file_infos(fileid, &delete_pending, &write_time_ts);
5000 if (delete_pending) {
5001 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5006 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5007 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5008 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5010 /* Pull out any data sent here before we realloc. */
5011 switch (info_level) {
5012 case SMB_INFO_QUERY_EAS_FROM_LIST:
5014 /* Pull any EA list from the data portion. */
5017 if (total_data < 4) {
5019 req, NT_STATUS_INVALID_PARAMETER);
5022 ea_size = IVAL(pdata,0);
5024 if (total_data > 0 && ea_size != total_data) {
5025 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5026 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5028 req, NT_STATUS_INVALID_PARAMETER);
5032 if (!lp_ea_support(SNUM(conn))) {
5033 reply_doserror(req, ERRDOS,
5034 ERReasnotsupported);
5038 /* Pull out the list of names. */
5039 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5042 req, NT_STATUS_INVALID_PARAMETER);
5048 case SMB_QUERY_POSIX_LOCK:
5050 if (fsp == NULL || fsp->fh->fd == -1) {
5051 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5055 if (total_data != POSIX_LOCK_DATA_SIZE) {
5057 req, NT_STATUS_INVALID_PARAMETER);
5061 /* Copy the lock range data. */
5062 lock_data = (char *)TALLOC_MEMDUP(
5063 req, pdata, total_data);
5065 reply_nterror(req, NT_STATUS_NO_MEMORY);
5068 lock_data_count = total_data;
5074 *pparams = (char *)SMB_REALLOC(*pparams,2);
5075 if (*pparams == NULL) {
5076 reply_nterror(req, NT_STATUS_NO_MEMORY);
5083 * draft-leach-cifs-v1-spec-02.txt
5084 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5087 * The requested information is placed in the Data portion of the
5088 * transaction response. For the information levels greater than 0x100,
5089 * the transaction response has 1 parameter word which should be
5090 * ignored by the client.
5092 * However Windows only follows this rule for the IS_NAME_VALID call.
5094 switch (info_level) {
5095 case SMB_INFO_IS_NAME_VALID:
5100 if ((info_level & 0xFF00) == 0xFF00) {
5102 * We use levels that start with 0xFF00
5103 * internally to represent SMB2 specific levels
5105 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5109 status = smbd_do_qfilepathinfo(conn, req, info_level,
5111 delete_pending, write_time_ts,
5112 ms_dfs_link, ea_list,
5113 lock_data_count, lock_data,
5114 req->flags2, max_data_bytes,
5115 ppdata, &data_size);
5116 if (!NT_STATUS_IS_OK(status)) {
5117 reply_nterror(req, status);
5121 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5127 /****************************************************************************
5128 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5130 ****************************************************************************/
5132 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5133 connection_struct *conn,
5134 const struct smb_filename *smb_fname_old,
5135 const struct smb_filename *smb_fname_new)
5137 NTSTATUS status = NT_STATUS_OK;
5139 /* source must already exist. */
5140 if (!VALID_STAT(smb_fname_old->st)) {
5141 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5144 /* Disallow if newname already exists. */
5145 if (VALID_STAT(smb_fname_new->st)) {
5146 return NT_STATUS_OBJECT_NAME_COLLISION;
5149 /* No links from a directory. */
5150 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5151 return NT_STATUS_FILE_IS_A_DIRECTORY;
5154 /* Setting a hardlink to/from a stream isn't currently supported. */
5155 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5156 is_ntfs_stream_smb_fname(smb_fname_new)) {
5157 return NT_STATUS_INVALID_PARAMETER;
5160 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5161 smb_fname_old->base_name, smb_fname_new->base_name));
5163 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5164 smb_fname_new->base_name) != 0) {
5165 status = map_nt_error_from_unix(errno);
5166 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5167 nt_errstr(status), smb_fname_old->base_name,
5168 smb_fname_new->base_name));
5173 /****************************************************************************
5174 Deal with setting the time from any of the setfilepathinfo functions.
5175 ****************************************************************************/
5177 NTSTATUS smb_set_file_time(connection_struct *conn,
5179 const struct smb_filename *smb_fname,
5180 struct smb_file_time *ft,
5181 bool setting_write_time)
5183 struct smb_filename *smb_fname_base = NULL;
5185 FILE_NOTIFY_CHANGE_LAST_ACCESS
5186 |FILE_NOTIFY_CHANGE_LAST_WRITE;
5187 bool set_createtime = false;
5188 bool set_ctime = false;
5191 if (!VALID_STAT(smb_fname->st)) {
5192 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5195 /* get some defaults (no modifications) if any info is zero or -1. */
5196 if (null_timespec(ft->create_time)) {
5197 ft->create_time = smb_fname->st.st_ex_btime;
5199 set_createtime = true;
5202 if (null_timespec(ft->ctime)) {
5203 ft->ctime = smb_fname->st.st_ex_ctime;
5208 if (null_timespec(ft->atime)) {
5209 ft->atime= smb_fname->st.st_ex_atime;
5210 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5213 if (null_timespec(ft->mtime)) {
5214 ft->mtime = smb_fname->st.st_ex_mtime;
5215 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5218 if (!setting_write_time) {
5219 /* ft->mtime comes from change time, not write time. */
5220 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5223 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5224 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5225 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5226 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5227 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5228 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5229 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5230 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5233 * Try and set the times of this file if
5234 * they are different from the current values.
5238 struct timespec mts = smb_fname->st.st_ex_mtime;
5239 struct timespec ats = smb_fname->st.st_ex_atime;
5240 if ((timespec_compare(&ft->atime, &ats) == 0) &&
5241 (timespec_compare(&ft->mtime, &mts) == 0)) {
5242 if (set_createtime || set_ctime) {
5243 notify_fname(conn, NOTIFY_ACTION_MODIFIED, FILE_NOTIFY_CHANGE_LAST_WRITE,
5244 smb_fname->base_name);
5246 return NT_STATUS_OK;
5250 if (setting_write_time) {
5252 * This was a Windows setfileinfo on an open file.
5253 * NT does this a lot. We also need to
5254 * set the time here, as it can be read by
5255 * FindFirst/FindNext and with the patch for bug #2045
5256 * in smbd/fileio.c it ensures that this timestamp is
5257 * kept sticky even after a write. We save the request
5258 * away and will set it on file close and after a write. JRA.
5261 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5262 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5265 if (fsp->base_fsp) {
5266 set_sticky_write_time_fsp(fsp->base_fsp,
5269 set_sticky_write_time_fsp(fsp, ft->mtime);
5272 set_sticky_write_time_path(
5273 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5278 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5280 /* Always call ntimes on the base, even if a stream was passed in. */
5281 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5282 NULL, &smb_fname->st,
5284 if (!NT_STATUS_IS_OK(status)) {
5288 if(file_ntimes(conn, smb_fname_base, ft)!=0) {
5289 TALLOC_FREE(smb_fname_base);
5290 return map_nt_error_from_unix(errno);
5292 TALLOC_FREE(smb_fname_base);
5294 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5295 smb_fname->base_name);
5296 return NT_STATUS_OK;
5299 /****************************************************************************
5300 Deal with setting the dosmode from any of the setfilepathinfo functions.
5301 ****************************************************************************/
5303 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5304 const struct smb_filename *smb_fname,
5307 struct smb_filename *smb_fname_base = NULL;
5310 if (!VALID_STAT(smb_fname->st)) {
5311 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5314 /* Always operate on the base_name, even if a stream was passed in. */
5315 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5316 NULL, &smb_fname->st,
5318 if (!NT_STATUS_IS_OK(status)) {
5323 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5330 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5332 /* check the mode isn't different, before changing it */
5333 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5334 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5335 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5336 (unsigned int)dosmode));
5338 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5340 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5342 smb_fname_str_dbg(smb_fname_base),
5344 status = map_nt_error_from_unix(errno);
5348 status = NT_STATUS_OK;
5350 TALLOC_FREE(smb_fname_base);
5354 /****************************************************************************
5355 Deal with setting the size from any of the setfilepathinfo functions.
5356 ****************************************************************************/
5358 static NTSTATUS smb_set_file_size(connection_struct *conn,
5359 struct smb_request *req,
5361 const struct smb_filename *smb_fname,
5362 const SMB_STRUCT_STAT *psbuf,
5365 NTSTATUS status = NT_STATUS_OK;
5366 struct smb_filename *smb_fname_tmp = NULL;
5367 files_struct *new_fsp = NULL;
5369 if (!VALID_STAT(*psbuf)) {
5370 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5373 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5375 if (size == get_file_size_stat(psbuf)) {
5376 return NT_STATUS_OK;
5379 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5380 smb_fname_str_dbg(smb_fname), (double)size));
5382 if (fsp && fsp->fh->fd != -1) {
5383 /* Handle based call. */
5384 if (vfs_set_filelen(fsp, size) == -1) {
5385 return map_nt_error_from_unix(errno);
5387 trigger_write_time_update_immediate(fsp);
5388 return NT_STATUS_OK;
5391 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5392 if (!NT_STATUS_IS_OK(status)) {
5396 smb_fname_tmp->st = *psbuf;
5398 status = SMB_VFS_CREATE_FILE(
5401 0, /* root_dir_fid */
5402 smb_fname_tmp, /* fname */
5403 FILE_WRITE_ATTRIBUTES, /* access_mask */
5404 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5406 FILE_OPEN, /* create_disposition*/
5407 0, /* create_options */
5408 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5409 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5410 0, /* allocation_size */
5413 &new_fsp, /* result */
5416 TALLOC_FREE(smb_fname_tmp);
5418 if (!NT_STATUS_IS_OK(status)) {
5419 /* NB. We check for open_was_deferred in the caller. */
5423 if (vfs_set_filelen(new_fsp, size) == -1) {
5424 status = map_nt_error_from_unix(errno);
5425 close_file(req, new_fsp,NORMAL_CLOSE);
5429 trigger_write_time_update_immediate(new_fsp);
5430 close_file(req, new_fsp,NORMAL_CLOSE);
5431 return NT_STATUS_OK;
5434 /****************************************************************************
5435 Deal with SMB_INFO_SET_EA.
5436 ****************************************************************************/
5438 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5442 const struct smb_filename *smb_fname)
5444 struct ea_list *ea_list = NULL;
5445 TALLOC_CTX *ctx = NULL;
5446 NTSTATUS status = NT_STATUS_OK;
5448 if (total_data < 10) {
5450 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5451 length. They seem to have no effect. Bug #3212. JRA */
5453 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5454 /* We're done. We only get EA info in this call. */
5455 return NT_STATUS_OK;
5458 return NT_STATUS_INVALID_PARAMETER;
5461 if (IVAL(pdata,0) > total_data) {
5462 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5463 IVAL(pdata,0), (unsigned int)total_data));
5464 return NT_STATUS_INVALID_PARAMETER;
5468 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5470 return NT_STATUS_INVALID_PARAMETER;
5472 status = set_ea(conn, fsp, smb_fname, ea_list);
5477 /****************************************************************************
5478 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5479 ****************************************************************************/
5481 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5485 const struct smb_filename *smb_fname)
5487 NTSTATUS status = NT_STATUS_OK;
5488 bool delete_on_close;
5491 if (total_data < 1) {
5492 return NT_STATUS_INVALID_PARAMETER;
5496 return NT_STATUS_INVALID_HANDLE;
5499 delete_on_close = (CVAL(pdata,0) ? True : False);
5500 dosmode = dos_mode(conn, smb_fname);
5502 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5503 "delete_on_close = %u\n",
5504 smb_fname_str_dbg(smb_fname),
5505 (unsigned int)dosmode,
5506 (unsigned int)delete_on_close ));
5508 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5510 if (!NT_STATUS_IS_OK(status)) {
5514 /* The set is across all open files on this dev/inode pair. */
5515 if (!set_delete_on_close(fsp, delete_on_close,
5516 &conn->server_info->utok)) {
5517 return NT_STATUS_ACCESS_DENIED;
5519 return NT_STATUS_OK;
5522 /****************************************************************************
5523 Deal with SMB_FILE_POSITION_INFORMATION.
5524 ****************************************************************************/
5526 static NTSTATUS smb_file_position_information(connection_struct *conn,
5531 uint64_t position_information;
5533 if (total_data < 8) {
5534 return NT_STATUS_INVALID_PARAMETER;
5538 /* Ignore on pathname based set. */
5539 return NT_STATUS_OK;
5542 position_information = (uint64_t)IVAL(pdata,0);
5543 #ifdef LARGE_SMB_OFF_T
5544 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5545 #else /* LARGE_SMB_OFF_T */
5546 if (IVAL(pdata,4) != 0) {
5547 /* more than 32 bits? */
5548 return NT_STATUS_INVALID_PARAMETER;
5550 #endif /* LARGE_SMB_OFF_T */
5552 DEBUG(10,("smb_file_position_information: Set file position "
5553 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5554 (double)position_information));
5555 fsp->fh->position_information = position_information;
5556 return NT_STATUS_OK;
5559 /****************************************************************************
5560 Deal with SMB_FILE_MODE_INFORMATION.
5561 ****************************************************************************/
5563 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5569 if (total_data < 4) {
5570 return NT_STATUS_INVALID_PARAMETER;
5572 mode = IVAL(pdata,0);
5573 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5574 return NT_STATUS_INVALID_PARAMETER;
5576 return NT_STATUS_OK;
5579 /****************************************************************************
5580 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5581 ****************************************************************************/
5583 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5584 struct smb_request *req,
5587 const struct smb_filename *smb_fname)
5589 char *link_target = NULL;
5590 const char *newname = smb_fname->base_name;
5591 NTSTATUS status = NT_STATUS_OK;
5592 TALLOC_CTX *ctx = talloc_tos();
5594 /* Set a symbolic link. */
5595 /* Don't allow this if follow links is false. */
5597 if (total_data == 0) {
5598 return NT_STATUS_INVALID_PARAMETER;
5601 if (!lp_symlinks(SNUM(conn))) {
5602 return NT_STATUS_ACCESS_DENIED;
5605 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5606 total_data, STR_TERMINATE);
5609 return NT_STATUS_INVALID_PARAMETER;
5612 /* !widelinks forces the target path to be within the share. */
5613 /* This means we can interpret the target as a pathname. */
5614 if (!lp_widelinks(SNUM(conn))) {
5615 char *rel_name = NULL;
5616 char *last_dirp = NULL;
5618 if (*link_target == '/') {
5619 /* No absolute paths allowed. */
5620 return NT_STATUS_ACCESS_DENIED;
5622 rel_name = talloc_strdup(ctx,newname);
5624 return NT_STATUS_NO_MEMORY;
5626 last_dirp = strrchr_m(rel_name, '/');
5628 last_dirp[1] = '\0';
5630 rel_name = talloc_strdup(ctx,"./");
5632 return NT_STATUS_NO_MEMORY;
5635 rel_name = talloc_asprintf_append(rel_name,
5639 return NT_STATUS_NO_MEMORY;
5642 status = check_name(conn, rel_name);
5643 if (!NT_STATUS_IS_OK(status)) {
5648 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5649 newname, link_target ));
5651 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5652 return map_nt_error_from_unix(errno);
5655 return NT_STATUS_OK;
5658 /****************************************************************************
5659 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5660 ****************************************************************************/
5662 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5663 struct smb_request *req,
5664 const char *pdata, int total_data,
5665 const struct smb_filename *smb_fname_new)
5667 char *oldname = NULL;
5668 struct smb_filename *smb_fname_old = NULL;
5669 TALLOC_CTX *ctx = talloc_tos();
5670 NTSTATUS status = NT_STATUS_OK;
5672 /* Set a hard link. */
5673 if (total_data == 0) {
5674 return NT_STATUS_INVALID_PARAMETER;
5677 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5678 total_data, STR_TERMINATE, &status);
5679 if (!NT_STATUS_IS_OK(status)) {
5683 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5684 smb_fname_str_dbg(smb_fname_new), oldname));
5686 status = filename_convert(ctx,
5688 req->flags2 & FLAGS2_DFS_PATHNAMES,
5693 if (!NT_STATUS_IS_OK(status)) {
5697 return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
5700 /****************************************************************************
5701 Deal with SMB_FILE_RENAME_INFORMATION.
5702 ****************************************************************************/
5704 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5705 struct smb_request *req,
5709 struct smb_filename *smb_fname_src)
5714 char *newname = NULL;
5715 struct smb_filename *smb_fname_dst = NULL;
5716 bool dest_has_wcard = False;
5717 NTSTATUS status = NT_STATUS_OK;
5719 TALLOC_CTX *ctx = talloc_tos();
5721 if (total_data < 13) {
5722 return NT_STATUS_INVALID_PARAMETER;
5725 overwrite = (CVAL(pdata,0) ? True : False);
5726 root_fid = IVAL(pdata,4);
5727 len = IVAL(pdata,8);
5729 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5730 return NT_STATUS_INVALID_PARAMETER;
5733 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5736 if (!NT_STATUS_IS_OK(status)) {
5740 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5743 status = resolve_dfspath_wcard(ctx, conn,
5744 req->flags2 & FLAGS2_DFS_PATHNAMES,
5748 if (!NT_STATUS_IS_OK(status)) {
5752 /* Check the new name has no '/' characters. */
5753 if (strchr_m(newname, '/')) {
5754 return NT_STATUS_NOT_SUPPORTED;
5757 if (fsp && fsp->base_fsp) {
5758 /* newname must be a stream name. */
5759 if (newname[0] != ':') {
5760 return NT_STATUS_NOT_SUPPORTED;
5763 /* Create an smb_fname to call rename_internals_fsp() with. */
5764 status = create_synthetic_smb_fname(talloc_tos(),
5765 fsp->base_fsp->fsp_name->base_name, newname, NULL,
5767 if (!NT_STATUS_IS_OK(status)) {
5772 * Set the original last component, since
5773 * rename_internals_fsp() requires it.
5775 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
5777 if (smb_fname_dst->original_lcomp == NULL) {
5778 status = NT_STATUS_NO_MEMORY;
5784 * Build up an smb_fname_dst based on the filename passed in.
5785 * We basically just strip off the last component, and put on
5786 * the newname instead.
5788 char *base_name = NULL;
5790 /* newname must *not* be a stream name. */
5791 if (newname[0] == ':') {
5792 return NT_STATUS_NOT_SUPPORTED;
5796 * Strip off the last component (filename) of the path passed
5799 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
5801 return NT_STATUS_NO_MEMORY;
5803 p = strrchr_m(base_name, '/');
5807 base_name = talloc_strdup(ctx, "./");
5809 return NT_STATUS_NO_MEMORY;
5812 /* Append the new name. */
5813 base_name = talloc_asprintf_append(base_name,
5817 return NT_STATUS_NO_MEMORY;
5820 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
5823 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
5826 /* If an error we expect this to be
5827 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5829 if (!NT_STATUS_IS_OK(status)) {
5830 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5834 /* Create an smb_fname to call rename_internals_fsp() */
5835 status = create_synthetic_smb_fname(ctx,
5839 if (!NT_STATUS_IS_OK(status)) {
5846 DEBUG(10,("smb_file_rename_information: "
5847 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5848 fsp->fnum, fsp_str_dbg(fsp),
5849 smb_fname_str_dbg(smb_fname_dst)));
5850 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
5853 DEBUG(10,("smb_file_rename_information: "
5854 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5855 smb_fname_str_dbg(smb_fname_src),
5856 smb_fname_str_dbg(smb_fname_dst)));
5857 status = rename_internals(ctx, conn, req, smb_fname_src,
5858 smb_fname_dst, 0, overwrite, false,
5860 FILE_WRITE_ATTRIBUTES);
5863 TALLOC_FREE(smb_fname_dst);
5867 /****************************************************************************
5868 Deal with SMB_SET_POSIX_ACL.
5869 ****************************************************************************/
5871 #if defined(HAVE_POSIX_ACLS)
5872 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5876 const struct smb_filename *smb_fname)
5878 uint16 posix_acl_version;
5879 uint16 num_file_acls;
5880 uint16 num_def_acls;
5881 bool valid_file_acls = True;
5882 bool valid_def_acls = True;
5884 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5885 return NT_STATUS_INVALID_PARAMETER;
5887 posix_acl_version = SVAL(pdata,0);
5888 num_file_acls = SVAL(pdata,2);
5889 num_def_acls = SVAL(pdata,4);
5891 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5892 valid_file_acls = False;
5896 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5897 valid_def_acls = False;
5901 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5902 return NT_STATUS_INVALID_PARAMETER;
5905 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5906 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5907 return NT_STATUS_INVALID_PARAMETER;
5910 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5911 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
5912 (unsigned int)num_file_acls,
5913 (unsigned int)num_def_acls));
5915 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
5916 smb_fname->base_name, num_file_acls,
5917 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5918 return map_nt_error_from_unix(errno);
5921 if (valid_def_acls && !set_unix_posix_default_acl(conn,
5922 smb_fname->base_name, &smb_fname->st, num_def_acls,
5923 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5924 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5925 return map_nt_error_from_unix(errno);
5927 return NT_STATUS_OK;
5931 /****************************************************************************
5932 Deal with SMB_SET_POSIX_LOCK.
5933 ****************************************************************************/
5935 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5936 struct smb_request *req,
5944 bool blocking_lock = False;
5945 enum brl_type lock_type;
5947 NTSTATUS status = NT_STATUS_OK;
5949 if (fsp == NULL || fsp->fh->fd == -1) {
5950 return NT_STATUS_INVALID_HANDLE;
5953 if (total_data != POSIX_LOCK_DATA_SIZE) {
5954 return NT_STATUS_INVALID_PARAMETER;
5957 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5958 case POSIX_LOCK_TYPE_READ:
5959 lock_type = READ_LOCK;
5961 case POSIX_LOCK_TYPE_WRITE:
5962 /* Return the right POSIX-mappable error code for files opened read-only. */
5963 if (!fsp->can_write) {
5964 return NT_STATUS_INVALID_HANDLE;
5966 lock_type = WRITE_LOCK;
5968 case POSIX_LOCK_TYPE_UNLOCK:
5969 lock_type = UNLOCK_LOCK;
5972 return NT_STATUS_INVALID_PARAMETER;
5975 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5976 blocking_lock = False;
5977 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5978 blocking_lock = True;
5980 return NT_STATUS_INVALID_PARAMETER;
5983 if (!lp_blocking_locks(SNUM(conn))) {
5984 blocking_lock = False;
5987 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5988 #if defined(HAVE_LONGLONG)
5989 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5990 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5991 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5992 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5993 #else /* HAVE_LONGLONG */
5994 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5995 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5996 #endif /* HAVE_LONGLONG */
5998 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5999 "lock_pid = %u, count = %.0f, offset = %.0f\n",
6001 (unsigned int)lock_type,
6002 (unsigned int)lock_pid,
6006 if (lock_type == UNLOCK_LOCK) {
6007 status = do_unlock(smbd_messaging_context(),
6014 uint32 block_smbpid;
6016 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
6028 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6030 * A blocking lock was requested. Package up
6031 * this smb into a queued request and push it
6032 * onto the blocking lock queue.
6034 if(push_blocking_lock_request(br_lck,
6037 -1, /* infinite timeout. */
6045 TALLOC_FREE(br_lck);
6049 TALLOC_FREE(br_lck);
6055 /****************************************************************************
6056 Deal with SMB_SET_FILE_BASIC_INFO.
6057 ****************************************************************************/
6059 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6063 const struct smb_filename *smb_fname)
6065 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6066 struct smb_file_time ft;
6068 NTSTATUS status = NT_STATUS_OK;
6072 if (total_data < 36) {
6073 return NT_STATUS_INVALID_PARAMETER;
6076 /* Set the attributes */
6077 dosmode = IVAL(pdata,32);
6078 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6079 if (!NT_STATUS_IS_OK(status)) {
6084 ft.create_time = interpret_long_date(pdata);
6087 ft.atime = interpret_long_date(pdata+8);
6090 ft.mtime = interpret_long_date(pdata+16);
6093 ft.ctime = interpret_long_date(pdata+24);
6095 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6096 smb_fname_str_dbg(smb_fname)));
6098 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6102 /****************************************************************************
6103 Deal with SMB_INFO_STANDARD.
6104 ****************************************************************************/
6106 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6110 const struct smb_filename *smb_fname)
6112 struct smb_file_time ft;
6116 if (total_data < 12) {
6117 return NT_STATUS_INVALID_PARAMETER;
6121 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6123 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6125 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6127 DEBUG(10,("smb_set_info_standard: file %s\n",
6128 smb_fname_str_dbg(smb_fname)));
6130 return smb_set_file_time(conn,
6137 /****************************************************************************
6138 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6139 ****************************************************************************/
6141 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6142 struct smb_request *req,
6146 struct smb_filename *smb_fname)
6148 uint64_t allocation_size = 0;
6149 NTSTATUS status = NT_STATUS_OK;
6150 files_struct *new_fsp = NULL;
6152 if (!VALID_STAT(smb_fname->st)) {
6153 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6156 if (total_data < 8) {
6157 return NT_STATUS_INVALID_PARAMETER;
6160 allocation_size = (uint64_t)IVAL(pdata,0);
6161 #ifdef LARGE_SMB_OFF_T
6162 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6163 #else /* LARGE_SMB_OFF_T */
6164 if (IVAL(pdata,4) != 0) {
6165 /* more than 32 bits? */
6166 return NT_STATUS_INVALID_PARAMETER;
6168 #endif /* LARGE_SMB_OFF_T */
6170 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6171 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6172 (double)allocation_size));
6174 if (allocation_size) {
6175 allocation_size = smb_roundup(conn, allocation_size);
6178 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6179 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6180 (double)allocation_size));
6182 if (fsp && fsp->fh->fd != -1) {
6183 /* Open file handle. */
6184 /* Only change if needed. */
6185 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6186 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6187 return map_nt_error_from_unix(errno);
6190 /* But always update the time. */
6192 * This is equivalent to a write. Ensure it's seen immediately
6193 * if there are no pending writes.
6195 trigger_write_time_update_immediate(fsp);
6196 return NT_STATUS_OK;
6199 /* Pathname or stat or directory file. */
6200 status = SMB_VFS_CREATE_FILE(
6203 0, /* root_dir_fid */
6204 smb_fname, /* fname */
6205 FILE_WRITE_DATA, /* access_mask */
6206 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6208 FILE_OPEN, /* create_disposition*/
6209 0, /* create_options */
6210 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6211 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6212 0, /* allocation_size */
6215 &new_fsp, /* result */
6218 if (!NT_STATUS_IS_OK(status)) {
6219 /* NB. We check for open_was_deferred in the caller. */
6223 /* Only change if needed. */
6224 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6225 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6226 status = map_nt_error_from_unix(errno);
6227 close_file(req, new_fsp, NORMAL_CLOSE);
6232 /* Changing the allocation size should set the last mod time. */
6234 * This is equivalent to a write. Ensure it's seen immediately
6235 * if there are no pending writes.
6237 trigger_write_time_update_immediate(new_fsp);
6239 close_file(req, new_fsp, NORMAL_CLOSE);
6240 return NT_STATUS_OK;
6243 /****************************************************************************
6244 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6245 ****************************************************************************/
6247 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6248 struct smb_request *req,
6252 const struct smb_filename *smb_fname)
6256 if (total_data < 8) {
6257 return NT_STATUS_INVALID_PARAMETER;
6260 size = IVAL(pdata,0);
6261 #ifdef LARGE_SMB_OFF_T
6262 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6263 #else /* LARGE_SMB_OFF_T */
6264 if (IVAL(pdata,4) != 0) {
6265 /* more than 32 bits? */
6266 return NT_STATUS_INVALID_PARAMETER;
6268 #endif /* LARGE_SMB_OFF_T */
6269 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6270 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6273 return smb_set_file_size(conn, req,
6280 /****************************************************************************
6281 Allow a UNIX info mknod.
6282 ****************************************************************************/
6284 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6287 const struct smb_filename *smb_fname)
6289 uint32 file_type = IVAL(pdata,56);
6290 #if defined(HAVE_MAKEDEV)
6291 uint32 dev_major = IVAL(pdata,60);
6292 uint32 dev_minor = IVAL(pdata,68);
6294 SMB_DEV_T dev = (SMB_DEV_T)0;
6295 uint32 raw_unixmode = IVAL(pdata,84);
6299 if (total_data < 100) {
6300 return NT_STATUS_INVALID_PARAMETER;
6303 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6304 PERM_NEW_FILE, &unixmode);
6305 if (!NT_STATUS_IS_OK(status)) {
6309 #if defined(HAVE_MAKEDEV)
6310 dev = makedev(dev_major, dev_minor);
6313 switch (file_type) {
6314 #if defined(S_IFIFO)
6315 case UNIX_TYPE_FIFO:
6316 unixmode |= S_IFIFO;
6319 #if defined(S_IFSOCK)
6320 case UNIX_TYPE_SOCKET:
6321 unixmode |= S_IFSOCK;
6324 #if defined(S_IFCHR)
6325 case UNIX_TYPE_CHARDEV:
6326 unixmode |= S_IFCHR;
6329 #if defined(S_IFBLK)
6330 case UNIX_TYPE_BLKDEV:
6331 unixmode |= S_IFBLK;
6335 return NT_STATUS_INVALID_PARAMETER;
6338 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6339 "%.0f mode 0%o for file %s\n", (double)dev,
6340 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6342 /* Ok - do the mknod. */
6343 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6344 return map_nt_error_from_unix(errno);
6347 /* If any of the other "set" calls fail we
6348 * don't want to end up with a half-constructed mknod.
6351 if (lp_inherit_perms(SNUM(conn))) {
6353 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6355 return NT_STATUS_NO_MEMORY;
6357 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6359 TALLOC_FREE(parent);
6362 return NT_STATUS_OK;
6365 /****************************************************************************
6366 Deal with SMB_SET_FILE_UNIX_BASIC.
6367 ****************************************************************************/
6369 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6370 struct smb_request *req,
6374 const struct smb_filename *smb_fname)
6376 struct smb_file_time ft;
6377 uint32 raw_unixmode;
6380 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6381 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6382 NTSTATUS status = NT_STATUS_OK;
6383 bool delete_on_fail = False;
6384 enum perm_type ptype;
6385 files_struct *all_fsps = NULL;
6386 bool modify_mtime = true;
6388 SMB_STRUCT_STAT sbuf;
6392 if (total_data < 100) {
6393 return NT_STATUS_INVALID_PARAMETER;
6396 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6397 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6398 size=IVAL(pdata,0); /* first 8 Bytes are size */
6399 #ifdef LARGE_SMB_OFF_T
6400 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6401 #else /* LARGE_SMB_OFF_T */
6402 if (IVAL(pdata,4) != 0) {
6403 /* more than 32 bits? */
6404 return NT_STATUS_INVALID_PARAMETER;
6406 #endif /* LARGE_SMB_OFF_T */
6409 ft.atime = interpret_long_date(pdata+24); /* access_time */
6410 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6411 set_owner = (uid_t)IVAL(pdata,40);
6412 set_grp = (gid_t)IVAL(pdata,48);
6413 raw_unixmode = IVAL(pdata,84);
6415 if (VALID_STAT(smb_fname->st)) {
6416 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6417 ptype = PERM_EXISTING_DIR;
6419 ptype = PERM_EXISTING_FILE;
6422 ptype = PERM_NEW_FILE;
6425 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6427 if (!NT_STATUS_IS_OK(status)) {
6431 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6432 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6433 smb_fname_str_dbg(smb_fname), (double)size,
6434 (unsigned int)set_owner, (unsigned int)set_grp,
6435 (int)raw_unixmode));
6437 sbuf = smb_fname->st;
6439 if (!VALID_STAT(sbuf)) {
6440 struct smb_filename *smb_fname_tmp = NULL;
6442 * The only valid use of this is to create character and block
6443 * devices, and named pipes. This is deprecated (IMHO) and
6444 * a new info level should be used for mknod. JRA.
6447 status = smb_unix_mknod(conn,
6451 if (!NT_STATUS_IS_OK(status)) {
6455 status = copy_smb_filename(talloc_tos(), smb_fname,
6457 if (!NT_STATUS_IS_OK(status)) {
6461 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6462 status = map_nt_error_from_unix(errno);
6463 TALLOC_FREE(smb_fname_tmp);
6464 SMB_VFS_UNLINK(conn, smb_fname);
6468 sbuf = smb_fname_tmp->st;
6469 TALLOC_FREE(smb_fname_tmp);
6471 /* Ensure we don't try and change anything else. */
6472 raw_unixmode = SMB_MODE_NO_CHANGE;
6473 size = get_file_size_stat(&sbuf);
6474 ft.atime = sbuf.st_ex_atime;
6475 ft.mtime = sbuf.st_ex_mtime;
6477 * We continue here as we might want to change the
6480 delete_on_fail = True;
6484 /* Horrible backwards compatibility hack as an old server bug
6485 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6489 size = get_file_size_stat(&sbuf);
6494 * Deal with the UNIX specific mode set.
6497 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6498 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6499 "setting mode 0%o for file %s\n",
6500 (unsigned int)unixmode,
6501 smb_fname_str_dbg(smb_fname)));
6502 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6503 return map_nt_error_from_unix(errno);
6508 * Deal with the UNIX specific uid set.
6511 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6512 (sbuf.st_ex_uid != set_owner)) {
6515 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6516 "changing owner %u for path %s\n",
6517 (unsigned int)set_owner,
6518 smb_fname_str_dbg(smb_fname)));
6520 if (S_ISLNK(sbuf.st_ex_mode)) {
6521 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6522 set_owner, (gid_t)-1);
6524 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6525 set_owner, (gid_t)-1);
6529 status = map_nt_error_from_unix(errno);
6530 if (delete_on_fail) {
6531 SMB_VFS_UNLINK(conn, smb_fname);
6538 * Deal with the UNIX specific gid set.
6541 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6542 (sbuf.st_ex_gid != set_grp)) {
6543 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6544 "changing group %u for file %s\n",
6545 (unsigned int)set_owner,
6546 smb_fname_str_dbg(smb_fname)));
6547 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6549 status = map_nt_error_from_unix(errno);
6550 if (delete_on_fail) {
6551 SMB_VFS_UNLINK(conn, smb_fname);
6557 /* Deal with any size changes. */
6559 status = smb_set_file_size(conn, req,
6564 if (!NT_STATUS_IS_OK(status)) {
6568 /* Deal with any time changes. */
6569 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6570 /* No change, don't cancel anything. */
6574 id = vfs_file_id_from_sbuf(conn, &sbuf);
6575 for(all_fsps = file_find_di_first(id); all_fsps;
6576 all_fsps = file_find_di_next(all_fsps)) {
6578 * We're setting the time explicitly for UNIX.
6579 * Cancel any pending changes over all handles.
6581 all_fsps->update_write_time_on_close = false;
6582 TALLOC_FREE(all_fsps->update_write_time_event);
6586 * Override the "setting_write_time"
6587 * parameter here as it almost does what
6588 * we need. Just remember if we modified
6589 * mtime and send the notify ourselves.
6591 if (null_timespec(ft.mtime)) {
6592 modify_mtime = false;
6595 status = smb_set_file_time(conn,
6601 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6602 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6607 /****************************************************************************
6608 Deal with SMB_SET_FILE_UNIX_INFO2.
6609 ****************************************************************************/
6611 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6612 struct smb_request *req,
6616 const struct smb_filename *smb_fname)
6622 if (total_data < 116) {
6623 return NT_STATUS_INVALID_PARAMETER;
6626 /* Start by setting all the fields that are common between UNIX_BASIC
6629 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6631 if (!NT_STATUS_IS_OK(status)) {
6635 smb_fflags = IVAL(pdata, 108);
6636 smb_fmask = IVAL(pdata, 112);
6638 /* NB: We should only attempt to alter the file flags if the client
6639 * sends a non-zero mask.
6641 if (smb_fmask != 0) {
6642 int stat_fflags = 0;
6644 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6645 smb_fmask, &stat_fflags)) {
6646 /* Client asked to alter a flag we don't understand. */
6647 return NT_STATUS_INVALID_PARAMETER;
6650 if (fsp && fsp->fh->fd != -1) {
6651 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6652 return NT_STATUS_NOT_SUPPORTED;
6654 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
6655 stat_fflags) != 0) {
6656 return map_nt_error_from_unix(errno);
6661 /* XXX: need to add support for changing the create_time here. You
6662 * can do this for paths on Darwin with setattrlist(2). The right way
6663 * to hook this up is probably by extending the VFS utimes interface.
6666 return NT_STATUS_OK;
6669 /****************************************************************************
6670 Create a directory with POSIX semantics.
6671 ****************************************************************************/
6673 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6674 struct smb_request *req,
6677 struct smb_filename *smb_fname,
6678 int *pdata_return_size)
6680 NTSTATUS status = NT_STATUS_OK;
6681 uint32 raw_unixmode = 0;
6682 uint32 mod_unixmode = 0;
6683 mode_t unixmode = (mode_t)0;
6684 files_struct *fsp = NULL;
6685 uint16 info_level_return = 0;
6687 char *pdata = *ppdata;
6689 if (total_data < 18) {
6690 return NT_STATUS_INVALID_PARAMETER;
6693 raw_unixmode = IVAL(pdata,8);
6694 /* Next 4 bytes are not yet defined. */
6696 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6697 PERM_NEW_DIR, &unixmode);
6698 if (!NT_STATUS_IS_OK(status)) {
6702 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6704 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6705 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
6707 status = SMB_VFS_CREATE_FILE(
6710 0, /* root_dir_fid */
6711 smb_fname, /* fname */
6712 FILE_READ_ATTRIBUTES, /* access_mask */
6713 FILE_SHARE_NONE, /* share_access */
6714 FILE_CREATE, /* create_disposition*/
6715 FILE_DIRECTORY_FILE, /* create_options */
6716 mod_unixmode, /* file_attributes */
6717 0, /* oplock_request */
6718 0, /* allocation_size */
6724 if (NT_STATUS_IS_OK(status)) {
6725 close_file(req, fsp, NORMAL_CLOSE);
6728 info_level_return = SVAL(pdata,16);
6730 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6731 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6732 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6733 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6735 *pdata_return_size = 12;
6738 /* Realloc the data size */
6739 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6740 if (*ppdata == NULL) {
6741 *pdata_return_size = 0;
6742 return NT_STATUS_NO_MEMORY;
6746 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6747 SSVAL(pdata,2,0); /* No fnum. */
6748 SIVAL(pdata,4,info); /* Was directory created. */
6750 switch (info_level_return) {
6751 case SMB_QUERY_FILE_UNIX_BASIC:
6752 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6753 SSVAL(pdata,10,0); /* Padding. */
6754 store_file_unix_basic(conn, pdata + 12, fsp,
6757 case SMB_QUERY_FILE_UNIX_INFO2:
6758 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6759 SSVAL(pdata,10,0); /* Padding. */
6760 store_file_unix_basic_info2(conn, pdata + 12, fsp,
6764 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6765 SSVAL(pdata,10,0); /* Padding. */
6772 /****************************************************************************
6773 Open/Create a file with POSIX semantics.
6774 ****************************************************************************/
6776 static NTSTATUS smb_posix_open(connection_struct *conn,
6777 struct smb_request *req,
6780 struct smb_filename *smb_fname,
6781 int *pdata_return_size)
6783 bool extended_oplock_granted = False;
6784 char *pdata = *ppdata;
6786 uint32 wire_open_mode = 0;
6787 uint32 raw_unixmode = 0;
6788 uint32 mod_unixmode = 0;
6789 uint32 create_disp = 0;
6790 uint32 access_mask = 0;
6791 uint32 create_options = 0;
6792 NTSTATUS status = NT_STATUS_OK;
6793 mode_t unixmode = (mode_t)0;
6794 files_struct *fsp = NULL;
6795 int oplock_request = 0;
6797 uint16 info_level_return = 0;
6799 if (total_data < 18) {
6800 return NT_STATUS_INVALID_PARAMETER;
6803 flags = IVAL(pdata,0);
6804 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6805 if (oplock_request) {
6806 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6809 wire_open_mode = IVAL(pdata,4);
6811 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6812 return smb_posix_mkdir(conn, req,
6819 switch (wire_open_mode & SMB_ACCMODE) {
6821 access_mask = FILE_READ_DATA;
6824 access_mask = FILE_WRITE_DATA;
6827 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6830 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6831 (unsigned int)wire_open_mode ));
6832 return NT_STATUS_INVALID_PARAMETER;
6835 wire_open_mode &= ~SMB_ACCMODE;
6837 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6838 create_disp = FILE_CREATE;
6839 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6840 create_disp = FILE_OVERWRITE_IF;
6841 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6842 create_disp = FILE_OPEN_IF;
6843 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6844 create_disp = FILE_OPEN;
6846 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6847 (unsigned int)wire_open_mode ));
6848 return NT_STATUS_INVALID_PARAMETER;
6851 raw_unixmode = IVAL(pdata,8);
6852 /* Next 4 bytes are not yet defined. */
6854 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6855 (VALID_STAT(smb_fname->st) ?
6856 PERM_EXISTING_FILE : PERM_NEW_FILE),
6859 if (!NT_STATUS_IS_OK(status)) {
6863 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6865 if (wire_open_mode & SMB_O_SYNC) {
6866 create_options |= FILE_WRITE_THROUGH;
6868 if (wire_open_mode & SMB_O_APPEND) {
6869 access_mask |= FILE_APPEND_DATA;
6871 if (wire_open_mode & SMB_O_DIRECT) {
6872 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6875 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6876 smb_fname_str_dbg(smb_fname),
6877 (unsigned int)wire_open_mode,
6878 (unsigned int)unixmode ));
6880 status = SMB_VFS_CREATE_FILE(
6883 0, /* root_dir_fid */
6884 smb_fname, /* fname */
6885 access_mask, /* access_mask */
6886 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6888 create_disp, /* create_disposition*/
6889 FILE_NON_DIRECTORY_FILE, /* create_options */
6890 mod_unixmode, /* file_attributes */
6891 oplock_request, /* oplock_request */
6892 0, /* allocation_size */
6898 if (!NT_STATUS_IS_OK(status)) {
6902 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6903 extended_oplock_granted = True;
6906 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6907 extended_oplock_granted = True;
6910 info_level_return = SVAL(pdata,16);
6912 /* Allocate the correct return size. */
6914 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6915 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6916 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6917 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6919 *pdata_return_size = 12;
6922 /* Realloc the data size */
6923 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6924 if (*ppdata == NULL) {
6925 close_file(req, fsp, ERROR_CLOSE);
6926 *pdata_return_size = 0;
6927 return NT_STATUS_NO_MEMORY;
6931 if (extended_oplock_granted) {
6932 if (flags & REQUEST_BATCH_OPLOCK) {
6933 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6935 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6937 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6938 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6940 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6943 SSVAL(pdata,2,fsp->fnum);
6944 SIVAL(pdata,4,info); /* Was file created etc. */
6946 switch (info_level_return) {
6947 case SMB_QUERY_FILE_UNIX_BASIC:
6948 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6949 SSVAL(pdata,10,0); /* padding. */
6950 store_file_unix_basic(conn, pdata + 12, fsp,
6953 case SMB_QUERY_FILE_UNIX_INFO2:
6954 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6955 SSVAL(pdata,10,0); /* padding. */
6956 store_file_unix_basic_info2(conn, pdata + 12, fsp,
6960 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6961 SSVAL(pdata,10,0); /* padding. */
6964 return NT_STATUS_OK;
6967 /****************************************************************************
6968 Delete a file with POSIX semantics.
6969 ****************************************************************************/
6971 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6972 struct smb_request *req,
6975 struct smb_filename *smb_fname)
6977 NTSTATUS status = NT_STATUS_OK;
6978 files_struct *fsp = NULL;
6982 int create_options = 0;
6984 struct share_mode_lock *lck = NULL;
6986 if (total_data < 2) {
6987 return NT_STATUS_INVALID_PARAMETER;
6990 flags = SVAL(pdata,0);
6992 if (!VALID_STAT(smb_fname->st)) {
6993 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6996 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6997 !VALID_STAT_OF_DIR(smb_fname->st)) {
6998 return NT_STATUS_NOT_A_DIRECTORY;
7001 DEBUG(10,("smb_posix_unlink: %s %s\n",
7002 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7003 smb_fname_str_dbg(smb_fname)));
7005 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7006 create_options |= FILE_DIRECTORY_FILE;
7009 status = SMB_VFS_CREATE_FILE(
7012 0, /* root_dir_fid */
7013 smb_fname, /* fname */
7014 DELETE_ACCESS, /* access_mask */
7015 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7017 FILE_OPEN, /* create_disposition*/
7018 create_options, /* create_options */
7019 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7020 0, /* oplock_request */
7021 0, /* allocation_size */
7027 if (!NT_STATUS_IS_OK(status)) {
7032 * Don't lie to client. If we can't really delete due to
7033 * non-POSIX opens return SHARING_VIOLATION.
7036 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7039 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7040 "lock for file %s\n", fsp_str_dbg(fsp)));
7041 close_file(req, fsp, NORMAL_CLOSE);
7042 return NT_STATUS_INVALID_PARAMETER;
7046 * See if others still have the file open. If this is the case, then
7047 * don't delete. If all opens are POSIX delete we can set the delete
7048 * on close disposition.
7050 for (i=0; i<lck->num_share_modes; i++) {
7051 struct share_mode_entry *e = &lck->share_modes[i];
7052 if (is_valid_share_mode_entry(e)) {
7053 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7056 /* Fail with sharing violation. */
7057 close_file(req, fsp, NORMAL_CLOSE);
7059 return NT_STATUS_SHARING_VIOLATION;
7064 * Set the delete on close.
7066 status = smb_set_file_disposition_info(conn,
7072 if (!NT_STATUS_IS_OK(status)) {
7073 close_file(req, fsp, NORMAL_CLOSE);
7078 return close_file(req, fsp, NORMAL_CLOSE);
7081 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7082 struct smb_request *req,
7083 TALLOC_CTX *mem_ctx,
7084 uint16_t info_level,
7086 struct smb_filename *smb_fname,
7087 char **ppdata, int total_data,
7090 char *pdata = *ppdata;
7091 NTSTATUS status = NT_STATUS_OK;
7092 int data_return_size = 0;
7096 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7097 return NT_STATUS_INVALID_LEVEL;
7100 if (!CAN_WRITE(conn)) {
7101 /* Allow POSIX opens. The open path will deny
7102 * any non-readonly opens. */
7103 if (info_level != SMB_POSIX_PATH_OPEN) {
7104 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7108 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7109 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7110 fsp ? fsp->fnum : -1, info_level, total_data));
7112 switch (info_level) {
7114 case SMB_INFO_STANDARD:
7116 status = smb_set_info_standard(conn,
7124 case SMB_INFO_SET_EA:
7126 status = smb_info_set_ea(conn,
7134 case SMB_SET_FILE_BASIC_INFO:
7135 case SMB_FILE_BASIC_INFORMATION:
7137 status = smb_set_file_basic_info(conn,
7145 case SMB_FILE_ALLOCATION_INFORMATION:
7146 case SMB_SET_FILE_ALLOCATION_INFO:
7148 status = smb_set_file_allocation_info(conn, req,
7156 case SMB_FILE_END_OF_FILE_INFORMATION:
7157 case SMB_SET_FILE_END_OF_FILE_INFO:
7159 status = smb_set_file_end_of_file_info(conn, req,
7167 case SMB_FILE_DISPOSITION_INFORMATION:
7168 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7171 /* JRA - We used to just ignore this on a path ?
7172 * Shouldn't this be invalid level on a pathname
7175 if (tran_call != TRANSACT2_SETFILEINFO) {
7176 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7179 status = smb_set_file_disposition_info(conn,
7187 case SMB_FILE_POSITION_INFORMATION:
7189 status = smb_file_position_information(conn,
7196 /* From tridge Samba4 :
7197 * MODE_INFORMATION in setfileinfo (I have no
7198 * idea what "mode information" on a file is - it takes a value of 0,
7199 * 2, 4 or 6. What could it be?).
7202 case SMB_FILE_MODE_INFORMATION:
7204 status = smb_file_mode_information(conn,
7211 * CIFS UNIX extensions.
7214 case SMB_SET_FILE_UNIX_BASIC:
7216 status = smb_set_file_unix_basic(conn, req,
7224 case SMB_SET_FILE_UNIX_INFO2:
7226 status = smb_set_file_unix_info2(conn, req,
7234 case SMB_SET_FILE_UNIX_LINK:
7237 /* We must have a pathname for this. */
7238 return NT_STATUS_INVALID_LEVEL;
7240 status = smb_set_file_unix_link(conn, req, pdata,
7241 total_data, smb_fname);
7245 case SMB_SET_FILE_UNIX_HLINK:
7248 /* We must have a pathname for this. */
7249 return NT_STATUS_INVALID_LEVEL;
7251 status = smb_set_file_unix_hlink(conn, req,
7257 case SMB_FILE_RENAME_INFORMATION:
7259 status = smb_file_rename_information(conn, req,
7265 #if defined(HAVE_POSIX_ACLS)
7266 case SMB_SET_POSIX_ACL:
7268 status = smb_set_posix_acl(conn,
7277 case SMB_SET_POSIX_LOCK:
7280 return NT_STATUS_INVALID_LEVEL;
7282 status = smb_set_posix_lock(conn, req,
7283 pdata, total_data, fsp);
7287 case SMB_POSIX_PATH_OPEN:
7290 /* We must have a pathname for this. */
7291 return NT_STATUS_INVALID_LEVEL;
7294 status = smb_posix_open(conn, req,
7302 case SMB_POSIX_PATH_UNLINK:
7305 /* We must have a pathname for this. */
7306 return NT_STATUS_INVALID_LEVEL;
7309 status = smb_posix_unlink(conn, req,
7317 return NT_STATUS_INVALID_LEVEL;
7320 if (!NT_STATUS_IS_OK(status)) {
7324 *ret_data_size = data_return_size;
7325 return NT_STATUS_OK;
7328 /****************************************************************************
7329 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7330 ****************************************************************************/
7332 static void call_trans2setfilepathinfo(connection_struct *conn,
7333 struct smb_request *req,
7334 unsigned int tran_call,
7335 char **pparams, int total_params,
7336 char **ppdata, int total_data,
7337 unsigned int max_data_bytes)
7339 char *params = *pparams;
7340 char *pdata = *ppdata;
7342 struct smb_filename *smb_fname = NULL;
7343 files_struct *fsp = NULL;
7344 NTSTATUS status = NT_STATUS_OK;
7345 int data_return_size = 0;
7348 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7352 if (tran_call == TRANSACT2_SETFILEINFO) {
7353 if (total_params < 4) {
7354 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7358 fsp = file_fsp(req, SVAL(params,0));
7359 /* Basic check for non-null fsp. */
7360 if (!check_fsp_open(conn, req, fsp)) {
7363 info_level = SVAL(params,2);
7365 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7367 if (!NT_STATUS_IS_OK(status)) {
7368 reply_nterror(req, status);
7372 if(fsp->is_directory || fsp->fh->fd == -1) {
7374 * This is actually a SETFILEINFO on a directory
7375 * handle (returned from an NT SMB). NT5.0 seems
7376 * to do this call. JRA.
7378 if (INFO_LEVEL_IS_UNIX(info_level)) {
7379 /* Always do lstat for UNIX calls. */
7380 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7381 DEBUG(3,("call_trans2setfilepathinfo: "
7382 "SMB_VFS_LSTAT of %s failed "
7384 smb_fname_str_dbg(smb_fname),
7386 reply_nterror(req, map_nt_error_from_unix(errno));
7390 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7391 DEBUG(3,("call_trans2setfilepathinfo: "
7392 "fileinfo of %s failed (%s)\n",
7393 smb_fname_str_dbg(smb_fname),
7395 reply_nterror(req, map_nt_error_from_unix(errno));
7399 } else if (fsp->print_file) {
7401 * Doing a DELETE_ON_CLOSE should cancel a print job.
7403 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7404 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
7406 DEBUG(3,("call_trans2setfilepathinfo: "
7407 "Cancelling print job (%s)\n",
7411 send_trans2_replies(conn, req, params, 2,
7416 reply_doserror(req, ERRDOS, ERRbadpath);
7421 * Original code - this is an open file.
7423 if (!check_fsp(conn, req, fsp)) {
7427 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7428 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7429 "of fnum %d failed (%s)\n", fsp->fnum,
7431 reply_nterror(req, map_nt_error_from_unix(errno));
7439 if (total_params < 7) {
7440 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7444 info_level = SVAL(params,0);
7445 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
7446 total_params - 6, STR_TERMINATE,
7448 if (!NT_STATUS_IS_OK(status)) {
7449 reply_nterror(req, status);
7453 status = filename_convert(req, conn,
7454 req->flags2 & FLAGS2_DFS_PATHNAMES,
7459 if (!NT_STATUS_IS_OK(status)) {
7460 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7461 reply_botherror(req,
7462 NT_STATUS_PATH_NOT_COVERED,
7463 ERRSRV, ERRbadpath);
7466 reply_nterror(req, status);
7470 if (INFO_LEVEL_IS_UNIX(info_level)) {
7472 * For CIFS UNIX extensions the target name may not exist.
7475 /* Always do lstat for UNIX calls. */
7476 SMB_VFS_LSTAT(conn, smb_fname);
7478 } else if (!VALID_STAT(smb_fname->st) &&
7479 SMB_VFS_STAT(conn, smb_fname)) {
7480 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7482 smb_fname_str_dbg(smb_fname),
7484 reply_nterror(req, map_nt_error_from_unix(errno));
7489 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7490 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
7491 fsp ? fsp->fnum : -1, info_level,total_data));
7493 /* Realloc the parameter size */
7494 *pparams = (char *)SMB_REALLOC(*pparams,2);
7495 if (*pparams == NULL) {
7496 reply_nterror(req, NT_STATUS_NO_MEMORY);
7503 status = smbd_do_setfilepathinfo(conn, req, req,
7509 if (!NT_STATUS_IS_OK(status)) {
7510 if (open_was_deferred(req->mid)) {
7511 /* We have re-scheduled this call. */
7514 if (blocking_lock_was_deferred(req->mid)) {
7515 /* We have re-scheduled this call. */
7518 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7519 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7520 ERRSRV, ERRbadpath);
7523 if (info_level == SMB_POSIX_PATH_OPEN) {
7524 reply_openerror(req, status);
7528 reply_nterror(req, status);
7532 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7538 /****************************************************************************
7539 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7540 ****************************************************************************/
7542 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7543 char **pparams, int total_params,
7544 char **ppdata, int total_data,
7545 unsigned int max_data_bytes)
7547 struct smb_filename *smb_dname = NULL;
7548 char *params = *pparams;
7549 char *pdata = *ppdata;
7550 char *directory = NULL;
7551 NTSTATUS status = NT_STATUS_OK;
7552 struct ea_list *ea_list = NULL;
7553 TALLOC_CTX *ctx = talloc_tos();
7555 if (!CAN_WRITE(conn)) {
7556 reply_doserror(req, ERRSRV, ERRaccess);
7560 if (total_params < 5) {
7561 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7565 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7566 total_params - 4, STR_TERMINATE,
7568 if (!NT_STATUS_IS_OK(status)) {
7569 reply_nterror(req, status);
7573 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7575 status = filename_convert(ctx,
7577 req->flags2 & FLAGS2_DFS_PATHNAMES,
7583 if (!NT_STATUS_IS_OK(status)) {
7584 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7585 reply_botherror(req,
7586 NT_STATUS_PATH_NOT_COVERED,
7587 ERRSRV, ERRbadpath);
7590 reply_nterror(req, status);
7594 /* Any data in this call is an EA list. */
7595 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7596 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7601 * OS/2 workplace shell seems to send SET_EA requests of "null"
7602 * length (4 bytes containing IVAL 4).
7603 * They seem to have no effect. Bug #3212. JRA.
7606 if (total_data != 4) {
7607 if (total_data < 10) {
7608 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7612 if (IVAL(pdata,0) > total_data) {
7613 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7614 IVAL(pdata,0), (unsigned int)total_data));
7615 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7619 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7622 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7626 /* If total_data == 4 Windows doesn't care what values
7627 * are placed in that field, it just ignores them.
7628 * The System i QNTC IBM SMB client puts bad values here,
7629 * so ignore them. */
7631 status = create_directory(conn, req, smb_dname);
7633 if (!NT_STATUS_IS_OK(status)) {
7634 reply_nterror(req, status);
7638 /* Try and set any given EA. */
7640 status = set_ea(conn, NULL, smb_dname, ea_list);
7641 if (!NT_STATUS_IS_OK(status)) {
7642 reply_nterror(req, status);
7647 /* Realloc the parameter and data sizes */
7648 *pparams = (char *)SMB_REALLOC(*pparams,2);
7649 if(*pparams == NULL) {
7650 reply_nterror(req, NT_STATUS_NO_MEMORY);
7657 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7660 TALLOC_FREE(smb_dname);
7664 /****************************************************************************
7665 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7666 We don't actually do this - we just send a null response.
7667 ****************************************************************************/
7669 static void call_trans2findnotifyfirst(connection_struct *conn,
7670 struct smb_request *req,
7671 char **pparams, int total_params,
7672 char **ppdata, int total_data,
7673 unsigned int max_data_bytes)
7675 char *params = *pparams;
7678 if (total_params < 6) {
7679 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7683 info_level = SVAL(params,4);
7684 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7686 switch (info_level) {
7691 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7695 /* Realloc the parameter and data sizes */
7696 *pparams = (char *)SMB_REALLOC(*pparams,6);
7697 if (*pparams == NULL) {
7698 reply_nterror(req, NT_STATUS_NO_MEMORY);
7703 SSVAL(params,0,fnf_handle);
7704 SSVAL(params,2,0); /* No changes */
7705 SSVAL(params,4,0); /* No EA errors */
7712 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7717 /****************************************************************************
7718 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7719 changes). Currently this does nothing.
7720 ****************************************************************************/
7722 static void call_trans2findnotifynext(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;
7730 DEBUG(3,("call_trans2findnotifynext\n"));
7732 /* Realloc the parameter and data sizes */
7733 *pparams = (char *)SMB_REALLOC(*pparams,4);
7734 if (*pparams == NULL) {
7735 reply_nterror(req, NT_STATUS_NO_MEMORY);
7740 SSVAL(params,0,0); /* No changes */
7741 SSVAL(params,2,0); /* No EA errors */
7743 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7748 /****************************************************************************
7749 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7750 ****************************************************************************/
7752 static void call_trans2getdfsreferral(connection_struct *conn,
7753 struct smb_request *req,
7754 char **pparams, int total_params,
7755 char **ppdata, int total_data,
7756 unsigned int max_data_bytes)
7758 char *params = *pparams;
7759 char *pathname = NULL;
7761 int max_referral_level;
7762 NTSTATUS status = NT_STATUS_OK;
7763 TALLOC_CTX *ctx = talloc_tos();
7765 DEBUG(10,("call_trans2getdfsreferral\n"));
7767 if (total_params < 3) {
7768 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7772 max_referral_level = SVAL(params,0);
7774 if(!lp_host_msdfs()) {
7775 reply_doserror(req, ERRDOS, ERRbadfunc);
7779 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7780 total_params - 2, STR_TERMINATE);
7782 reply_nterror(req, NT_STATUS_NOT_FOUND);
7785 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7786 ppdata,&status)) < 0) {
7787 reply_nterror(req, status);
7791 SSVAL(req->inbuf, smb_flg2,
7792 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7793 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7798 #define LMCAT_SPL 0x53
7799 #define LMFUNC_GETJOBID 0x60
7801 /****************************************************************************
7802 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7803 ****************************************************************************/
7805 static void call_trans2ioctl(connection_struct *conn,
7806 struct smb_request *req,
7807 char **pparams, int total_params,
7808 char **ppdata, int total_data,
7809 unsigned int max_data_bytes)
7811 char *pdata = *ppdata;
7812 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7814 /* check for an invalid fid before proceeding */
7817 reply_doserror(req, ERRDOS, ERRbadfid);
7821 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7822 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7823 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7824 if (*ppdata == NULL) {
7825 reply_nterror(req, NT_STATUS_NO_MEMORY);
7830 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7831 CAN ACCEPT THIS IN UNICODE. JRA. */
7833 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7834 srvstr_push(pdata, req->flags2, pdata + 2,
7835 global_myname(), 15,
7836 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7837 srvstr_push(pdata, req->flags2, pdata+18,
7838 lp_servicename(SNUM(conn)), 13,
7839 STR_ASCII|STR_TERMINATE); /* Service name */
7840 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7845 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7846 reply_doserror(req, ERRSRV, ERRerror);
7849 /****************************************************************************
7850 Reply to a SMBfindclose (stop trans2 directory search).
7851 ****************************************************************************/
7853 void reply_findclose(struct smb_request *req)
7856 struct smbd_server_connection *sconn = smbd_server_conn;
7858 START_PROFILE(SMBfindclose);
7861 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7862 END_PROFILE(SMBfindclose);
7866 dptr_num = SVALS(req->vwv+0, 0);
7868 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7870 dptr_close(sconn, &dptr_num);
7872 reply_outbuf(req, 0, 0);
7874 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7876 END_PROFILE(SMBfindclose);
7880 /****************************************************************************
7881 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7882 ****************************************************************************/
7884 void reply_findnclose(struct smb_request *req)
7888 START_PROFILE(SMBfindnclose);
7891 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7892 END_PROFILE(SMBfindnclose);
7896 dptr_num = SVAL(req->vwv+0, 0);
7898 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7900 /* We never give out valid handles for a
7901 findnotifyfirst - so any dptr_num is ok here.
7904 reply_outbuf(req, 0, 0);
7906 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7908 END_PROFILE(SMBfindnclose);
7912 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7913 struct trans_state *state)
7915 if (Protocol >= PROTOCOL_NT1) {
7916 req->flags2 |= 0x40; /* IS_LONG_NAME */
7917 SSVAL(req->inbuf,smb_flg2,req->flags2);
7920 if (conn->encrypt_level == Required && !req->encrypted) {
7921 if (state->call != TRANSACT2_QFSINFO &&
7922 state->call != TRANSACT2_SETFSINFO) {
7923 DEBUG(0,("handle_trans2: encryption required "
7925 (unsigned int)state->call));
7926 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7931 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
7933 /* Now we must call the relevant TRANS2 function */
7934 switch(state->call) {
7935 case TRANSACT2_OPEN:
7937 START_PROFILE(Trans2_open);
7938 call_trans2open(conn, req,
7939 &state->param, state->total_param,
7940 &state->data, state->total_data,
7941 state->max_data_return);
7942 END_PROFILE(Trans2_open);
7946 case TRANSACT2_FINDFIRST:
7948 START_PROFILE(Trans2_findfirst);
7949 call_trans2findfirst(conn, req,
7950 &state->param, state->total_param,
7951 &state->data, state->total_data,
7952 state->max_data_return);
7953 END_PROFILE(Trans2_findfirst);
7957 case TRANSACT2_FINDNEXT:
7959 START_PROFILE(Trans2_findnext);
7960 call_trans2findnext(conn, req,
7961 &state->param, state->total_param,
7962 &state->data, state->total_data,
7963 state->max_data_return);
7964 END_PROFILE(Trans2_findnext);
7968 case TRANSACT2_QFSINFO:
7970 START_PROFILE(Trans2_qfsinfo);
7971 call_trans2qfsinfo(conn, req,
7972 &state->param, state->total_param,
7973 &state->data, state->total_data,
7974 state->max_data_return);
7975 END_PROFILE(Trans2_qfsinfo);
7979 case TRANSACT2_SETFSINFO:
7981 START_PROFILE(Trans2_setfsinfo);
7982 call_trans2setfsinfo(conn, req,
7983 &state->param, state->total_param,
7984 &state->data, state->total_data,
7985 state->max_data_return);
7986 END_PROFILE(Trans2_setfsinfo);
7990 case TRANSACT2_QPATHINFO:
7991 case TRANSACT2_QFILEINFO:
7993 START_PROFILE(Trans2_qpathinfo);
7994 call_trans2qfilepathinfo(conn, req, state->call,
7995 &state->param, state->total_param,
7996 &state->data, state->total_data,
7997 state->max_data_return);
7998 END_PROFILE(Trans2_qpathinfo);
8002 case TRANSACT2_SETPATHINFO:
8003 case TRANSACT2_SETFILEINFO:
8005 START_PROFILE(Trans2_setpathinfo);
8006 call_trans2setfilepathinfo(conn, req, state->call,
8007 &state->param, state->total_param,
8008 &state->data, state->total_data,
8009 state->max_data_return);
8010 END_PROFILE(Trans2_setpathinfo);
8014 case TRANSACT2_FINDNOTIFYFIRST:
8016 START_PROFILE(Trans2_findnotifyfirst);
8017 call_trans2findnotifyfirst(conn, req,
8018 &state->param, state->total_param,
8019 &state->data, state->total_data,
8020 state->max_data_return);
8021 END_PROFILE(Trans2_findnotifyfirst);
8025 case TRANSACT2_FINDNOTIFYNEXT:
8027 START_PROFILE(Trans2_findnotifynext);
8028 call_trans2findnotifynext(conn, req,
8029 &state->param, state->total_param,
8030 &state->data, state->total_data,
8031 state->max_data_return);
8032 END_PROFILE(Trans2_findnotifynext);
8036 case TRANSACT2_MKDIR:
8038 START_PROFILE(Trans2_mkdir);
8039 call_trans2mkdir(conn, req,
8040 &state->param, state->total_param,
8041 &state->data, state->total_data,
8042 state->max_data_return);
8043 END_PROFILE(Trans2_mkdir);
8047 case TRANSACT2_GET_DFS_REFERRAL:
8049 START_PROFILE(Trans2_get_dfs_referral);
8050 call_trans2getdfsreferral(conn, req,
8051 &state->param, state->total_param,
8052 &state->data, state->total_data,
8053 state->max_data_return);
8054 END_PROFILE(Trans2_get_dfs_referral);
8058 case TRANSACT2_IOCTL:
8060 START_PROFILE(Trans2_ioctl);
8061 call_trans2ioctl(conn, req,
8062 &state->param, state->total_param,
8063 &state->data, state->total_data,
8064 state->max_data_return);
8065 END_PROFILE(Trans2_ioctl);
8070 /* Error in request */
8071 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8072 reply_doserror(req, ERRSRV,ERRerror);
8076 /****************************************************************************
8077 Reply to a SMBtrans2.
8078 ****************************************************************************/
8080 void reply_trans2(struct smb_request *req)
8082 connection_struct *conn = req->conn;
8087 unsigned int tran_call;
8088 struct trans_state *state;
8091 START_PROFILE(SMBtrans2);
8093 if (req->wct < 14) {
8094 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8095 END_PROFILE(SMBtrans2);
8099 dsoff = SVAL(req->vwv+12, 0);
8100 dscnt = SVAL(req->vwv+11, 0);
8101 psoff = SVAL(req->vwv+10, 0);
8102 pscnt = SVAL(req->vwv+9, 0);
8103 tran_call = SVAL(req->vwv+14, 0);
8105 result = allow_new_trans(conn->pending_trans, req->mid);
8106 if (!NT_STATUS_IS_OK(result)) {
8107 DEBUG(2, ("Got invalid trans2 request: %s\n",
8108 nt_errstr(result)));
8109 reply_nterror(req, result);
8110 END_PROFILE(SMBtrans2);
8115 switch (tran_call) {
8116 /* List the allowed trans2 calls on IPC$ */
8117 case TRANSACT2_OPEN:
8118 case TRANSACT2_GET_DFS_REFERRAL:
8119 case TRANSACT2_QFILEINFO:
8120 case TRANSACT2_QFSINFO:
8121 case TRANSACT2_SETFSINFO:
8124 reply_doserror(req, ERRSRV, ERRaccess);
8125 END_PROFILE(SMBtrans2);
8130 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8131 DEBUG(0, ("talloc failed\n"));
8132 reply_nterror(req, NT_STATUS_NO_MEMORY);
8133 END_PROFILE(SMBtrans2);
8137 state->cmd = SMBtrans2;
8139 state->mid = req->mid;
8140 state->vuid = req->vuid;
8141 state->setup_count = SVAL(req->vwv+13, 0);
8142 state->setup = NULL;
8143 state->total_param = SVAL(req->vwv+0, 0);
8144 state->param = NULL;
8145 state->total_data = SVAL(req->vwv+1, 0);
8147 state->max_param_return = SVAL(req->vwv+2, 0);
8148 state->max_data_return = SVAL(req->vwv+3, 0);
8149 state->max_setup_return = SVAL(req->vwv+4, 0);
8150 state->close_on_completion = BITSETW(req->vwv+5, 0);
8151 state->one_way = BITSETW(req->vwv+5, 1);
8153 state->call = tran_call;
8155 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8156 is so as a sanity check */
8157 if (state->setup_count != 1) {
8159 * Need to have rc=0 for ioctl to get job id for OS/2.
8160 * Network printing will fail if function is not successful.
8161 * Similar function in reply.c will be used if protocol
8162 * is LANMAN1.0 instead of LM1.2X002.
8163 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8164 * outbuf doesn't have to be set(only job id is used).
8166 if ( (state->setup_count == 4)
8167 && (tran_call == TRANSACT2_IOCTL)
8168 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8169 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8170 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8172 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8173 DEBUG(2,("Transaction is %d\n",tran_call));
8175 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8176 END_PROFILE(SMBtrans2);
8181 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8184 if (state->total_data) {
8186 if (trans_oob(state->total_data, 0, dscnt)
8187 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8191 /* Can't use talloc here, the core routines do realloc on the
8192 * params and data. */
8193 state->data = (char *)SMB_MALLOC(state->total_data);
8194 if (state->data == NULL) {
8195 DEBUG(0,("reply_trans2: data malloc fail for %u "
8196 "bytes !\n", (unsigned int)state->total_data));
8198 reply_nterror(req, NT_STATUS_NO_MEMORY);
8199 END_PROFILE(SMBtrans2);
8203 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8206 if (state->total_param) {
8208 if (trans_oob(state->total_param, 0, pscnt)
8209 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8213 /* Can't use talloc here, the core routines do realloc on the
8214 * params and data. */
8215 state->param = (char *)SMB_MALLOC(state->total_param);
8216 if (state->param == NULL) {
8217 DEBUG(0,("reply_trans: param malloc fail for %u "
8218 "bytes !\n", (unsigned int)state->total_param));
8219 SAFE_FREE(state->data);
8221 reply_nterror(req, NT_STATUS_NO_MEMORY);
8222 END_PROFILE(SMBtrans2);
8226 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8229 state->received_data = dscnt;
8230 state->received_param = pscnt;
8232 if ((state->received_param == state->total_param) &&
8233 (state->received_data == state->total_data)) {
8235 handle_trans2(conn, req, state);
8237 SAFE_FREE(state->data);
8238 SAFE_FREE(state->param);
8240 END_PROFILE(SMBtrans2);
8244 DLIST_ADD(conn->pending_trans, state);
8246 /* We need to send an interim response then receive the rest
8247 of the parameter/data bytes */
8248 reply_outbuf(req, 0, 0);
8249 show_msg((char *)req->outbuf);
8250 END_PROFILE(SMBtrans2);
8255 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8256 SAFE_FREE(state->data);
8257 SAFE_FREE(state->param);
8259 END_PROFILE(SMBtrans2);
8260 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8264 /****************************************************************************
8265 Reply to a SMBtranss2
8266 ****************************************************************************/
8268 void reply_transs2(struct smb_request *req)
8270 connection_struct *conn = req->conn;
8271 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8272 struct trans_state *state;
8274 START_PROFILE(SMBtranss2);
8276 show_msg((char *)req->inbuf);
8279 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8280 END_PROFILE(SMBtranss2);
8284 for (state = conn->pending_trans; state != NULL;
8285 state = state->next) {
8286 if (state->mid == req->mid) {
8291 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8292 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8293 END_PROFILE(SMBtranss2);
8297 /* Revise state->total_param and state->total_data in case they have
8298 changed downwards */
8300 if (SVAL(req->vwv+0, 0) < state->total_param)
8301 state->total_param = SVAL(req->vwv+0, 0);
8302 if (SVAL(req->vwv+1, 0) < state->total_data)
8303 state->total_data = SVAL(req->vwv+1, 0);
8305 pcnt = SVAL(req->vwv+2, 0);
8306 poff = SVAL(req->vwv+3, 0);
8307 pdisp = SVAL(req->vwv+4, 0);
8309 dcnt = SVAL(req->vwv+5, 0);
8310 doff = SVAL(req->vwv+6, 0);
8311 ddisp = SVAL(req->vwv+7, 0);
8313 state->received_param += pcnt;
8314 state->received_data += dcnt;
8316 if ((state->received_data > state->total_data) ||
8317 (state->received_param > state->total_param))
8321 if (trans_oob(state->total_param, pdisp, pcnt)
8322 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8325 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8329 if (trans_oob(state->total_data, ddisp, dcnt)
8330 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8333 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8336 if ((state->received_param < state->total_param) ||
8337 (state->received_data < state->total_data)) {
8338 END_PROFILE(SMBtranss2);
8342 handle_trans2(conn, req, state);
8344 DLIST_REMOVE(conn->pending_trans, state);
8345 SAFE_FREE(state->data);
8346 SAFE_FREE(state->param);
8349 END_PROFILE(SMBtranss2);
8354 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8355 DLIST_REMOVE(conn->pending_trans, state);
8356 SAFE_FREE(state->data);
8357 SAFE_FREE(state->param);
8359 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8360 END_PROFILE(SMBtranss2);