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,
75 SAMBA_XATTR_DOSTIMESTAMPS,
81 for (i = 0; prohibited_ea_names[i]; i++) {
82 if (strequal( prohibited_ea_names[i], unix_ea_name))
85 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
86 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
92 /****************************************************************************
93 Get one EA value. Fill in a struct ea_struct.
94 ****************************************************************************/
96 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
97 files_struct *fsp, const char *fname,
98 const char *ea_name, struct ea_struct *pea)
100 /* Get the value of this xattr. Max size is 64k. */
101 size_t attr_size = 256;
107 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
109 return NT_STATUS_NO_MEMORY;
112 if (fsp && fsp->fh->fd != -1) {
113 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
115 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
118 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
124 return map_nt_error_from_unix(errno);
127 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
128 dump_data(10, (uint8 *)val, sizeret);
131 if (strnequal(ea_name, "user.", 5)) {
132 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
134 pea->name = talloc_strdup(mem_ctx, ea_name);
136 if (pea->name == NULL) {
138 return NT_STATUS_NO_MEMORY;
140 pea->value.data = (unsigned char *)val;
141 pea->value.length = (size_t)sizeret;
145 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
146 files_struct *fsp, const char *fname,
147 char ***pnames, size_t *pnum_names)
149 /* Get a list of all xattrs. Max namesize is 64k. */
150 size_t ea_namelist_size = 1024;
151 char *ea_namelist = NULL;
156 ssize_t sizeret = -1;
158 if (!lp_ea_support(SNUM(conn))) {
165 * TALLOC the result early to get the talloc hierarchy right.
168 names = TALLOC_ARRAY(mem_ctx, char *, 1);
170 DEBUG(0, ("talloc failed\n"));
171 return NT_STATUS_NO_MEMORY;
174 while (ea_namelist_size <= 65536) {
176 ea_namelist = TALLOC_REALLOC_ARRAY(
177 names, ea_namelist, char, ea_namelist_size);
178 if (ea_namelist == NULL) {
179 DEBUG(0, ("talloc failed\n"));
181 return NT_STATUS_NO_MEMORY;
184 if (fsp && fsp->fh->fd != -1) {
185 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
188 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
192 if ((sizeret == -1) && (errno == ERANGE)) {
193 ea_namelist_size *= 2;
202 return map_nt_error_from_unix(errno);
205 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
206 (unsigned int)sizeret));
218 * Ensure the result is 0-terminated
221 if (ea_namelist[sizeret-1] != '\0') {
223 return NT_STATUS_INTERNAL_ERROR;
231 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
235 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
237 DEBUG(0, ("talloc failed\n"));
239 return NT_STATUS_NO_MEMORY;
245 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
246 names[num_names++] = p;
254 *pnum_names = num_names;
258 /****************************************************************************
259 Return a linked list of the total EA's. Plus the total size
260 ****************************************************************************/
262 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
263 const char *fname, size_t *pea_total_len)
265 /* Get a list of all xattrs. Max namesize is 64k. */
268 struct ea_list *ea_list_head = NULL;
273 if (!lp_ea_support(SNUM(conn))) {
277 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
280 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
284 for (i=0; i<num_names; i++) {
285 struct ea_list *listp;
288 if (strnequal(names[i], "system.", 7)
289 || samba_private_attr_name(names[i]))
292 listp = TALLOC_P(mem_ctx, struct ea_list);
297 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
303 push_ascii_fstring(dos_ea_name, listp->ea.name);
306 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
308 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
309 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
310 (unsigned int)listp->ea.value.length));
312 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
316 /* Add on 4 for total length. */
317 if (*pea_total_len) {
321 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
322 (unsigned int)*pea_total_len));
327 /****************************************************************************
328 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
330 ****************************************************************************/
332 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
333 connection_struct *conn, struct ea_list *ea_list)
335 unsigned int ret_data_size = 4;
338 SMB_ASSERT(total_data_size >= 4);
340 if (!lp_ea_support(SNUM(conn))) {
345 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
348 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
349 dos_namelen = strlen(dos_ea_name);
350 if (dos_namelen > 255 || dos_namelen == 0) {
353 if (ea_list->ea.value.length > 65535) {
356 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
360 /* We know we have room. */
361 SCVAL(p,0,ea_list->ea.flags);
362 SCVAL(p,1,dos_namelen);
363 SSVAL(p,2,ea_list->ea.value.length);
364 fstrcpy(p+4, dos_ea_name);
365 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
367 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
368 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
371 ret_data_size = PTR_DIFF(p, pdata);
372 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
373 SIVAL(pdata,0,ret_data_size);
374 return ret_data_size;
377 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
379 unsigned int total_data_size,
380 unsigned int *ret_data_size,
381 connection_struct *conn,
382 struct ea_list *ea_list)
384 uint8_t *p = (uint8_t *)pdata;
385 uint8_t *last_start = NULL;
389 if (!lp_ea_support(SNUM(conn))) {
390 return NT_STATUS_NO_EAS_ON_FILE;
393 for (; ea_list; ea_list = ea_list->next) {
399 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
403 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
404 dos_namelen = strlen(dos_ea_name);
405 if (dos_namelen > 255 || dos_namelen == 0) {
406 return NT_STATUS_INTERNAL_ERROR;
408 if (ea_list->ea.value.length > 65535) {
409 return NT_STATUS_INTERNAL_ERROR;
412 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
415 size_t pad = 4 - (this_size % 4);
419 if (this_size > total_data_size) {
420 return NT_STATUS_INFO_LENGTH_MISMATCH;
423 /* We know we have room. */
424 SIVAL(p, 0x00, 0); /* next offset */
425 SCVAL(p, 0x04, ea_list->ea.flags);
426 SCVAL(p, 0x05, dos_namelen);
427 SSVAL(p, 0x06, ea_list->ea.value.length);
428 fstrcpy((char *)(p+0x08), dos_ea_name);
429 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
431 total_data_size -= this_size;
435 *ret_data_size = PTR_DIFF(p, pdata);
436 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
440 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
442 size_t total_ea_len = 0;
443 TALLOC_CTX *mem_ctx = NULL;
445 if (!lp_ea_support(SNUM(conn))) {
448 mem_ctx = talloc_tos();
449 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
453 /****************************************************************************
454 Ensure the EA name is case insensitive by matching any existing EA name.
455 ****************************************************************************/
457 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
460 TALLOC_CTX *mem_ctx = talloc_tos();
461 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
463 for (; ea_list; ea_list = ea_list->next) {
464 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
465 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
466 &unix_ea_name[5], ea_list->ea.name));
467 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
473 /****************************************************************************
474 Set or delete an extended attribute.
475 ****************************************************************************/
477 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
478 const struct smb_filename *smb_fname, struct ea_list *ea_list)
482 if (!lp_ea_support(SNUM(conn))) {
483 return NT_STATUS_EAS_NOT_SUPPORTED;
486 /* For now setting EAs on streams isn't supported. */
487 fname = smb_fname->base_name;
489 for (;ea_list; ea_list = ea_list->next) {
491 fstring unix_ea_name;
493 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
494 fstrcat(unix_ea_name, ea_list->ea.name);
496 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
498 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
500 if (samba_private_attr_name(unix_ea_name)) {
501 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
502 return NT_STATUS_ACCESS_DENIED;
505 if (ea_list->ea.value.length == 0) {
506 /* Remove the attribute. */
507 if (fsp && (fsp->fh->fd != -1)) {
508 DEBUG(10,("set_ea: deleting ea name %s on "
509 "file %s by file descriptor.\n",
510 unix_ea_name, fsp_str_dbg(fsp)));
511 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
513 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
514 unix_ea_name, fname));
515 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
518 /* Removing a non existent attribute always succeeds. */
519 if (ret == -1 && errno == ENOATTR) {
520 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
526 if (fsp && (fsp->fh->fd != -1)) {
527 DEBUG(10,("set_ea: setting ea name %s on file "
528 "%s by file descriptor.\n",
529 unix_ea_name, fsp_str_dbg(fsp)));
530 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
531 ea_list->ea.value.data, ea_list->ea.value.length, 0);
533 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
534 unix_ea_name, fname));
535 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
536 ea_list->ea.value.data, ea_list->ea.value.length, 0);
542 if (errno == ENOTSUP) {
543 return NT_STATUS_EAS_NOT_SUPPORTED;
546 return map_nt_error_from_unix(errno);
552 /****************************************************************************
553 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
554 ****************************************************************************/
556 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
558 struct ea_list *ea_list_head = NULL;
559 size_t converted_size, offset = 0;
561 while (offset + 2 < data_size) {
562 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
563 unsigned int namelen = CVAL(pdata,offset);
565 offset++; /* Go past the namelen byte. */
567 /* integer wrap paranioa. */
568 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
569 (offset > data_size) || (namelen > data_size) ||
570 (offset + namelen >= data_size)) {
573 /* Ensure the name is null terminated. */
574 if (pdata[offset + namelen] != '\0') {
577 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
579 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
580 "failed: %s", strerror(errno)));
586 offset += (namelen + 1); /* Go past the name + terminating zero. */
587 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
588 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
594 /****************************************************************************
595 Read one EA list entry from the buffer.
596 ****************************************************************************/
598 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
600 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
602 unsigned int namelen;
603 size_t converted_size;
613 eal->ea.flags = CVAL(pdata,0);
614 namelen = CVAL(pdata,1);
615 val_len = SVAL(pdata,2);
617 if (4 + namelen + 1 + val_len > data_size) {
621 /* Ensure the name is null terminated. */
622 if (pdata[namelen + 4] != '\0') {
625 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
626 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
633 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
634 if (!eal->ea.value.data) {
638 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
640 /* Ensure we're null terminated just in case we print the value. */
641 eal->ea.value.data[val_len] = '\0';
642 /* But don't count the null. */
643 eal->ea.value.length--;
646 *pbytes_used = 4 + namelen + 1 + val_len;
649 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
650 dump_data(10, eal->ea.value.data, eal->ea.value.length);
655 /****************************************************************************
656 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
657 ****************************************************************************/
659 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
661 struct ea_list *ea_list_head = NULL;
663 size_t bytes_used = 0;
665 while (offset < data_size) {
666 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
672 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
673 offset += bytes_used;
679 /****************************************************************************
680 Count the total EA size needed.
681 ****************************************************************************/
683 static size_t ea_list_size(struct ea_list *ealist)
686 struct ea_list *listp;
689 for (listp = ealist; listp; listp = listp->next) {
690 push_ascii_fstring(dos_ea_name, listp->ea.name);
691 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
693 /* Add on 4 for total length. */
701 /****************************************************************************
702 Return a union of EA's from a file list and a list of names.
703 The TALLOC context for the two lists *MUST* be identical as we steal
704 memory from one list to add to another. JRA.
705 ****************************************************************************/
707 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
709 struct ea_list *nlistp, *flistp;
711 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
712 for (flistp = file_list; flistp; flistp = flistp->next) {
713 if (strequal(nlistp->ea.name, flistp->ea.name)) {
719 /* Copy the data from this entry. */
720 nlistp->ea.flags = flistp->ea.flags;
721 nlistp->ea.value = flistp->ea.value;
724 nlistp->ea.flags = 0;
725 ZERO_STRUCT(nlistp->ea.value);
729 *total_ea_len = ea_list_size(name_list);
733 /****************************************************************************
734 Send the required number of replies back.
735 We assume all fields other than the data fields are
736 set correctly for the type of call.
737 HACK ! Always assumes smb_setup field is zero.
738 ****************************************************************************/
740 void send_trans2_replies(connection_struct *conn,
741 struct smb_request *req,
748 /* As we are using a protocol > LANMAN1 then the max_send
749 variable must have been set in the sessetupX call.
750 This takes precedence over the max_xmit field in the
751 global struct. These different max_xmit variables should
752 be merged as this is now too confusing */
754 int data_to_send = datasize;
755 int params_to_send = paramsize;
757 const char *pp = params;
758 const char *pd = pdata;
759 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
760 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
761 int data_alignment_offset = 0;
762 bool overflow = False;
763 struct smbd_server_connection *sconn = smbd_server_conn;
764 int max_send = sconn->smb1.sessions.max_send;
766 /* Modify the data_to_send and datasize and set the error if
767 we're trying to send more than max_data_bytes. We still send
768 the part of the packet(s) that fit. Strange, but needed
771 if (max_data_bytes > 0 && datasize > max_data_bytes) {
772 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
773 max_data_bytes, datasize ));
774 datasize = data_to_send = max_data_bytes;
778 /* If there genuinely are no parameters or data to send just send the empty packet */
780 if(params_to_send == 0 && data_to_send == 0) {
781 reply_outbuf(req, 10, 0);
782 show_msg((char *)req->outbuf);
783 if (!srv_send_smb(smbd_server_fd(),
786 IS_CONN_ENCRYPTED(conn),
788 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
790 TALLOC_FREE(req->outbuf);
794 /* When sending params and data ensure that both are nicely aligned */
795 /* Only do this alignment when there is also data to send - else
796 can cause NT redirector problems. */
798 if (((params_to_send % 4) != 0) && (data_to_send != 0))
799 data_alignment_offset = 4 - (params_to_send % 4);
801 /* Space is bufsize minus Netbios over TCP header minus SMB header */
802 /* The alignment_offset is to align the param bytes on an even byte
803 boundary. NT 4.0 Beta needs this to work correctly. */
805 useable_space = max_send - (smb_size
808 + data_alignment_offset);
810 if (useable_space < 0) {
811 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
812 "= %d!!!", useable_space));
813 exit_server_cleanly("send_trans2_replies: Not enough space");
816 while (params_to_send || data_to_send) {
817 /* Calculate whether we will totally or partially fill this packet */
819 total_sent_thistime = params_to_send + data_to_send;
821 /* We can never send more than useable_space */
823 * Note that 'useable_space' does not include the alignment offsets,
824 * but we must include the alignment offsets in the calculation of
825 * the length of the data we send over the wire, as the alignment offsets
826 * are sent here. Fix from Marc_Jacobsen@hp.com.
829 total_sent_thistime = MIN(total_sent_thistime, useable_space);
831 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
832 + data_alignment_offset);
835 * We might have SMBtrans2s in req which was transferred to
836 * the outbuf, fix that.
838 SCVAL(req->outbuf, smb_com, SMBtrans2);
840 /* Set total params and data to be sent */
841 SSVAL(req->outbuf,smb_tprcnt,paramsize);
842 SSVAL(req->outbuf,smb_tdrcnt,datasize);
844 /* Calculate how many parameters and data we can fit into
845 * this packet. Parameters get precedence
848 params_sent_thistime = MIN(params_to_send,useable_space);
849 data_sent_thistime = useable_space - params_sent_thistime;
850 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
852 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
854 /* smb_proff is the offset from the start of the SMB header to the
855 parameter bytes, however the first 4 bytes of outbuf are
856 the Netbios over TCP header. Thus use smb_base() to subtract
857 them from the calculation */
859 SSVAL(req->outbuf,smb_proff,
860 ((smb_buf(req->outbuf)+alignment_offset)
861 - smb_base(req->outbuf)));
863 if(params_sent_thistime == 0)
864 SSVAL(req->outbuf,smb_prdisp,0);
866 /* Absolute displacement of param bytes sent in this packet */
867 SSVAL(req->outbuf,smb_prdisp,pp - params);
869 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
870 if(data_sent_thistime == 0) {
871 SSVAL(req->outbuf,smb_droff,0);
872 SSVAL(req->outbuf,smb_drdisp, 0);
874 /* The offset of the data bytes is the offset of the
875 parameter bytes plus the number of parameters being sent this time */
876 SSVAL(req->outbuf, smb_droff,
877 ((smb_buf(req->outbuf)+alignment_offset)
878 - smb_base(req->outbuf))
879 + params_sent_thistime + data_alignment_offset);
880 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
883 /* Initialize the padding for alignment */
885 if (alignment_offset != 0) {
886 memset(smb_buf(req->outbuf), 0, alignment_offset);
889 /* Copy the param bytes into the packet */
891 if(params_sent_thistime) {
892 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
893 params_sent_thistime);
896 /* Copy in the data bytes */
897 if(data_sent_thistime) {
898 if (data_alignment_offset != 0) {
899 memset((smb_buf(req->outbuf)+alignment_offset+
900 params_sent_thistime), 0,
901 data_alignment_offset);
903 memcpy(smb_buf(req->outbuf)+alignment_offset
904 +params_sent_thistime+data_alignment_offset,
905 pd,data_sent_thistime);
908 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
909 params_sent_thistime, data_sent_thistime, useable_space));
910 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
911 params_to_send, data_to_send, paramsize, datasize));
914 error_packet_set((char *)req->outbuf,
915 ERRDOS,ERRbufferoverflow,
916 STATUS_BUFFER_OVERFLOW,
920 /* Send the packet */
921 show_msg((char *)req->outbuf);
922 if (!srv_send_smb(smbd_server_fd(),
925 IS_CONN_ENCRYPTED(conn),
927 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
929 TALLOC_FREE(req->outbuf);
931 pp += params_sent_thistime;
932 pd += data_sent_thistime;
934 params_to_send -= params_sent_thistime;
935 data_to_send -= data_sent_thistime;
938 if(params_to_send < 0 || data_to_send < 0) {
939 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
940 params_to_send, data_to_send));
948 /****************************************************************************
949 Reply to a TRANSACT2_OPEN.
950 ****************************************************************************/
952 static void call_trans2open(connection_struct *conn,
953 struct smb_request *req,
954 char **pparams, int total_params,
955 char **ppdata, int total_data,
956 unsigned int max_data_bytes)
958 struct smb_filename *smb_fname = NULL;
959 char *params = *pparams;
960 char *pdata = *ppdata;
965 bool return_additional_info;
978 struct ea_list *ea_list = NULL;
983 uint32 create_disposition;
984 uint32 create_options = 0;
985 TALLOC_CTX *ctx = talloc_tos();
988 * Ensure we have enough parameters to perform the operation.
991 if (total_params < 29) {
992 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
996 flags = SVAL(params, 0);
997 deny_mode = SVAL(params, 2);
998 open_attr = SVAL(params,6);
999 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1000 if (oplock_request) {
1001 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1005 return_additional_info = BITSETW(params,0);
1006 open_sattr = SVAL(params, 4);
1007 open_time = make_unix_date3(params+8);
1009 open_ofun = SVAL(params,12);
1010 open_size = IVAL(params,14);
1011 pname = ¶ms[28];
1014 reply_doserror(req, ERRSRV, ERRaccess);
1018 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1019 total_params - 28, STR_TERMINATE,
1021 if (!NT_STATUS_IS_OK(status)) {
1022 reply_nterror(req, status);
1026 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1027 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1028 (unsigned int)open_ofun, open_size));
1030 status = filename_convert(ctx,
1032 req->flags2 & FLAGS2_DFS_PATHNAMES,
1037 if (!NT_STATUS_IS_OK(status)) {
1038 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1039 reply_botherror(req,
1040 NT_STATUS_PATH_NOT_COVERED,
1041 ERRSRV, ERRbadpath);
1044 reply_nterror(req, status);
1048 if (open_ofun == 0) {
1049 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1053 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, open_ofun,
1054 &access_mask, &share_mode,
1055 &create_disposition,
1057 reply_doserror(req, ERRDOS, ERRbadaccess);
1061 /* Any data in this call is an EA list. */
1062 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
1063 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1067 if (total_data != 4) {
1068 if (total_data < 10) {
1069 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1073 if (IVAL(pdata,0) > total_data) {
1074 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1075 IVAL(pdata,0), (unsigned int)total_data));
1076 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1080 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1083 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1086 } else if (IVAL(pdata,0) != 4) {
1087 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1091 status = SMB_VFS_CREATE_FILE(
1094 0, /* root_dir_fid */
1095 smb_fname, /* fname */
1096 access_mask, /* access_mask */
1097 share_mode, /* share_access */
1098 create_disposition, /* create_disposition*/
1099 create_options, /* create_options */
1100 open_attr, /* file_attributes */
1101 oplock_request, /* oplock_request */
1102 open_size, /* allocation_size */
1104 ea_list, /* ea_list */
1106 &smb_action); /* psbuf */
1108 if (!NT_STATUS_IS_OK(status)) {
1109 if (open_was_deferred(req->mid)) {
1110 /* We have re-scheduled this call. */
1113 reply_openerror(req, status);
1117 size = get_file_size_stat(&smb_fname->st);
1118 fattr = dos_mode(conn, smb_fname);
1119 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1120 inode = smb_fname->st.st_ex_ino;
1122 close_file(req, fsp, ERROR_CLOSE);
1123 reply_doserror(req, ERRDOS,ERRnoaccess);
1127 /* Realloc the size of parameters and data we will return */
1128 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1129 if(*pparams == NULL ) {
1130 reply_nterror(req, NT_STATUS_NO_MEMORY);
1135 SSVAL(params,0,fsp->fnum);
1136 SSVAL(params,2,fattr);
1137 srv_put_dos_date2(params,4, mtime);
1138 SIVAL(params,8, (uint32)size);
1139 SSVAL(params,12,deny_mode);
1140 SSVAL(params,14,0); /* open_type - file or directory. */
1141 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1143 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1144 smb_action |= EXTENDED_OPLOCK_GRANTED;
1147 SSVAL(params,18,smb_action);
1150 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1152 SIVAL(params,20,inode);
1153 SSVAL(params,24,0); /* Padding. */
1155 uint32 ea_size = estimate_ea_size(conn, fsp,
1156 fsp->fsp_name->base_name);
1157 SIVAL(params, 26, ea_size);
1159 SIVAL(params, 26, 0);
1162 /* Send the required number of replies */
1163 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1165 TALLOC_FREE(smb_fname);
1168 /*********************************************************
1169 Routine to check if a given string matches exactly.
1170 as a special case a mask of "." does NOT match. That
1171 is required for correct wildcard semantics
1172 Case can be significant or not.
1173 **********************************************************/
1175 static bool exact_match(bool has_wild,
1176 bool case_sensitive,
1180 if (mask[0] == '.' && mask[1] == 0) {
1188 if (case_sensitive) {
1189 return strcmp(str,mask)==0;
1191 return StrCaseCmp(str,mask) == 0;
1195 /****************************************************************************
1196 Return the filetype for UNIX extensions.
1197 ****************************************************************************/
1199 static uint32 unix_filetype(mode_t mode)
1202 return UNIX_TYPE_FILE;
1203 else if(S_ISDIR(mode))
1204 return UNIX_TYPE_DIR;
1206 else if(S_ISLNK(mode))
1207 return UNIX_TYPE_SYMLINK;
1210 else if(S_ISCHR(mode))
1211 return UNIX_TYPE_CHARDEV;
1214 else if(S_ISBLK(mode))
1215 return UNIX_TYPE_BLKDEV;
1218 else if(S_ISFIFO(mode))
1219 return UNIX_TYPE_FIFO;
1222 else if(S_ISSOCK(mode))
1223 return UNIX_TYPE_SOCKET;
1226 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1227 return UNIX_TYPE_UNKNOWN;
1230 /****************************************************************************
1231 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1232 ****************************************************************************/
1234 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1236 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1237 const SMB_STRUCT_STAT *psbuf,
1239 enum perm_type ptype,
1244 if (perms == SMB_MODE_NO_CHANGE) {
1245 if (!VALID_STAT(*psbuf)) {
1246 return NT_STATUS_INVALID_PARAMETER;
1248 *ret_perms = psbuf->st_ex_mode;
1249 return NT_STATUS_OK;
1253 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1254 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1255 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1256 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1257 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1258 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1259 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1260 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1261 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1263 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1266 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1269 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1274 /* Apply mode mask */
1275 ret &= lp_create_mask(SNUM(conn));
1276 /* Add in force bits */
1277 ret |= lp_force_create_mode(SNUM(conn));
1280 ret &= lp_dir_mask(SNUM(conn));
1281 /* Add in force bits */
1282 ret |= lp_force_dir_mode(SNUM(conn));
1284 case PERM_EXISTING_FILE:
1285 /* Apply mode mask */
1286 ret &= lp_security_mask(SNUM(conn));
1287 /* Add in force bits */
1288 ret |= lp_force_security_mode(SNUM(conn));
1290 case PERM_EXISTING_DIR:
1291 /* Apply mode mask */
1292 ret &= lp_dir_security_mask(SNUM(conn));
1293 /* Add in force bits */
1294 ret |= lp_force_dir_security_mode(SNUM(conn));
1299 return NT_STATUS_OK;
1302 /****************************************************************************
1303 Needed to show the msdfs symlinks as directories. Modifies psbuf
1304 to be a directory if it's a msdfs link.
1305 ****************************************************************************/
1307 static bool check_msdfs_link(connection_struct *conn,
1308 const char *pathname,
1309 SMB_STRUCT_STAT *psbuf)
1311 int saved_errno = errno;
1312 if(lp_host_msdfs() &&
1313 lp_msdfs_root(SNUM(conn)) &&
1314 is_msdfs_link(conn, pathname, psbuf)) {
1316 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1319 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1320 errno = saved_errno;
1323 errno = saved_errno;
1328 /****************************************************************************
1329 Get a level dependent lanman2 dir entry.
1330 ****************************************************************************/
1332 struct smbd_dirptr_lanman2_state {
1333 connection_struct *conn;
1334 uint32_t info_level;
1335 bool check_mangled_names;
1337 bool got_exact_match;
1340 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1346 struct smbd_dirptr_lanman2_state *state =
1347 (struct smbd_dirptr_lanman2_state *)private_data;
1349 char mangled_name[13]; /* mangled 8.3 name. */
1353 /* Mangle fname if it's an illegal name. */
1354 if (mangle_must_mangle(dname, state->conn->params)) {
1355 ok = name_to_8_3(dname, mangled_name,
1356 true, state->conn->params);
1360 fname = mangled_name;
1365 got_match = exact_match(state->has_wild,
1366 state->conn->case_sensitive,
1368 state->got_exact_match = got_match;
1370 got_match = mask_match(fname, mask,
1371 state->conn->case_sensitive);
1374 if(!got_match && state->check_mangled_names &&
1375 !mangle_is_8_3(fname, false, state->conn->params)) {
1377 * It turns out that NT matches wildcards against
1378 * both long *and* short names. This may explain some
1379 * of the wildcard wierdness from old DOS clients
1380 * that some people have been seeing.... JRA.
1382 /* Force the mangling into 8.3. */
1383 ok = name_to_8_3(fname, mangled_name,
1384 false, state->conn->params);
1389 got_match = exact_match(state->has_wild,
1390 state->conn->case_sensitive,
1391 mangled_name, mask);
1392 state->got_exact_match = got_match;
1394 got_match = mask_match(mangled_name, mask,
1395 state->conn->case_sensitive);
1403 *_fname = talloc_strdup(ctx, fname);
1404 if (*_fname == NULL) {
1411 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1413 struct smb_filename *smb_fname,
1416 struct smbd_dirptr_lanman2_state *state =
1417 (struct smbd_dirptr_lanman2_state *)private_data;
1418 bool ms_dfs_link = false;
1421 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1422 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1423 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1424 "Couldn't lstat [%s] (%s)\n",
1425 smb_fname_str_dbg(smb_fname),
1429 } else if (!VALID_STAT(smb_fname->st) &&
1430 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1431 /* Needed to show the msdfs symlinks as
1434 ms_dfs_link = check_msdfs_link(state->conn,
1435 smb_fname->base_name,
1438 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1439 "Couldn't stat [%s] (%s)\n",
1440 smb_fname_str_dbg(smb_fname),
1447 mode = dos_mode_msdfs(state->conn, smb_fname);
1449 mode = dos_mode(state->conn, smb_fname);
1456 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1457 connection_struct *conn,
1459 uint32_t info_level,
1460 struct ea_list *name_list,
1461 bool check_mangled_names,
1462 bool requires_resume_key,
1465 const struct smb_filename *smb_fname,
1466 uint64_t space_remaining,
1473 uint64_t *last_entry_off)
1475 char *p, *q, *pdata = *ppdata;
1477 uint64_t file_size = 0;
1478 uint64_t allocation_size = 0;
1480 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1481 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1482 time_t c_date = (time_t)0;
1484 char *last_entry_ptr;
1486 uint32_t nt_extmode; /* Used for NT connections instead of mode */
1490 *out_of_space = false;
1492 ZERO_STRUCT(mdate_ts);
1493 ZERO_STRUCT(adate_ts);
1494 ZERO_STRUCT(create_date_ts);
1495 ZERO_STRUCT(cdate_ts);
1497 if (!(mode & aDIR)) {
1498 file_size = get_file_size_stat(&smb_fname->st);
1500 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1502 mdate_ts = smb_fname->st.st_ex_mtime;
1503 adate_ts = smb_fname->st.st_ex_atime;
1504 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1505 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1507 if (lp_dos_filetime_resolution(SNUM(conn))) {
1508 dos_filetime_timespec(&create_date_ts);
1509 dos_filetime_timespec(&mdate_ts);
1510 dos_filetime_timespec(&adate_ts);
1511 dos_filetime_timespec(&cdate_ts);
1514 create_date = convert_timespec_to_time_t(create_date_ts);
1515 mdate = convert_timespec_to_time_t(mdate_ts);
1516 adate = convert_timespec_to_time_t(adate_ts);
1517 c_date = convert_timespec_to_time_t(cdate_ts);
1519 /* align the record */
1520 off = PTR_DIFF(pdata, base_data);
1521 pad = (off + (align-1)) & ~(align-1);
1524 /* initialize padding to 0 */
1525 memset(pdata, 0, pad);
1526 space_remaining -= pad;
1535 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1537 switch (info_level) {
1538 case SMB_FIND_INFO_STANDARD:
1539 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1540 if(requires_resume_key) {
1544 srv_put_dos_date2(p,0,create_date);
1545 srv_put_dos_date2(p,4,adate);
1546 srv_put_dos_date2(p,8,mdate);
1547 SIVAL(p,12,(uint32)file_size);
1548 SIVAL(p,16,(uint32)allocation_size);
1552 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1553 p += ucs2_align(base_data, p, 0);
1555 len = srvstr_push(base_data, flags2, p,
1556 fname, PTR_DIFF(end_data, p),
1558 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1560 SCVAL(nameptr, -1, len - 2);
1562 SCVAL(nameptr, -1, 0);
1566 SCVAL(nameptr, -1, len - 1);
1568 SCVAL(nameptr, -1, 0);
1574 case SMB_FIND_EA_SIZE:
1575 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1576 if (requires_resume_key) {
1580 srv_put_dos_date2(p,0,create_date);
1581 srv_put_dos_date2(p,4,adate);
1582 srv_put_dos_date2(p,8,mdate);
1583 SIVAL(p,12,(uint32)file_size);
1584 SIVAL(p,16,(uint32)allocation_size);
1587 unsigned int ea_size = estimate_ea_size(conn, NULL,
1588 smb_fname->base_name);
1589 SIVAL(p,22,ea_size); /* Extended attributes */
1593 len = srvstr_push(base_data, flags2,
1594 p, fname, PTR_DIFF(end_data, p),
1595 STR_TERMINATE | STR_NOALIGN);
1596 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1609 SCVAL(nameptr,0,len);
1611 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1614 case SMB_FIND_EA_LIST:
1616 struct ea_list *file_list = NULL;
1619 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1623 if (requires_resume_key) {
1627 srv_put_dos_date2(p,0,create_date);
1628 srv_put_dos_date2(p,4,adate);
1629 srv_put_dos_date2(p,8,mdate);
1630 SIVAL(p,12,(uint32)file_size);
1631 SIVAL(p,16,(uint32)allocation_size);
1633 p += 22; /* p now points to the EA area. */
1635 file_list = get_ea_list_from_file(ctx, conn, NULL,
1636 smb_fname->base_name,
1638 name_list = ea_list_union(name_list, file_list, &ea_len);
1640 /* We need to determine if this entry will fit in the space available. */
1641 /* Max string size is 255 bytes. */
1642 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1643 *out_of_space = true;
1644 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1645 return False; /* Not finished - just out of space */
1648 /* Push the ea_data followed by the name. */
1649 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1651 len = srvstr_push(base_data, flags2,
1652 p + 1, fname, PTR_DIFF(end_data, p+1),
1653 STR_TERMINATE | STR_NOALIGN);
1654 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1667 SCVAL(nameptr,0,len);
1669 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1673 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1674 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1675 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1677 SIVAL(p,0,reskey); p += 4;
1678 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1679 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1680 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1681 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1682 SOFF_T(p,0,file_size); p += 8;
1683 SOFF_T(p,0,allocation_size); p += 8;
1684 SIVAL(p,0,nt_extmode); p += 4;
1685 q = p; p += 4; /* q is placeholder for name length. */
1687 unsigned int ea_size = estimate_ea_size(conn, NULL,
1688 smb_fname->base_name);
1689 SIVAL(p,0,ea_size); /* Extended attributes */
1692 /* Clear the short name buffer. This is
1693 * IMPORTANT as not doing so will trigger
1694 * a Win2k client bug. JRA.
1696 if (!was_8_3 && check_mangled_names) {
1697 char mangled_name[13]; /* mangled 8.3 name. */
1698 if (!name_to_8_3(fname,mangled_name,True,
1700 /* Error - mangle failed ! */
1701 memset(mangled_name,'\0',12);
1703 mangled_name[12] = 0;
1704 len = srvstr_push(base_data, flags2,
1705 p+2, mangled_name, 24,
1706 STR_UPPER|STR_UNICODE);
1708 memset(p + 2 + len,'\0',24 - len);
1715 len = srvstr_push(base_data, flags2, p,
1716 fname, PTR_DIFF(end_data, p),
1717 STR_TERMINATE_ASCII);
1721 len = PTR_DIFF(p, pdata);
1722 pad = (len + (align-1)) & ~(align-1);
1724 * offset to the next entry, the caller
1725 * will overwrite it for the last entry
1726 * that's why we always include the padding
1730 * set padding to zero
1733 memset(p, 0, pad - len);
1740 case SMB_FIND_FILE_DIRECTORY_INFO:
1741 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1743 SIVAL(p,0,reskey); p += 4;
1744 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1745 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1746 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1747 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1748 SOFF_T(p,0,file_size); p += 8;
1749 SOFF_T(p,0,allocation_size); p += 8;
1750 SIVAL(p,0,nt_extmode); p += 4;
1751 len = srvstr_push(base_data, flags2,
1752 p + 4, fname, PTR_DIFF(end_data, p+4),
1753 STR_TERMINATE_ASCII);
1757 len = PTR_DIFF(p, pdata);
1758 pad = (len + (align-1)) & ~(align-1);
1760 * offset to the next entry, the caller
1761 * will overwrite it for the last entry
1762 * that's why we always include the padding
1766 * set padding to zero
1769 memset(p, 0, pad - len);
1776 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1777 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1779 SIVAL(p,0,reskey); p += 4;
1780 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1781 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1782 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1783 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1784 SOFF_T(p,0,file_size); p += 8;
1785 SOFF_T(p,0,allocation_size); p += 8;
1786 SIVAL(p,0,nt_extmode); p += 4;
1787 q = p; p += 4; /* q is placeholder for name length. */
1789 unsigned int ea_size = estimate_ea_size(conn, NULL,
1790 smb_fname->base_name);
1791 SIVAL(p,0,ea_size); /* Extended attributes */
1794 len = srvstr_push(base_data, flags2, p,
1795 fname, PTR_DIFF(end_data, p),
1796 STR_TERMINATE_ASCII);
1800 len = PTR_DIFF(p, pdata);
1801 pad = (len + (align-1)) & ~(align-1);
1803 * offset to the next entry, the caller
1804 * will overwrite it for the last entry
1805 * that's why we always include the padding
1809 * set padding to zero
1812 memset(p, 0, pad - len);
1819 case SMB_FIND_FILE_NAMES_INFO:
1820 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1822 SIVAL(p,0,reskey); p += 4;
1824 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1825 acl on a dir (tridge) */
1826 len = srvstr_push(base_data, flags2, p,
1827 fname, PTR_DIFF(end_data, p),
1828 STR_TERMINATE_ASCII);
1832 len = PTR_DIFF(p, pdata);
1833 pad = (len + (align-1)) & ~(align-1);
1835 * offset to the next entry, the caller
1836 * will overwrite it for the last entry
1837 * that's why we always include the padding
1841 * set padding to zero
1844 memset(p, 0, pad - len);
1851 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1852 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1854 SIVAL(p,0,reskey); p += 4;
1855 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1856 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1857 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1858 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1859 SOFF_T(p,0,file_size); p += 8;
1860 SOFF_T(p,0,allocation_size); p += 8;
1861 SIVAL(p,0,nt_extmode); p += 4;
1862 q = p; p += 4; /* q is placeholder for name length. */
1864 unsigned int ea_size = estimate_ea_size(conn, NULL,
1865 smb_fname->base_name);
1866 SIVAL(p,0,ea_size); /* Extended attributes */
1869 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1870 SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
1871 SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
1872 len = srvstr_push(base_data, flags2, p,
1873 fname, PTR_DIFF(end_data, p),
1874 STR_TERMINATE_ASCII);
1878 len = PTR_DIFF(p, pdata);
1879 pad = (len + (align-1)) & ~(align-1);
1881 * offset to the next entry, the caller
1882 * will overwrite it for the last entry
1883 * that's why we always include the padding
1887 * set padding to zero
1890 memset(p, 0, pad - len);
1897 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1898 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1899 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1901 SIVAL(p,0,reskey); p += 4;
1902 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1903 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1904 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1905 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1906 SOFF_T(p,0,file_size); p += 8;
1907 SOFF_T(p,0,allocation_size); p += 8;
1908 SIVAL(p,0,nt_extmode); p += 4;
1909 q = p; p += 4; /* q is placeholder for name length */
1911 unsigned int ea_size = estimate_ea_size(conn, NULL,
1912 smb_fname->base_name);
1913 SIVAL(p,0,ea_size); /* Extended attributes */
1916 /* Clear the short name buffer. This is
1917 * IMPORTANT as not doing so will trigger
1918 * a Win2k client bug. JRA.
1920 if (!was_8_3 && check_mangled_names) {
1921 char mangled_name[13]; /* mangled 8.3 name. */
1922 if (!name_to_8_3(fname,mangled_name,True,
1924 /* Error - mangle failed ! */
1925 memset(mangled_name,'\0',12);
1927 mangled_name[12] = 0;
1928 len = srvstr_push(base_data, flags2,
1929 p+2, mangled_name, 24,
1930 STR_UPPER|STR_UNICODE);
1933 memset(p + 2 + len,'\0',24 - len);
1940 SSVAL(p,0,0); p += 2; /* Reserved ? */
1941 SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
1942 SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
1943 len = srvstr_push(base_data, flags2, p,
1944 fname, PTR_DIFF(end_data, p),
1945 STR_TERMINATE_ASCII);
1949 len = PTR_DIFF(p, pdata);
1950 pad = (len + (align-1)) & ~(align-1);
1952 * offset to the next entry, the caller
1953 * will overwrite it for the last entry
1954 * that's why we always include the padding
1958 * set padding to zero
1961 memset(p, 0, pad - len);
1968 /* CIFS UNIX Extension. */
1970 case SMB_FIND_FILE_UNIX:
1971 case SMB_FIND_FILE_UNIX_INFO2:
1973 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1975 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1977 if (info_level == SMB_FIND_FILE_UNIX) {
1978 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1979 p = store_file_unix_basic(conn, p,
1980 NULL, &smb_fname->st);
1981 len = srvstr_push(base_data, flags2, p,
1982 fname, PTR_DIFF(end_data, p),
1985 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1986 p = store_file_unix_basic_info2(conn, p,
1987 NULL, &smb_fname->st);
1990 len = srvstr_push(base_data, flags2, p, fname,
1991 PTR_DIFF(end_data, p), 0);
1992 SIVAL(nameptr, 0, len);
1997 len = PTR_DIFF(p, pdata);
1998 pad = (len + (align-1)) & ~(align-1);
2000 * offset to the next entry, the caller
2001 * will overwrite it for the last entry
2002 * that's why we always include the padding
2006 * set padding to zero
2009 memset(p, 0, pad - len);
2014 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2022 if (PTR_DIFF(p,pdata) > space_remaining) {
2023 *out_of_space = true;
2024 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
2025 return false; /* Not finished - just out of space */
2028 /* Setup the last entry pointer, as an offset from base_data */
2029 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2030 /* Advance the data pointer to the next slot */
2036 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2037 connection_struct *conn,
2038 struct dptr_struct *dirptr,
2040 const char *path_mask,
2043 int requires_resume_key,
2051 int space_remaining,
2053 bool *got_exact_match,
2054 int *_last_entry_off,
2055 struct ea_list *name_list)
2058 const char *mask = NULL;
2059 long prev_dirpos = 0;
2062 struct smb_filename *smb_fname = NULL;
2063 struct smbd_dirptr_lanman2_state state;
2065 uint64_t last_entry_off = 0;
2069 state.info_level = info_level;
2070 state.check_mangled_names = lp_manglednames(conn->params);
2071 state.has_wild = dptr_has_wild(dirptr);
2072 state.got_exact_match = false;
2074 *out_of_space = false;
2075 *got_exact_match = false;
2077 p = strrchr_m(path_mask,'/');
2088 ok = smbd_dirptr_get_entry(ctx,
2094 smbd_dirptr_lanman2_match_fn,
2095 smbd_dirptr_lanman2_mode_fn,
2105 *got_exact_match = state.got_exact_match;
2107 ok = smbd_marshall_dir_entry(ctx,
2112 state.check_mangled_names,
2113 requires_resume_key,
2126 TALLOC_FREE(smb_fname);
2127 if (*out_of_space) {
2128 dptr_SeekDir(dirptr, prev_dirpos);
2135 *_last_entry_off = last_entry_off;
2139 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2140 connection_struct *conn,
2141 struct dptr_struct *dirptr,
2143 const char *path_mask,
2146 int requires_resume_key,
2152 int space_remaining,
2154 bool *got_exact_match,
2155 int *last_entry_off,
2156 struct ea_list *name_list)
2158 bool resume_key = false;
2159 const uint8_t align = 4;
2160 const bool do_pad = true;
2162 if (requires_resume_key) {
2166 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2167 path_mask, dirtype, info_level,
2168 resume_key, dont_descend, ask_sharemode,
2170 ppdata, base_data, end_data,
2172 out_of_space, got_exact_match,
2173 last_entry_off, name_list);
2176 /****************************************************************************
2177 Reply to a TRANS2_FINDFIRST.
2178 ****************************************************************************/
2180 static void call_trans2findfirst(connection_struct *conn,
2181 struct smb_request *req,
2182 char **pparams, int total_params,
2183 char **ppdata, int total_data,
2184 unsigned int max_data_bytes)
2186 /* We must be careful here that we don't return more than the
2187 allowed number of data bytes. If this means returning fewer than
2188 maxentries then so be it. We assume that the redirector has
2189 enough room for the fixed number of parameter bytes it has
2191 struct smb_filename *smb_dname = NULL;
2192 char *params = *pparams;
2193 char *pdata = *ppdata;
2197 uint16 findfirst_flags;
2198 bool close_after_first;
2200 bool requires_resume_key;
2202 char *directory = NULL;
2205 int last_entry_off=0;
2209 bool finished = False;
2210 bool dont_descend = False;
2211 bool out_of_space = False;
2212 int space_remaining;
2213 bool mask_contains_wcard = False;
2214 struct ea_list *ea_list = NULL;
2215 NTSTATUS ntstatus = NT_STATUS_OK;
2216 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2217 TALLOC_CTX *ctx = talloc_tos();
2218 struct dptr_struct *dirptr = NULL;
2219 struct smbd_server_connection *sconn = smbd_server_conn;
2221 if (total_params < 13) {
2222 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2226 dirtype = SVAL(params,0);
2227 maxentries = SVAL(params,2);
2228 findfirst_flags = SVAL(params,4);
2229 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2230 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2231 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2232 info_level = SVAL(params,6);
2234 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2235 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2236 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2237 info_level, max_data_bytes));
2240 /* W2K3 seems to treat zero as 1. */
2244 switch (info_level) {
2245 case SMB_FIND_INFO_STANDARD:
2246 case SMB_FIND_EA_SIZE:
2247 case SMB_FIND_EA_LIST:
2248 case SMB_FIND_FILE_DIRECTORY_INFO:
2249 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2250 case SMB_FIND_FILE_NAMES_INFO:
2251 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2252 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2253 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2255 case SMB_FIND_FILE_UNIX:
2256 case SMB_FIND_FILE_UNIX_INFO2:
2257 /* Always use filesystem for UNIX mtime query. */
2258 ask_sharemode = false;
2259 if (!lp_unix_extensions()) {
2260 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2265 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2269 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2270 params+12, total_params - 12,
2271 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2272 if (!NT_STATUS_IS_OK(ntstatus)) {
2273 reply_nterror(req, ntstatus);
2277 ntstatus = filename_convert(ctx, conn,
2278 req->flags2 & FLAGS2_DFS_PATHNAMES,
2281 UCF_ALWAYS_ALLOW_WCARD_LCOMP),
2282 &mask_contains_wcard,
2284 if (!NT_STATUS_IS_OK(ntstatus)) {
2285 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2286 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2287 ERRSRV, ERRbadpath);
2290 reply_nterror(req, ntstatus);
2294 mask = smb_dname->original_lcomp;
2296 directory = smb_dname->base_name;
2298 p = strrchr_m(directory,'/');
2300 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2301 if((directory[0] == '.') && (directory[1] == '\0')) {
2302 mask = talloc_strdup(ctx,"*");
2304 reply_nterror(req, NT_STATUS_NO_MEMORY);
2307 mask_contains_wcard = True;
2309 directory = talloc_strdup(talloc_tos(), "./");
2311 reply_nterror(req, NT_STATUS_NO_MEMORY);
2318 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2320 if (info_level == SMB_FIND_EA_LIST) {
2323 if (total_data < 4) {
2324 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2328 ea_size = IVAL(pdata,0);
2329 if (ea_size != total_data) {
2330 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2331 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2332 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2336 if (!lp_ea_support(SNUM(conn))) {
2337 reply_doserror(req, ERRDOS, ERReasnotsupported);
2341 /* Pull out the list of names. */
2342 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2344 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2349 *ppdata = (char *)SMB_REALLOC(
2350 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2351 if(*ppdata == NULL ) {
2352 reply_nterror(req, NT_STATUS_NO_MEMORY);
2356 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2358 /* Realloc the params space */
2359 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2360 if (*pparams == NULL) {
2361 reply_nterror(req, NT_STATUS_NO_MEMORY);
2366 /* Save the wildcard match and attribs we are using on this directory -
2367 needed as lanman2 assumes these are being saved between calls */
2369 ntstatus = dptr_create(conn,
2375 mask_contains_wcard,
2379 if (!NT_STATUS_IS_OK(ntstatus)) {
2380 reply_nterror(req, ntstatus);
2384 dptr_num = dptr_dnum(dirptr);
2385 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2387 /* Initialize per TRANS2_FIND_FIRST operation data */
2388 dptr_init_search_op(dirptr);
2390 /* We don't need to check for VOL here as this is returned by
2391 a different TRANS2 call. */
2393 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2394 directory,lp_dontdescend(SNUM(conn))));
2395 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2396 dont_descend = True;
2399 space_remaining = max_data_bytes;
2400 out_of_space = False;
2402 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2403 bool got_exact_match = False;
2405 /* this is a heuristic to avoid seeking the dirptr except when
2406 absolutely necessary. It allows for a filename of about 40 chars */
2407 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2408 out_of_space = True;
2411 finished = !get_lanman2_dir_entry(ctx,
2415 mask,dirtype,info_level,
2416 requires_resume_key,dont_descend,
2419 space_remaining, &out_of_space,
2421 &last_entry_off, ea_list);
2424 if (finished && out_of_space)
2427 if (!finished && !out_of_space)
2431 * As an optimisation if we know we aren't looking
2432 * for a wildcard name (ie. the name matches the wildcard exactly)
2433 * then we can finish on any (first) match.
2434 * This speeds up large directory searches. JRA.
2440 /* Ensure space_remaining never goes -ve. */
2441 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2442 space_remaining = 0;
2443 out_of_space = true;
2445 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2449 /* Check if we can close the dirptr */
2450 if(close_after_first || (finished && close_if_end)) {
2451 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2452 dptr_close(sconn, &dptr_num);
2456 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2457 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2458 * the protocol level is less than NT1. Tested with smbclient. JRA.
2459 * This should fix the OS/2 client bug #2335.
2462 if(numentries == 0) {
2463 dptr_close(sconn, &dptr_num);
2464 if (Protocol < PROTOCOL_NT1) {
2465 reply_doserror(req, ERRDOS, ERRnofiles);
2468 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2469 ERRDOS, ERRbadfile);
2474 /* At this point pdata points to numentries directory entries. */
2476 /* Set up the return parameter block */
2477 SSVAL(params,0,dptr_num);
2478 SSVAL(params,2,numentries);
2479 SSVAL(params,4,finished);
2480 SSVAL(params,6,0); /* Never an EA error */
2481 SSVAL(params,8,last_entry_off);
2483 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2486 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2487 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2489 reply_nterror(req, NT_STATUS_NO_MEMORY);
2493 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2494 smb_fn_name(req->cmd),
2495 mask, directory, dirtype, numentries ) );
2498 * Force a name mangle here to ensure that the
2499 * mask as an 8.3 name is top of the mangled cache.
2500 * The reasons for this are subtle. Don't remove
2501 * this code unless you know what you are doing
2502 * (see PR#13758). JRA.
2505 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2506 char mangled_name[13];
2507 name_to_8_3(mask, mangled_name, True, conn->params);
2510 TALLOC_FREE(smb_dname);
2514 /****************************************************************************
2515 Reply to a TRANS2_FINDNEXT.
2516 ****************************************************************************/
2518 static void call_trans2findnext(connection_struct *conn,
2519 struct smb_request *req,
2520 char **pparams, int total_params,
2521 char **ppdata, int total_data,
2522 unsigned int max_data_bytes)
2524 /* We must be careful here that we don't return more than the
2525 allowed number of data bytes. If this means returning fewer than
2526 maxentries then so be it. We assume that the redirector has
2527 enough room for the fixed number of parameter bytes it has
2529 char *params = *pparams;
2530 char *pdata = *ppdata;
2536 uint16 findnext_flags;
2537 bool close_after_request;
2539 bool requires_resume_key;
2541 bool mask_contains_wcard = False;
2542 char *resume_name = NULL;
2543 const char *mask = NULL;
2544 const char *directory = NULL;
2548 int i, last_entry_off=0;
2549 bool finished = False;
2550 bool dont_descend = False;
2551 bool out_of_space = False;
2552 int space_remaining;
2553 struct ea_list *ea_list = NULL;
2554 NTSTATUS ntstatus = NT_STATUS_OK;
2555 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2556 TALLOC_CTX *ctx = talloc_tos();
2557 struct dptr_struct *dirptr;
2558 struct smbd_server_connection *sconn = smbd_server_conn;
2560 if (total_params < 13) {
2561 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2565 dptr_num = SVAL(params,0);
2566 maxentries = SVAL(params,2);
2567 info_level = SVAL(params,4);
2568 resume_key = IVAL(params,6);
2569 findnext_flags = SVAL(params,10);
2570 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2571 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2572 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2573 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2575 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2577 total_params - 12, STR_TERMINATE, &ntstatus,
2578 &mask_contains_wcard);
2579 if (!NT_STATUS_IS_OK(ntstatus)) {
2580 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2581 complain (it thinks we're asking for the directory above the shared
2582 path or an invalid name). Catch this as the resume name is only compared, never used in
2583 a file access. JRA. */
2584 srvstr_pull_talloc(ctx, params, req->flags2,
2585 &resume_name, params+12,
2589 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2590 reply_nterror(req, ntstatus);
2595 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2596 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2597 resume_key = %d resume name = %s continue=%d level = %d\n",
2598 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2599 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2602 /* W2K3 seems to treat zero as 1. */
2606 switch (info_level) {
2607 case SMB_FIND_INFO_STANDARD:
2608 case SMB_FIND_EA_SIZE:
2609 case SMB_FIND_EA_LIST:
2610 case SMB_FIND_FILE_DIRECTORY_INFO:
2611 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2612 case SMB_FIND_FILE_NAMES_INFO:
2613 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2614 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2615 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2617 case SMB_FIND_FILE_UNIX:
2618 case SMB_FIND_FILE_UNIX_INFO2:
2619 /* Always use filesystem for UNIX mtime query. */
2620 ask_sharemode = false;
2621 if (!lp_unix_extensions()) {
2622 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2627 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2631 if (info_level == SMB_FIND_EA_LIST) {
2634 if (total_data < 4) {
2635 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2639 ea_size = IVAL(pdata,0);
2640 if (ea_size != total_data) {
2641 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2642 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2643 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2647 if (!lp_ea_support(SNUM(conn))) {
2648 reply_doserror(req, ERRDOS, ERReasnotsupported);
2652 /* Pull out the list of names. */
2653 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2655 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2660 *ppdata = (char *)SMB_REALLOC(
2661 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2662 if(*ppdata == NULL) {
2663 reply_nterror(req, NT_STATUS_NO_MEMORY);
2668 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2670 /* Realloc the params space */
2671 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2672 if(*pparams == NULL ) {
2673 reply_nterror(req, NT_STATUS_NO_MEMORY);
2679 /* Check that the dptr is valid */
2680 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2681 reply_doserror(req, ERRDOS, ERRnofiles);
2685 directory = dptr_path(sconn, dptr_num);
2687 /* Get the wildcard mask from the dptr */
2688 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2689 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2690 reply_doserror(req, ERRDOS, ERRnofiles);
2696 /* Get the attr mask from the dptr */
2697 dirtype = dptr_attr(sconn, dptr_num);
2699 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2700 dptr_num, mask, dirtype,
2702 dptr_TellDir(dirptr)));
2704 /* Initialize per TRANS2_FIND_NEXT operation data */
2705 dptr_init_search_op(dirptr);
2707 /* We don't need to check for VOL here as this is returned by
2708 a different TRANS2 call. */
2710 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2711 directory,lp_dontdescend(SNUM(conn))));
2712 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2713 dont_descend = True;
2716 space_remaining = max_data_bytes;
2717 out_of_space = False;
2720 * Seek to the correct position. We no longer use the resume key but
2721 * depend on the last file name instead.
2724 if(*resume_name && !continue_bit) {
2727 long current_pos = 0;
2729 * Remember, name_to_8_3 is called by
2730 * get_lanman2_dir_entry(), so the resume name
2731 * could be mangled. Ensure we check the unmangled name.
2734 if (mangle_is_mangled(resume_name, conn->params)) {
2735 char *new_resume_name = NULL;
2736 mangle_lookup_name_from_8_3(ctx,
2740 if (new_resume_name) {
2741 resume_name = new_resume_name;
2746 * Fix for NT redirector problem triggered by resume key indexes
2747 * changing between directory scans. We now return a resume key of 0
2748 * and instead look for the filename to continue from (also given
2749 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2750 * findfirst/findnext (as is usual) then the directory pointer
2751 * should already be at the correct place.
2754 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
2755 } /* end if resume_name && !continue_bit */
2757 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2758 bool got_exact_match = False;
2760 /* this is a heuristic to avoid seeking the dirptr except when
2761 absolutely necessary. It allows for a filename of about 40 chars */
2762 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2763 out_of_space = True;
2766 finished = !get_lanman2_dir_entry(ctx,
2770 mask,dirtype,info_level,
2771 requires_resume_key,dont_descend,
2774 space_remaining, &out_of_space,
2776 &last_entry_off, ea_list);
2779 if (finished && out_of_space)
2782 if (!finished && !out_of_space)
2786 * As an optimisation if we know we aren't looking
2787 * for a wildcard name (ie. the name matches the wildcard exactly)
2788 * then we can finish on any (first) match.
2789 * This speeds up large directory searches. JRA.
2795 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2798 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2799 smb_fn_name(req->cmd),
2800 mask, directory, dirtype, numentries ) );
2802 /* Check if we can close the dirptr */
2803 if(close_after_request || (finished && close_if_end)) {
2804 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2805 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2808 /* Set up the return parameter block */
2809 SSVAL(params,0,numentries);
2810 SSVAL(params,2,finished);
2811 SSVAL(params,4,0); /* Never an EA error */
2812 SSVAL(params,6,last_entry_off);
2814 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2820 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2822 E_md4hash(lp_servicename(SNUM(conn)),objid);
2826 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2828 SMB_ASSERT(extended_info != NULL);
2830 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2831 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2832 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2833 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2834 #ifdef SAMBA_VERSION_REVISION
2835 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2837 extended_info->samba_subversion = 0;
2838 #ifdef SAMBA_VERSION_RC_RELEASE
2839 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2841 #ifdef SAMBA_VERSION_PRE_RELEASE
2842 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2845 #ifdef SAMBA_VERSION_VENDOR_PATCH
2846 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2848 extended_info->samba_gitcommitdate = 0;
2849 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2850 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2853 memset(extended_info->samba_version_string, 0,
2854 sizeof(extended_info->samba_version_string));
2856 snprintf (extended_info->samba_version_string,
2857 sizeof(extended_info->samba_version_string),
2858 "%s", samba_version_string());
2861 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2862 TALLOC_CTX *mem_ctx,
2863 uint16_t info_level,
2865 unsigned int max_data_bytes,
2869 char *pdata, *end_data;
2870 int data_len = 0, len;
2871 const char *vname = volume_label(SNUM(conn));
2872 int snum = SNUM(conn);
2873 char *fstype = lp_fstype(SNUM(conn));
2874 uint32 additional_flags = 0;
2875 struct smb_filename *smb_fname_dot = NULL;
2880 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2881 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2882 "info level (0x%x) on IPC$.\n",
2883 (unsigned int)info_level));
2884 return NT_STATUS_ACCESS_DENIED;
2888 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2890 status = create_synthetic_smb_fname(talloc_tos(), ".", NULL, NULL,
2892 if (!NT_STATUS_IS_OK(status)) {
2896 if(SMB_VFS_STAT(conn, smb_fname_dot) != 0) {
2897 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2898 TALLOC_FREE(smb_fname_dot);
2899 return map_nt_error_from_unix(errno);
2902 st = smb_fname_dot->st;
2903 TALLOC_FREE(smb_fname_dot);
2905 *ppdata = (char *)SMB_REALLOC(
2906 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2907 if (*ppdata == NULL) {
2908 return NT_STATUS_NO_MEMORY;
2912 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2913 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2915 switch (info_level) {
2916 case SMB_INFO_ALLOCATION:
2918 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2920 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2921 return map_nt_error_from_unix(errno);
2924 block_size = lp_block_size(snum);
2925 if (bsize < block_size) {
2926 uint64_t factor = block_size/bsize;
2931 if (bsize > block_size) {
2932 uint64_t factor = bsize/block_size;
2937 bytes_per_sector = 512;
2938 sectors_per_unit = bsize/bytes_per_sector;
2940 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2941 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2942 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2944 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2945 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2946 SIVAL(pdata,l1_cUnit,dsize);
2947 SIVAL(pdata,l1_cUnitAvail,dfree);
2948 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2952 case SMB_INFO_VOLUME:
2953 /* Return volume name */
2955 * Add volume serial number - hash of a combination of
2956 * the called hostname and the service name.
2958 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2960 * Win2k3 and previous mess this up by sending a name length
2961 * one byte short. I believe only older clients (OS/2 Win9x) use
2962 * this call so try fixing this by adding a terminating null to
2963 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2967 pdata+l2_vol_szVolLabel, vname,
2968 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2969 STR_NOALIGN|STR_TERMINATE);
2970 SCVAL(pdata,l2_vol_cch,len);
2971 data_len = l2_vol_szVolLabel + len;
2972 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
2973 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2977 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2978 case SMB_FS_ATTRIBUTE_INFORMATION:
2980 additional_flags = 0;
2981 #if defined(HAVE_SYS_QUOTAS)
2982 additional_flags |= FILE_VOLUME_QUOTAS;
2985 if(lp_nt_acl_support(SNUM(conn))) {
2986 additional_flags |= FILE_PERSISTENT_ACLS;
2989 /* Capabilities are filled in at connection time through STATVFS call */
2990 additional_flags |= conn->fs_capabilities;
2991 additional_flags |= lp_parm_int(conn->params->service,
2992 "share", "fake_fscaps",
2995 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2996 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2997 additional_flags); /* FS ATTRIBUTES */
2999 SIVAL(pdata,4,255); /* Max filename component length */
3000 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3001 and will think we can't do long filenames */
3002 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3003 PTR_DIFF(end_data, pdata+12),
3006 data_len = 12 + len;
3009 case SMB_QUERY_FS_LABEL_INFO:
3010 case SMB_FS_LABEL_INFORMATION:
3011 len = srvstr_push(pdata, flags2, pdata+4, vname,
3012 PTR_DIFF(end_data, pdata+4), 0);
3017 case SMB_QUERY_FS_VOLUME_INFO:
3018 case SMB_FS_VOLUME_INFORMATION:
3021 * Add volume serial number - hash of a combination of
3022 * the called hostname and the service name.
3024 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3025 (str_checksum(get_local_machine_name())<<16));
3027 /* Max label len is 32 characters. */
3028 len = srvstr_push(pdata, flags2, pdata+18, vname,
3029 PTR_DIFF(end_data, pdata+18),
3031 SIVAL(pdata,12,len);
3034 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3035 (int)strlen(vname),vname, lp_servicename(snum)));
3038 case SMB_QUERY_FS_SIZE_INFO:
3039 case SMB_FS_SIZE_INFORMATION:
3041 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3043 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3044 return map_nt_error_from_unix(errno);
3046 block_size = lp_block_size(snum);
3047 if (bsize < block_size) {
3048 uint64_t factor = block_size/bsize;
3053 if (bsize > block_size) {
3054 uint64_t factor = bsize/block_size;
3059 bytes_per_sector = 512;
3060 sectors_per_unit = bsize/bytes_per_sector;
3061 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3062 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3063 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3064 SBIG_UINT(pdata,0,dsize);
3065 SBIG_UINT(pdata,8,dfree);
3066 SIVAL(pdata,16,sectors_per_unit);
3067 SIVAL(pdata,20,bytes_per_sector);
3071 case SMB_FS_FULL_SIZE_INFORMATION:
3073 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3075 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3076 return map_nt_error_from_unix(errno);
3078 block_size = lp_block_size(snum);
3079 if (bsize < block_size) {
3080 uint64_t factor = block_size/bsize;
3085 if (bsize > block_size) {
3086 uint64_t factor = bsize/block_size;
3091 bytes_per_sector = 512;
3092 sectors_per_unit = bsize/bytes_per_sector;
3093 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3094 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3095 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3096 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3097 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3098 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3099 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3100 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3104 case SMB_QUERY_FS_DEVICE_INFO:
3105 case SMB_FS_DEVICE_INFORMATION:
3107 SIVAL(pdata,0,0); /* dev type */
3108 SIVAL(pdata,4,0); /* characteristics */
3111 #ifdef HAVE_SYS_QUOTAS
3112 case SMB_FS_QUOTA_INFORMATION:
3114 * what we have to send --metze:
3116 * Unknown1: 24 NULL bytes
3117 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3118 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3119 * Quota Flags: 2 byte :
3120 * Unknown3: 6 NULL bytes
3124 * details for Quota Flags:
3126 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3127 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3128 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3129 * 0x0001 Enable Quotas: enable quota for this fs
3133 /* we need to fake up a fsp here,
3134 * because its not send in this call
3137 SMB_NTQUOTA_STRUCT quotas;
3140 ZERO_STRUCT(quotas);
3146 if (conn->server_info->utok.uid != sec_initial_uid()) {
3147 DEBUG(0,("set_user_quota: access_denied "
3148 "service [%s] user [%s]\n",
3149 lp_servicename(SNUM(conn)),
3150 conn->server_info->unix_name));
3151 return NT_STATUS_ACCESS_DENIED;
3154 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3155 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3156 return map_nt_error_from_unix(errno);
3161 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3162 lp_servicename(SNUM(conn))));
3164 /* Unknown1 24 NULL bytes*/
3165 SBIG_UINT(pdata,0,(uint64_t)0);
3166 SBIG_UINT(pdata,8,(uint64_t)0);
3167 SBIG_UINT(pdata,16,(uint64_t)0);
3169 /* Default Soft Quota 8 bytes */
3170 SBIG_UINT(pdata,24,quotas.softlim);
3172 /* Default Hard Quota 8 bytes */
3173 SBIG_UINT(pdata,32,quotas.hardlim);
3175 /* Quota flag 2 bytes */
3176 SSVAL(pdata,40,quotas.qflags);
3178 /* Unknown3 6 NULL bytes */
3184 #endif /* HAVE_SYS_QUOTAS */
3185 case SMB_FS_OBJECTID_INFORMATION:
3187 unsigned char objid[16];
3188 struct smb_extended_info extended_info;
3189 memcpy(pdata,create_volume_objectid(conn, objid),16);
3190 samba_extended_info_version (&extended_info);
3191 SIVAL(pdata,16,extended_info.samba_magic);
3192 SIVAL(pdata,20,extended_info.samba_version);
3193 SIVAL(pdata,24,extended_info.samba_subversion);
3194 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3195 memcpy(pdata+36,extended_info.samba_version_string,28);
3201 * Query the version and capabilities of the CIFS UNIX extensions
3205 case SMB_QUERY_CIFS_UNIX_INFO:
3207 bool large_write = lp_min_receive_file_size() &&
3208 !srv_is_signing_active(smbd_server_conn);
3209 bool large_read = !srv_is_signing_active(smbd_server_conn);
3210 int encrypt_caps = 0;
3212 if (!lp_unix_extensions()) {
3213 return NT_STATUS_INVALID_LEVEL;
3216 switch (conn->encrypt_level) {
3222 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3225 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3226 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3227 large_write = false;
3233 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3234 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3236 /* We have POSIX ACLs, pathname, encryption,
3237 * large read/write, and locking capability. */
3239 SBIG_UINT(pdata,4,((uint64_t)(
3240 CIFS_UNIX_POSIX_ACLS_CAP|
3241 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3242 CIFS_UNIX_FCNTL_LOCKS_CAP|
3243 CIFS_UNIX_EXTATTR_CAP|
3244 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3246 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3248 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3252 case SMB_QUERY_POSIX_FS_INFO:
3255 vfs_statvfs_struct svfs;
3257 if (!lp_unix_extensions()) {
3258 return NT_STATUS_INVALID_LEVEL;
3261 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3265 SIVAL(pdata,0,svfs.OptimalTransferSize);
3266 SIVAL(pdata,4,svfs.BlockSize);
3267 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3268 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3269 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3270 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3271 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3272 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3273 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3275 } else if (rc == EOPNOTSUPP) {
3276 return NT_STATUS_INVALID_LEVEL;
3277 #endif /* EOPNOTSUPP */
3279 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3280 return NT_STATUS_DOS(ERRSRV, ERRerror);
3285 case SMB_QUERY_POSIX_WHOAMI:
3291 if (!lp_unix_extensions()) {
3292 return NT_STATUS_INVALID_LEVEL;
3295 if (max_data_bytes < 40) {
3296 return NT_STATUS_BUFFER_TOO_SMALL;
3299 /* We ARE guest if global_sid_Builtin_Guests is
3300 * in our list of SIDs.
3302 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3303 conn->server_info->ptok)) {
3304 flags |= SMB_WHOAMI_GUEST;
3307 /* We are NOT guest if global_sid_Authenticated_Users
3308 * is in our list of SIDs.
3310 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3311 conn->server_info->ptok)) {
3312 flags &= ~SMB_WHOAMI_GUEST;
3315 /* NOTE: 8 bytes for UID/GID, irrespective of native
3316 * platform size. This matches
3317 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3319 data_len = 4 /* flags */
3326 + 4 /* pad/reserved */
3327 + (conn->server_info->utok.ngroups * 8)
3329 + (conn->server_info->ptok->num_sids *
3333 SIVAL(pdata, 0, flags);
3334 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3336 (uint64_t)conn->server_info->utok.uid);
3337 SBIG_UINT(pdata, 16,
3338 (uint64_t)conn->server_info->utok.gid);
3341 if (data_len >= max_data_bytes) {
3342 /* Potential overflow, skip the GIDs and SIDs. */
3344 SIVAL(pdata, 24, 0); /* num_groups */
3345 SIVAL(pdata, 28, 0); /* num_sids */
3346 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3347 SIVAL(pdata, 36, 0); /* reserved */
3353 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3354 SIVAL(pdata, 28, conn->server_info->num_sids);
3356 /* We walk the SID list twice, but this call is fairly
3357 * infrequent, and I don't expect that it's performance
3358 * sensitive -- jpeach
3360 for (i = 0, sid_bytes = 0;
3361 i < conn->server_info->ptok->num_sids; ++i) {
3362 sid_bytes += ndr_size_dom_sid(
3363 &conn->server_info->ptok->user_sids[i],
3368 /* SID list byte count */
3369 SIVAL(pdata, 32, sid_bytes);
3371 /* 4 bytes pad/reserved - must be zero */
3372 SIVAL(pdata, 36, 0);
3376 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3377 SBIG_UINT(pdata, data_len,
3378 (uint64_t)conn->server_info->utok.groups[i]);
3384 i < conn->server_info->ptok->num_sids; ++i) {
3385 int sid_len = ndr_size_dom_sid(
3386 &conn->server_info->ptok->user_sids[i],
3390 sid_linearize(pdata + data_len, sid_len,
3391 &conn->server_info->ptok->user_sids[i]);
3392 data_len += sid_len;
3398 case SMB_MAC_QUERY_FS_INFO:
3400 * Thursby MAC extension... ONLY on NTFS filesystems
3401 * once we do streams then we don't need this
3403 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3405 SIVAL(pdata,84,0x100); /* Don't support mac... */
3410 return NT_STATUS_INVALID_LEVEL;
3413 *ret_data_len = data_len;
3414 return NT_STATUS_OK;
3417 /****************************************************************************
3418 Reply to a TRANS2_QFSINFO (query filesystem info).
3419 ****************************************************************************/
3421 static void call_trans2qfsinfo(connection_struct *conn,
3422 struct smb_request *req,
3423 char **pparams, int total_params,
3424 char **ppdata, int total_data,
3425 unsigned int max_data_bytes)
3427 char *params = *pparams;
3428 uint16_t info_level;
3432 if (total_params < 2) {
3433 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3437 info_level = SVAL(params,0);
3439 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3440 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3441 DEBUG(0,("call_trans2qfsinfo: encryption required "
3442 "and info level 0x%x sent.\n",
3443 (unsigned int)info_level));
3444 exit_server_cleanly("encryption required "
3450 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3452 status = smbd_do_qfsinfo(conn, req,
3457 if (!NT_STATUS_IS_OK(status)) {
3458 reply_nterror(req, status);
3462 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3465 DEBUG( 4, ( "%s info_level = %d\n",
3466 smb_fn_name(req->cmd), info_level) );
3471 /****************************************************************************
3472 Reply to a TRANS2_SETFSINFO (set filesystem info).
3473 ****************************************************************************/
3475 static void call_trans2setfsinfo(connection_struct *conn,
3476 struct smb_request *req,
3477 char **pparams, int total_params,
3478 char **ppdata, int total_data,
3479 unsigned int max_data_bytes)
3481 char *pdata = *ppdata;
3482 char *params = *pparams;
3485 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3488 if (total_params < 4) {
3489 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3491 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3495 info_level = SVAL(params,2);
3498 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3499 info_level != SMB_SET_CIFS_UNIX_INFO) {
3500 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3501 "info level (0x%x) on IPC$.\n",
3502 (unsigned int)info_level));
3503 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3508 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3509 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3510 DEBUG(0,("call_trans2setfsinfo: encryption required "
3511 "and info level 0x%x sent.\n",
3512 (unsigned int)info_level));
3513 exit_server_cleanly("encryption required "
3519 switch(info_level) {
3520 case SMB_SET_CIFS_UNIX_INFO:
3522 uint16 client_unix_major;
3523 uint16 client_unix_minor;
3524 uint32 client_unix_cap_low;
3525 uint32 client_unix_cap_high;
3527 if (!lp_unix_extensions()) {
3529 NT_STATUS_INVALID_LEVEL);
3533 /* There should be 12 bytes of capabilities set. */
3534 if (total_data < 8) {
3537 NT_STATUS_INVALID_PARAMETER);
3540 client_unix_major = SVAL(pdata,0);
3541 client_unix_minor = SVAL(pdata,2);
3542 client_unix_cap_low = IVAL(pdata,4);
3543 client_unix_cap_high = IVAL(pdata,8);
3544 /* Just print these values for now. */
3545 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3546 cap_low = 0x%x, cap_high = 0x%x\n",
3547 (unsigned int)client_unix_major,
3548 (unsigned int)client_unix_minor,
3549 (unsigned int)client_unix_cap_low,
3550 (unsigned int)client_unix_cap_high ));
3552 /* Here is where we must switch to posix pathname processing... */
3553 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3554 lp_set_posix_pathnames();
3555 mangle_change_to_posix();
3558 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3559 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3560 /* Client that knows how to do posix locks,
3561 * but not posix open/mkdir operations. Set a
3562 * default type for read/write checks. */
3564 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3570 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3573 size_t param_len = 0;
3574 size_t data_len = total_data;
3576 if (!lp_unix_extensions()) {
3579 NT_STATUS_INVALID_LEVEL);
3583 if (lp_smb_encrypt(SNUM(conn)) == false) {
3586 NT_STATUS_NOT_SUPPORTED);
3590 DEBUG( 4,("call_trans2setfsinfo: "
3591 "request transport encryption.\n"));
3593 status = srv_request_encryption_setup(conn,
3594 (unsigned char **)ppdata,
3596 (unsigned char **)pparams,
3599 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3600 !NT_STATUS_IS_OK(status)) {
3601 reply_nterror(req, status);
3605 send_trans2_replies(conn, req,
3612 if (NT_STATUS_IS_OK(status)) {
3613 /* Server-side transport
3614 * encryption is now *on*. */
3615 status = srv_encryption_start(conn);
3616 if (!NT_STATUS_IS_OK(status)) {
3617 exit_server_cleanly(
3618 "Failure in setting "
3619 "up encrypted transport");
3625 case SMB_FS_QUOTA_INFORMATION:
3627 files_struct *fsp = NULL;
3628 SMB_NTQUOTA_STRUCT quotas;
3630 ZERO_STRUCT(quotas);
3633 if ((conn->server_info->utok.uid != sec_initial_uid())
3634 ||!CAN_WRITE(conn)) {
3635 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3636 lp_servicename(SNUM(conn)),
3637 conn->server_info->unix_name));
3638 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3642 /* note: normaly there're 48 bytes,
3643 * but we didn't use the last 6 bytes for now
3646 fsp = file_fsp(req, SVAL(params,0));
3648 if (!check_fsp_ntquota_handle(conn, req,
3650 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3652 req, NT_STATUS_INVALID_HANDLE);
3656 if (total_data < 42) {
3657 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3661 NT_STATUS_INVALID_PARAMETER);
3665 /* unknown_1 24 NULL bytes in pdata*/
3667 /* the soft quotas 8 bytes (uint64_t)*/
3668 quotas.softlim = (uint64_t)IVAL(pdata,24);
3669 #ifdef LARGE_SMB_OFF_T
3670 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3671 #else /* LARGE_SMB_OFF_T */
3672 if ((IVAL(pdata,28) != 0)&&
3673 ((quotas.softlim != 0xFFFFFFFF)||
3674 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3675 /* more than 32 bits? */
3678 NT_STATUS_INVALID_PARAMETER);
3681 #endif /* LARGE_SMB_OFF_T */
3683 /* the hard quotas 8 bytes (uint64_t)*/
3684 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3685 #ifdef LARGE_SMB_OFF_T
3686 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3687 #else /* LARGE_SMB_OFF_T */
3688 if ((IVAL(pdata,36) != 0)&&
3689 ((quotas.hardlim != 0xFFFFFFFF)||
3690 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3691 /* more than 32 bits? */
3694 NT_STATUS_INVALID_PARAMETER);
3697 #endif /* LARGE_SMB_OFF_T */
3699 /* quota_flags 2 bytes **/
3700 quotas.qflags = SVAL(pdata,40);
3702 /* unknown_2 6 NULL bytes follow*/
3704 /* now set the quotas */
3705 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3706 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3707 reply_nterror(req, map_nt_error_from_unix(errno));
3714 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3716 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3722 * sending this reply works fine,
3723 * but I'm not sure it's the same
3724 * like windows do...
3727 reply_outbuf(req, 10, 0);
3730 #if defined(HAVE_POSIX_ACLS)
3731 /****************************************************************************
3732 Utility function to count the number of entries in a POSIX acl.
3733 ****************************************************************************/
3735 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3737 unsigned int ace_count = 0;
3738 int entry_id = SMB_ACL_FIRST_ENTRY;
3739 SMB_ACL_ENTRY_T entry;
3741 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3743 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3744 entry_id = SMB_ACL_NEXT_ENTRY;
3751 /****************************************************************************
3752 Utility function to marshall a POSIX acl into wire format.
3753 ****************************************************************************/
3755 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3757 int entry_id = SMB_ACL_FIRST_ENTRY;
3758 SMB_ACL_ENTRY_T entry;
3760 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3761 SMB_ACL_TAG_T tagtype;
3762 SMB_ACL_PERMSET_T permset;
3763 unsigned char perms = 0;
3764 unsigned int own_grp;
3767 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3768 entry_id = SMB_ACL_NEXT_ENTRY;
3771 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3772 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3776 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3777 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3781 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3782 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3783 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3785 SCVAL(pdata,1,perms);
3788 case SMB_ACL_USER_OBJ:
3789 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3790 own_grp = (unsigned int)pst->st_ex_uid;
3791 SIVAL(pdata,2,own_grp);
3796 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3798 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3801 own_grp = (unsigned int)*puid;
3802 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3803 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3804 SIVAL(pdata,2,own_grp);
3808 case SMB_ACL_GROUP_OBJ:
3809 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3810 own_grp = (unsigned int)pst->st_ex_gid;
3811 SIVAL(pdata,2,own_grp);
3816 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3818 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3821 own_grp = (unsigned int)*pgid;
3822 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3823 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3824 SIVAL(pdata,2,own_grp);
3829 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3830 SIVAL(pdata,2,0xFFFFFFFF);
3831 SIVAL(pdata,6,0xFFFFFFFF);
3834 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3835 SIVAL(pdata,2,0xFFFFFFFF);
3836 SIVAL(pdata,6,0xFFFFFFFF);
3839 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3842 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3849 /****************************************************************************
3850 Store the FILE_UNIX_BASIC info.
3851 ****************************************************************************/
3853 static char *store_file_unix_basic(connection_struct *conn,
3856 const SMB_STRUCT_STAT *psbuf)
3858 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3859 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3861 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3864 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3867 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3868 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3869 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3872 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3876 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3880 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3883 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3887 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3891 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */
3894 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3898 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3905 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3906 * the chflags(2) (or equivalent) flags.
3908 * XXX: this really should be behind the VFS interface. To do this, we would
3909 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3910 * Each VFS module could then implement its own mapping as appropriate for the
3911 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3913 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3917 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3921 { UF_IMMUTABLE, EXT_IMMUTABLE },
3925 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3929 { UF_HIDDEN, EXT_HIDDEN },
3932 /* Do not remove. We need to guarantee that this array has at least one
3933 * entry to build on HP-UX.
3939 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3940 uint32 *smb_fflags, uint32 *smb_fmask)
3944 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3945 *smb_fmask |= info2_flags_map[i].smb_fflag;
3946 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3947 *smb_fflags |= info2_flags_map[i].smb_fflag;
3952 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3953 const uint32 smb_fflags,
3954 const uint32 smb_fmask,
3957 uint32 max_fmask = 0;
3960 *stat_fflags = psbuf->st_ex_flags;
3962 /* For each flags requested in smb_fmask, check the state of the
3963 * corresponding flag in smb_fflags and set or clear the matching
3967 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3968 max_fmask |= info2_flags_map[i].smb_fflag;
3969 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3970 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3971 *stat_fflags |= info2_flags_map[i].stat_fflag;
3973 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3978 /* If smb_fmask is asking to set any bits that are not supported by
3979 * our flag mappings, we should fail.
3981 if ((smb_fmask & max_fmask) != smb_fmask) {
3989 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3990 * of file flags and birth (create) time.
3992 static char *store_file_unix_basic_info2(connection_struct *conn,
3995 const SMB_STRUCT_STAT *psbuf)
3997 uint32 file_flags = 0;
3998 uint32 flags_mask = 0;
4000 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4002 /* Create (birth) time 64 bit */
4003 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4006 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4007 SIVAL(pdata, 0, file_flags); /* flags */
4008 SIVAL(pdata, 4, flags_mask); /* mask */
4014 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4015 const struct stream_struct *streams,
4017 unsigned int max_data_bytes,
4018 unsigned int *data_size)
4021 unsigned int ofs = 0;
4023 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4024 unsigned int next_offset;
4026 smb_ucs2_t *namebuf;
4028 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4029 streams[i].name, &namelen) ||
4032 return NT_STATUS_INVALID_PARAMETER;
4036 * name_buf is now null-terminated, we need to marshall as not
4042 SIVAL(data, ofs+4, namelen);
4043 SOFF_T(data, ofs+8, streams[i].size);
4044 SOFF_T(data, ofs+16, streams[i].alloc_size);
4045 memcpy(data+ofs+24, namebuf, namelen);
4046 TALLOC_FREE(namebuf);
4048 next_offset = ofs + 24 + namelen;
4050 if (i == num_streams-1) {
4051 SIVAL(data, ofs, 0);
4054 unsigned int align = ndr_align_size(next_offset, 8);
4056 memset(data+next_offset, 0, align);
4057 next_offset += align;
4059 SIVAL(data, ofs, next_offset - ofs);
4068 return NT_STATUS_OK;
4071 /****************************************************************************
4072 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4073 ****************************************************************************/
4075 static void call_trans2qpipeinfo(connection_struct *conn,
4076 struct smb_request *req,
4077 unsigned int tran_call,
4078 char **pparams, int total_params,
4079 char **ppdata, int total_data,
4080 unsigned int max_data_bytes)
4082 char *params = *pparams;
4083 char *pdata = *ppdata;
4084 unsigned int data_size = 0;
4085 unsigned int param_size = 2;
4090 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4094 if (total_params < 4) {
4095 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4099 fsp = file_fsp(req, SVAL(params,0));
4100 if (!fsp_is_np(fsp)) {
4101 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4105 info_level = SVAL(params,2);
4107 *pparams = (char *)SMB_REALLOC(*pparams,2);
4108 if (*pparams == NULL) {
4109 reply_nterror(req, NT_STATUS_NO_MEMORY);
4114 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4115 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4116 if (*ppdata == NULL ) {
4117 reply_nterror(req, NT_STATUS_NO_MEMORY);
4122 switch (info_level) {
4123 case SMB_FILE_STANDARD_INFORMATION:
4125 SOFF_T(pdata,0,4096LL);
4132 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4136 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4142 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4143 TALLOC_CTX *mem_ctx,
4144 uint16_t info_level,
4146 struct smb_filename *smb_fname,
4147 bool delete_pending,
4148 struct timespec write_time_ts,
4150 struct ea_list *ea_list,
4151 int lock_data_count,
4154 unsigned int max_data_bytes,
4156 unsigned int *pdata_size)
4158 char *pdata = *ppdata;
4159 char *dstart, *dend;
4160 unsigned int data_size;
4161 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4162 time_t create_time, mtime, atime, c_time;
4163 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4170 uint64_t file_size = 0;
4172 uint64_t allocation_size = 0;
4173 uint64_t file_index = 0;
4174 uint32_t access_mask = 0;
4176 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4177 return NT_STATUS_INVALID_LEVEL;
4180 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4181 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4182 info_level, max_data_bytes));
4185 mode = dos_mode_msdfs(conn, smb_fname);
4187 mode = dos_mode(conn, smb_fname);
4190 mode = FILE_ATTRIBUTE_NORMAL;
4192 nlink = psbuf->st_ex_nlink;
4194 if (nlink && (mode&aDIR)) {
4198 if ((nlink > 0) && delete_pending) {
4202 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4203 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4204 if (*ppdata == NULL) {
4205 return NT_STATUS_NO_MEMORY;
4209 dend = dstart + data_size - 1;
4211 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4212 update_stat_ex_mtime(psbuf, write_time_ts);
4215 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4216 mtime_ts = psbuf->st_ex_mtime;
4217 atime_ts = psbuf->st_ex_atime;
4218 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4220 if (lp_dos_filetime_resolution(SNUM(conn))) {
4221 dos_filetime_timespec(&create_time_ts);
4222 dos_filetime_timespec(&mtime_ts);
4223 dos_filetime_timespec(&atime_ts);
4224 dos_filetime_timespec(&ctime_ts);
4227 create_time = convert_timespec_to_time_t(create_time_ts);
4228 mtime = convert_timespec_to_time_t(mtime_ts);
4229 atime = convert_timespec_to_time_t(atime_ts);
4230 c_time = convert_timespec_to_time_t(ctime_ts);
4232 p = strrchr_m(smb_fname->base_name,'/');
4234 base_name = smb_fname->base_name;
4238 /* NT expects the name to be in an exact form of the *full*
4239 filename. See the trans2 torture test */
4240 if (ISDOT(base_name)) {
4241 dos_fname = talloc_strdup(mem_ctx, "\\");
4243 return NT_STATUS_NO_MEMORY;
4246 dos_fname = talloc_asprintf(mem_ctx,
4248 smb_fname->base_name);
4250 return NT_STATUS_NO_MEMORY;
4252 if (is_ntfs_stream_smb_fname(smb_fname)) {
4253 dos_fname = talloc_asprintf(dos_fname, "%s",
4254 smb_fname->stream_name);
4256 return NT_STATUS_NO_MEMORY;
4260 string_replace(dos_fname, '/', '\\');
4263 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4266 /* Do we have this path open ? */
4268 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4269 fsp1 = file_find_di_first(fileid);
4270 if (fsp1 && fsp1->initial_allocation_size) {
4271 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4275 if (!(mode & aDIR)) {
4276 file_size = get_file_size_stat(psbuf);
4280 pos = fsp->fh->position_information;
4284 access_mask = fsp->access_mask;
4286 /* GENERIC_EXECUTE mapping from Windows */
4287 access_mask = 0x12019F;
4290 /* This should be an index number - looks like
4293 I think this causes us to fail the IFSKIT
4294 BasicFileInformationTest. -tpot */
4295 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
4296 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
4298 switch (info_level) {
4299 case SMB_INFO_STANDARD:
4300 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4302 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4303 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4304 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4305 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4306 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4307 SSVAL(pdata,l1_attrFile,mode);
4310 case SMB_INFO_QUERY_EA_SIZE:
4312 unsigned int ea_size =
4313 estimate_ea_size(conn, fsp,
4314 smb_fname->base_name);
4315 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4317 srv_put_dos_date2(pdata,0,create_time);
4318 srv_put_dos_date2(pdata,4,atime);
4319 srv_put_dos_date2(pdata,8,mtime); /* write time */
4320 SIVAL(pdata,12,(uint32)file_size);
4321 SIVAL(pdata,16,(uint32)allocation_size);
4322 SSVAL(pdata,20,mode);
4323 SIVAL(pdata,22,ea_size);
4327 case SMB_INFO_IS_NAME_VALID:
4328 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4330 /* os/2 needs this ? really ?*/
4331 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4333 /* This is only reached for qpathinfo */
4337 case SMB_INFO_QUERY_EAS_FROM_LIST:
4339 size_t total_ea_len = 0;
4340 struct ea_list *ea_file_list = NULL;
4342 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4345 get_ea_list_from_file(mem_ctx, conn, fsp,
4346 smb_fname->base_name,
4348 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4350 if (!ea_list || (total_ea_len > data_size)) {
4352 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4356 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4360 case SMB_INFO_QUERY_ALL_EAS:
4362 /* We have data_size bytes to put EA's into. */
4363 size_t total_ea_len = 0;
4365 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4367 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4368 smb_fname->base_name,
4370 if (!ea_list || (total_ea_len > data_size)) {
4372 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4376 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4380 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4382 /* This is FileFullEaInformation - 0xF which maps to
4383 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4385 /* We have data_size bytes to put EA's into. */
4386 size_t total_ea_len = 0;
4387 struct ea_list *ea_file_list = NULL;
4389 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4391 /*TODO: add filtering and index handling */
4394 get_ea_list_from_file(mem_ctx, conn, fsp,
4395 smb_fname->base_name,
4397 if (!ea_file_list) {
4398 return NT_STATUS_NO_EAS_ON_FILE;
4401 status = fill_ea_chained_buffer(mem_ctx,
4405 conn, ea_file_list);
4406 if (!NT_STATUS_IS_OK(status)) {
4412 case SMB_FILE_BASIC_INFORMATION:
4413 case SMB_QUERY_FILE_BASIC_INFO:
4415 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4416 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4417 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4419 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4423 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4424 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4425 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4426 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4427 SIVAL(pdata,32,mode);
4429 DEBUG(5,("SMB_QFBI - "));
4430 DEBUG(5,("create: %s ", ctime(&create_time)));
4431 DEBUG(5,("access: %s ", ctime(&atime)));
4432 DEBUG(5,("write: %s ", ctime(&mtime)));
4433 DEBUG(5,("change: %s ", ctime(&c_time)));
4434 DEBUG(5,("mode: %x\n", mode));
4437 case SMB_FILE_STANDARD_INFORMATION:
4438 case SMB_QUERY_FILE_STANDARD_INFO:
4440 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4442 SOFF_T(pdata,0,allocation_size);
4443 SOFF_T(pdata,8,file_size);
4444 SIVAL(pdata,16,nlink);
4445 SCVAL(pdata,20,delete_pending?1:0);
4446 SCVAL(pdata,21,(mode&aDIR)?1:0);
4447 SSVAL(pdata,22,0); /* Padding. */
4450 case SMB_FILE_EA_INFORMATION:
4451 case SMB_QUERY_FILE_EA_INFO:
4453 unsigned int ea_size =
4454 estimate_ea_size(conn, fsp, smb_fname->base_name);
4455 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4457 SIVAL(pdata,0,ea_size);
4461 /* Get the 8.3 name - used if NT SMB was negotiated. */
4462 case SMB_QUERY_FILE_ALT_NAME_INFO:
4463 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4466 char mangled_name[13];
4467 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4468 if (!name_to_8_3(base_name,mangled_name,
4469 True,conn->params)) {
4470 return NT_STATUS_NO_MEMORY;
4472 len = srvstr_push(dstart, flags2,
4473 pdata+4, mangled_name,
4474 PTR_DIFF(dend, pdata+4),
4476 data_size = 4 + len;
4481 case SMB_QUERY_FILE_NAME_INFO:
4485 this must be *exactly* right for ACLs on mapped drives to work
4487 len = srvstr_push(dstart, flags2,
4489 PTR_DIFF(dend, pdata+4),
4491 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4492 data_size = 4 + len;
4497 case SMB_FILE_ALLOCATION_INFORMATION:
4498 case SMB_QUERY_FILE_ALLOCATION_INFO:
4499 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4501 SOFF_T(pdata,0,allocation_size);
4504 case SMB_FILE_END_OF_FILE_INFORMATION:
4505 case SMB_QUERY_FILE_END_OF_FILEINFO:
4506 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4508 SOFF_T(pdata,0,file_size);
4511 case SMB_QUERY_FILE_ALL_INFO:
4512 case SMB_FILE_ALL_INFORMATION:
4515 unsigned int ea_size =
4516 estimate_ea_size(conn, fsp, smb_fname->base_name);
4517 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4518 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4519 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4520 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4521 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4522 SIVAL(pdata,32,mode);
4523 SIVAL(pdata,36,0); /* padding. */
4525 SOFF_T(pdata,0,allocation_size);
4526 SOFF_T(pdata,8,file_size);
4527 SIVAL(pdata,16,nlink);
4528 SCVAL(pdata,20,delete_pending);
4529 SCVAL(pdata,21,(mode&aDIR)?1:0);
4532 SIVAL(pdata,0,ea_size);
4533 pdata += 4; /* EA info */
4534 len = srvstr_push(dstart, flags2,
4536 PTR_DIFF(dend, pdata+4),
4540 data_size = PTR_DIFF(pdata,(*ppdata));
4544 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4547 unsigned int ea_size =
4548 estimate_ea_size(conn, fsp, smb_fname->base_name);
4549 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4550 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4551 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4552 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4553 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4554 SIVAL(pdata, 0x20, mode);
4555 SIVAL(pdata, 0x24, 0); /* padding. */
4556 SBVAL(pdata, 0x28, allocation_size);
4557 SBVAL(pdata, 0x30, file_size);
4558 SIVAL(pdata, 0x38, nlink);
4559 SCVAL(pdata, 0x3C, delete_pending);
4560 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4561 SSVAL(pdata, 0x3E, 0); /* padding */
4562 SBVAL(pdata, 0x40, file_index);
4563 SIVAL(pdata, 0x48, ea_size);
4564 SIVAL(pdata, 0x4C, access_mask);
4565 SBVAL(pdata, 0x50, pos);
4566 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4567 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4571 len = srvstr_push(dstart, flags2,
4573 PTR_DIFF(dend, pdata+4),
4577 data_size = PTR_DIFF(pdata,(*ppdata));
4580 case SMB_FILE_INTERNAL_INFORMATION:
4582 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4583 SBVAL(pdata, 0, file_index);
4587 case SMB_FILE_ACCESS_INFORMATION:
4588 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4589 SIVAL(pdata, 0, access_mask);
4593 case SMB_FILE_NAME_INFORMATION:
4594 /* Pathname with leading '\'. */
4597 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4598 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4599 SIVAL(pdata,0,byte_len);
4600 data_size = 4 + byte_len;
4604 case SMB_FILE_DISPOSITION_INFORMATION:
4605 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4607 SCVAL(pdata,0,delete_pending);
4610 case SMB_FILE_POSITION_INFORMATION:
4611 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4613 SOFF_T(pdata,0,pos);
4616 case SMB_FILE_MODE_INFORMATION:
4617 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4618 SIVAL(pdata,0,mode);
4622 case SMB_FILE_ALIGNMENT_INFORMATION:
4623 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4624 SIVAL(pdata,0,0); /* No alignment needed. */
4629 * NT4 server just returns "invalid query" to this - if we try
4630 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4633 /* The first statement above is false - verified using Thursby
4634 * client against NT4 -- gcolley.
4636 case SMB_QUERY_FILE_STREAM_INFO:
4637 case SMB_FILE_STREAM_INFORMATION: {
4638 unsigned int num_streams;
4639 struct stream_struct *streams;
4641 DEBUG(10,("smbd_do_qfilepathinfo: "
4642 "SMB_FILE_STREAM_INFORMATION\n"));
4644 if (is_ntfs_stream_smb_fname(smb_fname)) {
4645 return NT_STATUS_INVALID_PARAMETER;
4648 status = SMB_VFS_STREAMINFO(
4649 conn, fsp, smb_fname->base_name, talloc_tos(),
4650 &num_streams, &streams);
4652 if (!NT_STATUS_IS_OK(status)) {
4653 DEBUG(10, ("could not get stream info: %s\n",
4654 nt_errstr(status)));
4658 status = marshall_stream_info(num_streams, streams,
4659 pdata, max_data_bytes,
4662 if (!NT_STATUS_IS_OK(status)) {
4663 DEBUG(10, ("marshall_stream_info failed: %s\n",
4664 nt_errstr(status)));
4668 TALLOC_FREE(streams);
4672 case SMB_QUERY_COMPRESSION_INFO:
4673 case SMB_FILE_COMPRESSION_INFORMATION:
4674 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4675 SOFF_T(pdata,0,file_size);
4676 SIVAL(pdata,8,0); /* ??? */
4677 SIVAL(pdata,12,0); /* ??? */
4681 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4682 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4683 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4684 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4685 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4686 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4687 SOFF_T(pdata,32,allocation_size);
4688 SOFF_T(pdata,40,file_size);
4689 SIVAL(pdata,48,mode);
4690 SIVAL(pdata,52,0); /* ??? */
4694 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4695 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4696 SIVAL(pdata,0,mode);
4702 * CIFS UNIX Extensions.
4705 case SMB_QUERY_FILE_UNIX_BASIC:
4707 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4708 data_size = PTR_DIFF(pdata,(*ppdata));
4712 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4714 for (i=0; i<100; i++)
4715 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4721 case SMB_QUERY_FILE_UNIX_INFO2:
4723 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4724 data_size = PTR_DIFF(pdata,(*ppdata));
4728 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4730 for (i=0; i<100; i++)
4731 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4737 case SMB_QUERY_FILE_UNIX_LINK:
4740 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4743 return NT_STATUS_NO_MEMORY;
4746 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4748 if(!S_ISLNK(psbuf->st_ex_mode)) {
4749 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4752 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4754 len = SMB_VFS_READLINK(conn,
4755 smb_fname->base_name,
4758 return map_nt_error_from_unix(errno);
4761 len = srvstr_push(dstart, flags2,
4763 PTR_DIFF(dend, pdata),
4766 data_size = PTR_DIFF(pdata,(*ppdata));
4771 #if defined(HAVE_POSIX_ACLS)
4772 case SMB_QUERY_POSIX_ACL:
4774 SMB_ACL_T file_acl = NULL;
4775 SMB_ACL_T def_acl = NULL;
4776 uint16 num_file_acls = 0;
4777 uint16 num_def_acls = 0;
4779 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4780 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4783 SMB_VFS_SYS_ACL_GET_FILE(conn,
4784 smb_fname->base_name,
4785 SMB_ACL_TYPE_ACCESS);
4788 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4789 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4790 "not implemented on "
4791 "filesystem containing %s\n",
4792 smb_fname->base_name));
4793 return NT_STATUS_NOT_IMPLEMENTED;
4796 if (S_ISDIR(psbuf->st_ex_mode)) {
4797 if (fsp && fsp->is_directory) {
4799 SMB_VFS_SYS_ACL_GET_FILE(
4801 fsp->fsp_name->base_name,
4802 SMB_ACL_TYPE_DEFAULT);
4805 SMB_VFS_SYS_ACL_GET_FILE(
4807 smb_fname->base_name,
4808 SMB_ACL_TYPE_DEFAULT);
4810 def_acl = free_empty_sys_acl(conn, def_acl);
4813 num_file_acls = count_acl_entries(conn, file_acl);
4814 num_def_acls = count_acl_entries(conn, def_acl);
4816 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4817 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4819 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4820 SMB_POSIX_ACL_HEADER_SIZE) ));
4822 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4825 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4827 return NT_STATUS_BUFFER_TOO_SMALL;
4830 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4831 SSVAL(pdata,2,num_file_acls);
4832 SSVAL(pdata,4,num_def_acls);
4833 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4835 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4838 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4840 return NT_STATUS_INTERNAL_ERROR;
4842 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4844 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4847 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4849 return NT_STATUS_INTERNAL_ERROR;
4853 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4856 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4858 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4864 case SMB_QUERY_POSIX_LOCK:
4869 enum brl_type lock_type;
4871 /* We need an open file with a real fd for this. */
4872 if (!fsp || fsp->is_directory || fsp->fh->fd == -1) {
4873 return NT_STATUS_INVALID_LEVEL;
4876 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4877 return NT_STATUS_INVALID_PARAMETER;
4880 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4881 case POSIX_LOCK_TYPE_READ:
4882 lock_type = READ_LOCK;
4884 case POSIX_LOCK_TYPE_WRITE:
4885 lock_type = WRITE_LOCK;
4887 case POSIX_LOCK_TYPE_UNLOCK:
4889 /* There's no point in asking for an unlock... */
4890 return NT_STATUS_INVALID_PARAMETER;
4893 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4894 #if defined(HAVE_LONGLONG)
4895 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4896 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4897 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4898 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4899 #else /* HAVE_LONGLONG */
4900 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4901 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4902 #endif /* HAVE_LONGLONG */
4904 status = query_lock(fsp,
4911 if (ERROR_WAS_LOCK_DENIED(status)) {
4912 /* Here we need to report who has it locked... */
4913 data_size = POSIX_LOCK_DATA_SIZE;
4915 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4916 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4917 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4918 #if defined(HAVE_LONGLONG)
4919 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4920 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4921 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4922 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4923 #else /* HAVE_LONGLONG */
4924 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4925 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4926 #endif /* HAVE_LONGLONG */
4928 } else if (NT_STATUS_IS_OK(status)) {
4929 /* For success we just return a copy of what we sent
4930 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4931 data_size = POSIX_LOCK_DATA_SIZE;
4932 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4933 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4941 return NT_STATUS_INVALID_LEVEL;
4944 *pdata_size = data_size;
4945 return NT_STATUS_OK;
4948 /****************************************************************************
4949 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4950 file name or file id).
4951 ****************************************************************************/
4953 static void call_trans2qfilepathinfo(connection_struct *conn,
4954 struct smb_request *req,
4955 unsigned int tran_call,
4956 char **pparams, int total_params,
4957 char **ppdata, int total_data,
4958 unsigned int max_data_bytes)
4960 char *params = *pparams;
4961 char *pdata = *ppdata;
4963 unsigned int data_size = 0;
4964 unsigned int param_size = 2;
4965 struct smb_filename *smb_fname = NULL;
4966 bool delete_pending = False;
4967 struct timespec write_time_ts;
4968 files_struct *fsp = NULL;
4969 struct file_id fileid;
4970 struct ea_list *ea_list = NULL;
4971 int lock_data_count = 0;
4972 char *lock_data = NULL;
4973 bool ms_dfs_link = false;
4974 NTSTATUS status = NT_STATUS_OK;
4977 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4981 ZERO_STRUCT(write_time_ts);
4983 if (tran_call == TRANSACT2_QFILEINFO) {
4984 if (total_params < 4) {
4985 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4990 call_trans2qpipeinfo(conn, req, tran_call,
4991 pparams, total_params,
4997 fsp = file_fsp(req, SVAL(params,0));
4998 info_level = SVAL(params,2);
5000 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5002 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5003 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5007 /* Initial check for valid fsp ptr. */
5008 if (!check_fsp_open(conn, req, fsp)) {
5012 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5014 if (!NT_STATUS_IS_OK(status)) {
5015 reply_nterror(req, status);
5019 if(fsp->fake_file_handle) {
5021 * This is actually for the QUOTA_FAKE_FILE --metze
5024 /* We know this name is ok, it's already passed the checks. */
5026 } else if(fsp->is_directory || fsp->fh->fd == -1) {
5028 * This is actually a QFILEINFO on a directory
5029 * handle (returned from an NT SMB). NT5.0 seems
5030 * to do this call. JRA.
5033 if (INFO_LEVEL_IS_UNIX(info_level)) {
5034 /* Always do lstat for UNIX calls. */
5035 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5036 DEBUG(3,("call_trans2qfilepathinfo: "
5037 "SMB_VFS_LSTAT of %s failed "
5039 smb_fname_str_dbg(smb_fname),
5042 map_nt_error_from_unix(errno));
5045 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5046 DEBUG(3,("call_trans2qfilepathinfo: "
5047 "SMB_VFS_STAT of %s failed (%s)\n",
5048 smb_fname_str_dbg(smb_fname),
5051 map_nt_error_from_unix(errno));
5055 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5056 get_file_infos(fileid, &delete_pending, &write_time_ts);
5059 * Original code - this is an open file.
5061 if (!check_fsp(conn, req, fsp)) {
5065 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5066 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5067 fsp->fnum, strerror(errno)));
5069 map_nt_error_from_unix(errno));
5072 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5073 get_file_infos(fileid, &delete_pending, &write_time_ts);
5080 if (total_params < 7) {
5081 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5085 info_level = SVAL(params,0);
5087 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5089 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5090 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5094 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
5096 STR_TERMINATE, &status);
5097 if (!NT_STATUS_IS_OK(status)) {
5098 reply_nterror(req, status);
5102 status = filename_convert(req,
5104 req->flags2 & FLAGS2_DFS_PATHNAMES,
5109 if (!NT_STATUS_IS_OK(status)) {
5110 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5111 reply_botherror(req,
5112 NT_STATUS_PATH_NOT_COVERED,
5113 ERRSRV, ERRbadpath);
5116 reply_nterror(req, status);
5120 /* If this is a stream, check if there is a delete_pending. */
5121 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5122 && is_ntfs_stream_smb_fname(smb_fname)) {
5123 struct smb_filename *smb_fname_base = NULL;
5125 /* Create an smb_filename with stream_name == NULL. */
5127 create_synthetic_smb_fname(talloc_tos(),
5128 smb_fname->base_name,
5131 if (!NT_STATUS_IS_OK(status)) {
5132 reply_nterror(req, status);
5136 if (INFO_LEVEL_IS_UNIX(info_level)) {
5137 /* Always do lstat for UNIX calls. */
5138 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5139 DEBUG(3,("call_trans2qfilepathinfo: "
5140 "SMB_VFS_LSTAT of %s failed "
5142 smb_fname_str_dbg(smb_fname_base),
5144 TALLOC_FREE(smb_fname_base);
5146 map_nt_error_from_unix(errno));
5150 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5151 DEBUG(3,("call_trans2qfilepathinfo: "
5152 "fileinfo of %s failed "
5154 smb_fname_str_dbg(smb_fname_base),
5156 TALLOC_FREE(smb_fname_base);
5158 map_nt_error_from_unix(errno));
5163 fileid = vfs_file_id_from_sbuf(conn,
5164 &smb_fname_base->st);
5165 TALLOC_FREE(smb_fname_base);
5166 get_file_infos(fileid, &delete_pending, NULL);
5167 if (delete_pending) {
5168 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5173 if (INFO_LEVEL_IS_UNIX(info_level)) {
5174 /* Always do lstat for UNIX calls. */
5175 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5176 DEBUG(3,("call_trans2qfilepathinfo: "
5177 "SMB_VFS_LSTAT of %s failed (%s)\n",
5178 smb_fname_str_dbg(smb_fname),
5181 map_nt_error_from_unix(errno));
5185 } else if (!VALID_STAT(smb_fname->st) &&
5186 SMB_VFS_STAT(conn, smb_fname) &&
5187 (info_level != SMB_INFO_IS_NAME_VALID)) {
5188 ms_dfs_link = check_msdfs_link(conn,
5189 smb_fname->base_name,
5193 DEBUG(3,("call_trans2qfilepathinfo: "
5194 "SMB_VFS_STAT of %s failed (%s)\n",
5195 smb_fname_str_dbg(smb_fname),
5198 map_nt_error_from_unix(errno));
5203 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5204 get_file_infos(fileid, &delete_pending, &write_time_ts);
5205 if (delete_pending) {
5206 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5211 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5212 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5213 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5215 /* Pull out any data sent here before we realloc. */
5216 switch (info_level) {
5217 case SMB_INFO_QUERY_EAS_FROM_LIST:
5219 /* Pull any EA list from the data portion. */
5222 if (total_data < 4) {
5224 req, NT_STATUS_INVALID_PARAMETER);
5227 ea_size = IVAL(pdata,0);
5229 if (total_data > 0 && ea_size != total_data) {
5230 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5231 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5233 req, NT_STATUS_INVALID_PARAMETER);
5237 if (!lp_ea_support(SNUM(conn))) {
5238 reply_doserror(req, ERRDOS,
5239 ERReasnotsupported);
5243 /* Pull out the list of names. */
5244 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5247 req, NT_STATUS_INVALID_PARAMETER);
5253 case SMB_QUERY_POSIX_LOCK:
5255 if (fsp == NULL || fsp->fh->fd == -1) {
5256 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5260 if (total_data != POSIX_LOCK_DATA_SIZE) {
5262 req, NT_STATUS_INVALID_PARAMETER);
5266 /* Copy the lock range data. */
5267 lock_data = (char *)TALLOC_MEMDUP(
5268 req, pdata, total_data);
5270 reply_nterror(req, NT_STATUS_NO_MEMORY);
5273 lock_data_count = total_data;
5279 *pparams = (char *)SMB_REALLOC(*pparams,2);
5280 if (*pparams == NULL) {
5281 reply_nterror(req, NT_STATUS_NO_MEMORY);
5288 * draft-leach-cifs-v1-spec-02.txt
5289 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5292 * The requested information is placed in the Data portion of the
5293 * transaction response. For the information levels greater than 0x100,
5294 * the transaction response has 1 parameter word which should be
5295 * ignored by the client.
5297 * However Windows only follows this rule for the IS_NAME_VALID call.
5299 switch (info_level) {
5300 case SMB_INFO_IS_NAME_VALID:
5305 if ((info_level & 0xFF00) == 0xFF00) {
5307 * We use levels that start with 0xFF00
5308 * internally to represent SMB2 specific levels
5310 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5314 status = smbd_do_qfilepathinfo(conn, req, info_level,
5316 delete_pending, write_time_ts,
5317 ms_dfs_link, ea_list,
5318 lock_data_count, lock_data,
5319 req->flags2, max_data_bytes,
5320 ppdata, &data_size);
5321 if (!NT_STATUS_IS_OK(status)) {
5322 reply_nterror(req, status);
5326 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5332 /****************************************************************************
5333 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5335 ****************************************************************************/
5337 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5338 connection_struct *conn,
5339 const struct smb_filename *smb_fname_old,
5340 const struct smb_filename *smb_fname_new)
5342 NTSTATUS status = NT_STATUS_OK;
5344 /* source must already exist. */
5345 if (!VALID_STAT(smb_fname_old->st)) {
5346 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5349 /* Disallow if newname already exists. */
5350 if (VALID_STAT(smb_fname_new->st)) {
5351 return NT_STATUS_OBJECT_NAME_COLLISION;
5354 /* No links from a directory. */
5355 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5356 return NT_STATUS_FILE_IS_A_DIRECTORY;
5359 /* Setting a hardlink to/from a stream isn't currently supported. */
5360 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5361 is_ntfs_stream_smb_fname(smb_fname_new)) {
5362 return NT_STATUS_INVALID_PARAMETER;
5365 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5366 smb_fname_old->base_name, smb_fname_new->base_name));
5368 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5369 smb_fname_new->base_name) != 0) {
5370 status = map_nt_error_from_unix(errno);
5371 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5372 nt_errstr(status), smb_fname_old->base_name,
5373 smb_fname_new->base_name));
5378 /****************************************************************************
5379 Deal with setting the time from any of the setfilepathinfo functions.
5380 ****************************************************************************/
5382 NTSTATUS smb_set_file_time(connection_struct *conn,
5384 const struct smb_filename *smb_fname,
5385 struct smb_file_time *ft,
5386 bool setting_write_time)
5388 struct smb_filename *smb_fname_base = NULL;
5390 FILE_NOTIFY_CHANGE_LAST_ACCESS
5391 |FILE_NOTIFY_CHANGE_LAST_WRITE
5392 |FILE_NOTIFY_CHANGE_CREATION;
5395 if (!VALID_STAT(smb_fname->st)) {
5396 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5399 /* get some defaults (no modifications) if any info is zero or -1. */
5400 if (null_timespec(ft->create_time)) {
5401 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5404 if (null_timespec(ft->atime)) {
5405 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5408 if (null_timespec(ft->mtime)) {
5409 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5412 if (!setting_write_time) {
5413 /* ft->mtime comes from change time, not write time. */
5414 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5417 /* Ensure the resolution is the correct for
5418 * what we can store on this filesystem. */
5420 round_timespec(conn->ts_res, &ft->create_time);
5421 round_timespec(conn->ts_res, &ft->ctime);
5422 round_timespec(conn->ts_res, &ft->atime);
5423 round_timespec(conn->ts_res, &ft->mtime);
5425 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5426 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5427 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5428 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5429 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5430 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5431 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5432 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5434 if (setting_write_time) {
5436 * This was a Windows setfileinfo on an open file.
5437 * NT does this a lot. We also need to
5438 * set the time here, as it can be read by
5439 * FindFirst/FindNext and with the patch for bug #2045
5440 * in smbd/fileio.c it ensures that this timestamp is
5441 * kept sticky even after a write. We save the request
5442 * away and will set it on file close and after a write. JRA.
5445 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5446 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5449 if (fsp->base_fsp) {
5450 set_sticky_write_time_fsp(fsp->base_fsp,
5453 set_sticky_write_time_fsp(fsp, ft->mtime);
5456 set_sticky_write_time_path(
5457 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5462 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5464 /* Always call ntimes on the base, even if a stream was passed in. */
5465 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5466 NULL, &smb_fname->st,
5468 if (!NT_STATUS_IS_OK(status)) {
5472 if(file_ntimes(conn, smb_fname_base, ft)!=0) {
5473 TALLOC_FREE(smb_fname_base);
5474 return map_nt_error_from_unix(errno);
5476 TALLOC_FREE(smb_fname_base);
5478 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5479 smb_fname->base_name);
5480 return NT_STATUS_OK;
5483 /****************************************************************************
5484 Deal with setting the dosmode from any of the setfilepathinfo functions.
5485 ****************************************************************************/
5487 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5488 const struct smb_filename *smb_fname,
5491 struct smb_filename *smb_fname_base = NULL;
5494 if (!VALID_STAT(smb_fname->st)) {
5495 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5498 /* Always operate on the base_name, even if a stream was passed in. */
5499 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5500 NULL, &smb_fname->st,
5502 if (!NT_STATUS_IS_OK(status)) {
5507 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5514 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5516 /* check the mode isn't different, before changing it */
5517 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5518 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5519 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5520 (unsigned int)dosmode));
5522 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5524 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5526 smb_fname_str_dbg(smb_fname_base),
5528 status = map_nt_error_from_unix(errno);
5532 status = NT_STATUS_OK;
5534 TALLOC_FREE(smb_fname_base);
5538 /****************************************************************************
5539 Deal with setting the size from any of the setfilepathinfo functions.
5540 ****************************************************************************/
5542 static NTSTATUS smb_set_file_size(connection_struct *conn,
5543 struct smb_request *req,
5545 const struct smb_filename *smb_fname,
5546 const SMB_STRUCT_STAT *psbuf,
5549 NTSTATUS status = NT_STATUS_OK;
5550 struct smb_filename *smb_fname_tmp = NULL;
5551 files_struct *new_fsp = NULL;
5553 if (!VALID_STAT(*psbuf)) {
5554 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5557 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5559 if (size == get_file_size_stat(psbuf)) {
5560 return NT_STATUS_OK;
5563 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5564 smb_fname_str_dbg(smb_fname), (double)size));
5566 if (fsp && fsp->fh->fd != -1) {
5567 /* Handle based call. */
5568 if (vfs_set_filelen(fsp, size) == -1) {
5569 return map_nt_error_from_unix(errno);
5571 trigger_write_time_update_immediate(fsp);
5572 return NT_STATUS_OK;
5575 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5576 if (!NT_STATUS_IS_OK(status)) {
5580 smb_fname_tmp->st = *psbuf;
5582 status = SMB_VFS_CREATE_FILE(
5585 0, /* root_dir_fid */
5586 smb_fname_tmp, /* fname */
5587 FILE_WRITE_ATTRIBUTES, /* access_mask */
5588 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5590 FILE_OPEN, /* create_disposition*/
5591 0, /* create_options */
5592 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5593 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5594 0, /* allocation_size */
5597 &new_fsp, /* result */
5600 TALLOC_FREE(smb_fname_tmp);
5602 if (!NT_STATUS_IS_OK(status)) {
5603 /* NB. We check for open_was_deferred in the caller. */
5607 if (vfs_set_filelen(new_fsp, size) == -1) {
5608 status = map_nt_error_from_unix(errno);
5609 close_file(req, new_fsp,NORMAL_CLOSE);
5613 trigger_write_time_update_immediate(new_fsp);
5614 close_file(req, new_fsp,NORMAL_CLOSE);
5615 return NT_STATUS_OK;
5618 /****************************************************************************
5619 Deal with SMB_INFO_SET_EA.
5620 ****************************************************************************/
5622 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5626 const struct smb_filename *smb_fname)
5628 struct ea_list *ea_list = NULL;
5629 TALLOC_CTX *ctx = NULL;
5630 NTSTATUS status = NT_STATUS_OK;
5632 if (total_data < 10) {
5634 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5635 length. They seem to have no effect. Bug #3212. JRA */
5637 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5638 /* We're done. We only get EA info in this call. */
5639 return NT_STATUS_OK;
5642 return NT_STATUS_INVALID_PARAMETER;
5645 if (IVAL(pdata,0) > total_data) {
5646 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5647 IVAL(pdata,0), (unsigned int)total_data));
5648 return NT_STATUS_INVALID_PARAMETER;
5652 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5654 return NT_STATUS_INVALID_PARAMETER;
5656 status = set_ea(conn, fsp, smb_fname, ea_list);
5661 /****************************************************************************
5662 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5663 ****************************************************************************/
5665 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5670 struct ea_list *ea_list = NULL;
5674 return NT_STATUS_INVALID_HANDLE;
5677 if (!lp_ea_support(SNUM(conn))) {
5678 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5679 "EA's not supported.\n",
5680 (unsigned int)total_data));
5681 return NT_STATUS_EAS_NOT_SUPPORTED;
5684 if (total_data < 10) {
5685 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5687 (unsigned int)total_data));
5688 return NT_STATUS_INVALID_PARAMETER;
5691 ea_list = read_nttrans_ea_list(talloc_tos(),
5696 return NT_STATUS_INVALID_PARAMETER;
5698 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5700 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5701 smb_fname_str_dbg(fsp->fsp_name),
5702 nt_errstr(status) ));
5708 /****************************************************************************
5709 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5710 ****************************************************************************/
5712 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5716 const struct smb_filename *smb_fname)
5718 NTSTATUS status = NT_STATUS_OK;
5719 bool delete_on_close;
5722 if (total_data < 1) {
5723 return NT_STATUS_INVALID_PARAMETER;
5727 return NT_STATUS_INVALID_HANDLE;
5730 delete_on_close = (CVAL(pdata,0) ? True : False);
5731 dosmode = dos_mode(conn, smb_fname);
5733 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5734 "delete_on_close = %u\n",
5735 smb_fname_str_dbg(smb_fname),
5736 (unsigned int)dosmode,
5737 (unsigned int)delete_on_close ));
5739 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5741 if (!NT_STATUS_IS_OK(status)) {
5745 /* The set is across all open files on this dev/inode pair. */
5746 if (!set_delete_on_close(fsp, delete_on_close,
5747 &conn->server_info->utok)) {
5748 return NT_STATUS_ACCESS_DENIED;
5750 return NT_STATUS_OK;
5753 /****************************************************************************
5754 Deal with SMB_FILE_POSITION_INFORMATION.
5755 ****************************************************************************/
5757 static NTSTATUS smb_file_position_information(connection_struct *conn,
5762 uint64_t position_information;
5764 if (total_data < 8) {
5765 return NT_STATUS_INVALID_PARAMETER;
5769 /* Ignore on pathname based set. */
5770 return NT_STATUS_OK;
5773 position_information = (uint64_t)IVAL(pdata,0);
5774 #ifdef LARGE_SMB_OFF_T
5775 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5776 #else /* LARGE_SMB_OFF_T */
5777 if (IVAL(pdata,4) != 0) {
5778 /* more than 32 bits? */
5779 return NT_STATUS_INVALID_PARAMETER;
5781 #endif /* LARGE_SMB_OFF_T */
5783 DEBUG(10,("smb_file_position_information: Set file position "
5784 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5785 (double)position_information));
5786 fsp->fh->position_information = position_information;
5787 return NT_STATUS_OK;
5790 /****************************************************************************
5791 Deal with SMB_FILE_MODE_INFORMATION.
5792 ****************************************************************************/
5794 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5800 if (total_data < 4) {
5801 return NT_STATUS_INVALID_PARAMETER;
5803 mode = IVAL(pdata,0);
5804 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5805 return NT_STATUS_INVALID_PARAMETER;
5807 return NT_STATUS_OK;
5810 /****************************************************************************
5811 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5812 ****************************************************************************/
5814 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5815 struct smb_request *req,
5818 const struct smb_filename *smb_fname)
5820 char *link_target = NULL;
5821 const char *newname = smb_fname->base_name;
5822 NTSTATUS status = NT_STATUS_OK;
5823 TALLOC_CTX *ctx = talloc_tos();
5825 /* Set a symbolic link. */
5826 /* Don't allow this if follow links is false. */
5828 if (total_data == 0) {
5829 return NT_STATUS_INVALID_PARAMETER;
5832 if (!lp_symlinks(SNUM(conn))) {
5833 return NT_STATUS_ACCESS_DENIED;
5836 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5837 total_data, STR_TERMINATE);
5840 return NT_STATUS_INVALID_PARAMETER;
5843 /* !widelinks forces the target path to be within the share. */
5844 /* This means we can interpret the target as a pathname. */
5845 if (!lp_widelinks(SNUM(conn))) {
5846 char *rel_name = NULL;
5847 char *last_dirp = NULL;
5849 if (*link_target == '/') {
5850 /* No absolute paths allowed. */
5851 return NT_STATUS_ACCESS_DENIED;
5853 rel_name = talloc_strdup(ctx,newname);
5855 return NT_STATUS_NO_MEMORY;
5857 last_dirp = strrchr_m(rel_name, '/');
5859 last_dirp[1] = '\0';
5861 rel_name = talloc_strdup(ctx,"./");
5863 return NT_STATUS_NO_MEMORY;
5866 rel_name = talloc_asprintf_append(rel_name,
5870 return NT_STATUS_NO_MEMORY;
5873 status = check_name(conn, rel_name);
5874 if (!NT_STATUS_IS_OK(status)) {
5879 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5880 newname, link_target ));
5882 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5883 return map_nt_error_from_unix(errno);
5886 return NT_STATUS_OK;
5889 /****************************************************************************
5890 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5891 ****************************************************************************/
5893 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5894 struct smb_request *req,
5895 const char *pdata, int total_data,
5896 const struct smb_filename *smb_fname_new)
5898 char *oldname = NULL;
5899 struct smb_filename *smb_fname_old = NULL;
5900 TALLOC_CTX *ctx = talloc_tos();
5901 NTSTATUS status = NT_STATUS_OK;
5903 /* Set a hard link. */
5904 if (total_data == 0) {
5905 return NT_STATUS_INVALID_PARAMETER;
5908 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5909 total_data, STR_TERMINATE, &status);
5910 if (!NT_STATUS_IS_OK(status)) {
5914 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5915 smb_fname_str_dbg(smb_fname_new), oldname));
5917 status = filename_convert(ctx,
5919 req->flags2 & FLAGS2_DFS_PATHNAMES,
5924 if (!NT_STATUS_IS_OK(status)) {
5928 return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
5931 /****************************************************************************
5932 Deal with SMB_FILE_RENAME_INFORMATION.
5933 ****************************************************************************/
5935 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5936 struct smb_request *req,
5940 struct smb_filename *smb_fname_src)
5945 char *newname = NULL;
5946 struct smb_filename *smb_fname_dst = NULL;
5947 bool dest_has_wcard = False;
5948 NTSTATUS status = NT_STATUS_OK;
5950 TALLOC_CTX *ctx = talloc_tos();
5952 if (total_data < 13) {
5953 return NT_STATUS_INVALID_PARAMETER;
5956 overwrite = (CVAL(pdata,0) ? True : False);
5957 root_fid = IVAL(pdata,4);
5958 len = IVAL(pdata,8);
5960 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5961 return NT_STATUS_INVALID_PARAMETER;
5964 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5967 if (!NT_STATUS_IS_OK(status)) {
5971 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5974 status = resolve_dfspath_wcard(ctx, conn,
5975 req->flags2 & FLAGS2_DFS_PATHNAMES,
5979 if (!NT_STATUS_IS_OK(status)) {
5983 /* Check the new name has no '/' characters. */
5984 if (strchr_m(newname, '/')) {
5985 return NT_STATUS_NOT_SUPPORTED;
5988 if (fsp && fsp->base_fsp) {
5989 /* newname must be a stream name. */
5990 if (newname[0] != ':') {
5991 return NT_STATUS_NOT_SUPPORTED;
5994 /* Create an smb_fname to call rename_internals_fsp() with. */
5995 status = create_synthetic_smb_fname(talloc_tos(),
5996 fsp->base_fsp->fsp_name->base_name, newname, NULL,
5998 if (!NT_STATUS_IS_OK(status)) {
6003 * Set the original last component, since
6004 * rename_internals_fsp() requires it.
6006 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6008 if (smb_fname_dst->original_lcomp == NULL) {
6009 status = NT_STATUS_NO_MEMORY;
6015 * Build up an smb_fname_dst based on the filename passed in.
6016 * We basically just strip off the last component, and put on
6017 * the newname instead.
6019 char *base_name = NULL;
6021 /* newname must *not* be a stream name. */
6022 if (newname[0] == ':') {
6023 return NT_STATUS_NOT_SUPPORTED;
6027 * Strip off the last component (filename) of the path passed
6030 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6032 return NT_STATUS_NO_MEMORY;
6034 p = strrchr_m(base_name, '/');
6038 base_name = talloc_strdup(ctx, "./");
6040 return NT_STATUS_NO_MEMORY;
6043 /* Append the new name. */
6044 base_name = talloc_asprintf_append(base_name,
6048 return NT_STATUS_NO_MEMORY;
6051 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6054 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6057 /* If an error we expect this to be
6058 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6060 if (!NT_STATUS_IS_OK(status)) {
6061 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6065 /* Create an smb_fname to call rename_internals_fsp() */
6066 status = create_synthetic_smb_fname(ctx,
6070 if (!NT_STATUS_IS_OK(status)) {
6077 DEBUG(10,("smb_file_rename_information: "
6078 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6079 fsp->fnum, fsp_str_dbg(fsp),
6080 smb_fname_str_dbg(smb_fname_dst)));
6081 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6084 DEBUG(10,("smb_file_rename_information: "
6085 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6086 smb_fname_str_dbg(smb_fname_src),
6087 smb_fname_str_dbg(smb_fname_dst)));
6088 status = rename_internals(ctx, conn, req, smb_fname_src,
6089 smb_fname_dst, 0, overwrite, false,
6091 FILE_WRITE_ATTRIBUTES);
6094 TALLOC_FREE(smb_fname_dst);
6098 /****************************************************************************
6099 Deal with SMB_SET_POSIX_ACL.
6100 ****************************************************************************/
6102 #if defined(HAVE_POSIX_ACLS)
6103 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6107 const struct smb_filename *smb_fname)
6109 uint16 posix_acl_version;
6110 uint16 num_file_acls;
6111 uint16 num_def_acls;
6112 bool valid_file_acls = True;
6113 bool valid_def_acls = True;
6115 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6116 return NT_STATUS_INVALID_PARAMETER;
6118 posix_acl_version = SVAL(pdata,0);
6119 num_file_acls = SVAL(pdata,2);
6120 num_def_acls = SVAL(pdata,4);
6122 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6123 valid_file_acls = False;
6127 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6128 valid_def_acls = False;
6132 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6133 return NT_STATUS_INVALID_PARAMETER;
6136 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6137 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6138 return NT_STATUS_INVALID_PARAMETER;
6141 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6142 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6143 (unsigned int)num_file_acls,
6144 (unsigned int)num_def_acls));
6146 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6147 smb_fname->base_name, num_file_acls,
6148 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6149 return map_nt_error_from_unix(errno);
6152 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6153 smb_fname->base_name, &smb_fname->st, num_def_acls,
6154 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6155 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6156 return map_nt_error_from_unix(errno);
6158 return NT_STATUS_OK;
6162 /****************************************************************************
6163 Deal with SMB_SET_POSIX_LOCK.
6164 ****************************************************************************/
6166 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6167 struct smb_request *req,
6175 bool blocking_lock = False;
6176 enum brl_type lock_type;
6178 NTSTATUS status = NT_STATUS_OK;
6180 if (fsp == NULL || fsp->fh->fd == -1) {
6181 return NT_STATUS_INVALID_HANDLE;
6184 if (total_data != POSIX_LOCK_DATA_SIZE) {
6185 return NT_STATUS_INVALID_PARAMETER;
6188 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6189 case POSIX_LOCK_TYPE_READ:
6190 lock_type = READ_LOCK;
6192 case POSIX_LOCK_TYPE_WRITE:
6193 /* Return the right POSIX-mappable error code for files opened read-only. */
6194 if (!fsp->can_write) {
6195 return NT_STATUS_INVALID_HANDLE;
6197 lock_type = WRITE_LOCK;
6199 case POSIX_LOCK_TYPE_UNLOCK:
6200 lock_type = UNLOCK_LOCK;
6203 return NT_STATUS_INVALID_PARAMETER;
6206 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6207 blocking_lock = False;
6208 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6209 blocking_lock = True;
6211 return NT_STATUS_INVALID_PARAMETER;
6214 if (!lp_blocking_locks(SNUM(conn))) {
6215 blocking_lock = False;
6218 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6219 #if defined(HAVE_LONGLONG)
6220 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6221 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6222 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6223 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6224 #else /* HAVE_LONGLONG */
6225 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6226 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6227 #endif /* HAVE_LONGLONG */
6229 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6230 "lock_pid = %u, count = %.0f, offset = %.0f\n",
6232 (unsigned int)lock_type,
6233 (unsigned int)lock_pid,
6237 if (lock_type == UNLOCK_LOCK) {
6238 status = do_unlock(smbd_messaging_context(),
6245 uint32 block_smbpid;
6247 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
6259 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6261 * A blocking lock was requested. Package up
6262 * this smb into a queued request and push it
6263 * onto the blocking lock queue.
6265 if(push_blocking_lock_request(br_lck,
6268 -1, /* infinite timeout. */
6276 TALLOC_FREE(br_lck);
6280 TALLOC_FREE(br_lck);
6286 /****************************************************************************
6287 Deal with SMB_SET_FILE_BASIC_INFO.
6288 ****************************************************************************/
6290 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6294 const struct smb_filename *smb_fname)
6296 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6297 struct smb_file_time ft;
6299 NTSTATUS status = NT_STATUS_OK;
6303 if (total_data < 36) {
6304 return NT_STATUS_INVALID_PARAMETER;
6307 /* Set the attributes */
6308 dosmode = IVAL(pdata,32);
6309 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6310 if (!NT_STATUS_IS_OK(status)) {
6315 ft.create_time = interpret_long_date(pdata);
6318 ft.atime = interpret_long_date(pdata+8);
6321 ft.mtime = interpret_long_date(pdata+16);
6324 ft.ctime = interpret_long_date(pdata+24);
6326 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6327 smb_fname_str_dbg(smb_fname)));
6329 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6333 /****************************************************************************
6334 Deal with SMB_INFO_STANDARD.
6335 ****************************************************************************/
6337 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6341 const struct smb_filename *smb_fname)
6343 struct smb_file_time ft;
6347 if (total_data < 12) {
6348 return NT_STATUS_INVALID_PARAMETER;
6352 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6354 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6356 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6358 DEBUG(10,("smb_set_info_standard: file %s\n",
6359 smb_fname_str_dbg(smb_fname)));
6361 return smb_set_file_time(conn,
6368 /****************************************************************************
6369 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6370 ****************************************************************************/
6372 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6373 struct smb_request *req,
6377 struct smb_filename *smb_fname)
6379 uint64_t allocation_size = 0;
6380 NTSTATUS status = NT_STATUS_OK;
6381 files_struct *new_fsp = NULL;
6383 if (!VALID_STAT(smb_fname->st)) {
6384 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6387 if (total_data < 8) {
6388 return NT_STATUS_INVALID_PARAMETER;
6391 allocation_size = (uint64_t)IVAL(pdata,0);
6392 #ifdef LARGE_SMB_OFF_T
6393 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6394 #else /* LARGE_SMB_OFF_T */
6395 if (IVAL(pdata,4) != 0) {
6396 /* more than 32 bits? */
6397 return NT_STATUS_INVALID_PARAMETER;
6399 #endif /* LARGE_SMB_OFF_T */
6401 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6402 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6403 (double)allocation_size));
6405 if (allocation_size) {
6406 allocation_size = smb_roundup(conn, allocation_size);
6409 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6410 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6411 (double)allocation_size));
6413 if (fsp && fsp->fh->fd != -1) {
6414 /* Open file handle. */
6415 /* Only change if needed. */
6416 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6417 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6418 return map_nt_error_from_unix(errno);
6421 /* But always update the time. */
6423 * This is equivalent to a write. Ensure it's seen immediately
6424 * if there are no pending writes.
6426 trigger_write_time_update_immediate(fsp);
6427 return NT_STATUS_OK;
6430 /* Pathname or stat or directory file. */
6431 status = SMB_VFS_CREATE_FILE(
6434 0, /* root_dir_fid */
6435 smb_fname, /* fname */
6436 FILE_WRITE_DATA, /* access_mask */
6437 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6439 FILE_OPEN, /* create_disposition*/
6440 0, /* create_options */
6441 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6442 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6443 0, /* allocation_size */
6446 &new_fsp, /* result */
6449 if (!NT_STATUS_IS_OK(status)) {
6450 /* NB. We check for open_was_deferred in the caller. */
6454 /* Only change if needed. */
6455 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6456 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6457 status = map_nt_error_from_unix(errno);
6458 close_file(req, new_fsp, NORMAL_CLOSE);
6463 /* Changing the allocation size should set the last mod time. */
6465 * This is equivalent to a write. Ensure it's seen immediately
6466 * if there are no pending writes.
6468 trigger_write_time_update_immediate(new_fsp);
6470 close_file(req, new_fsp, NORMAL_CLOSE);
6471 return NT_STATUS_OK;
6474 /****************************************************************************
6475 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6476 ****************************************************************************/
6478 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6479 struct smb_request *req,
6483 const struct smb_filename *smb_fname)
6487 if (total_data < 8) {
6488 return NT_STATUS_INVALID_PARAMETER;
6491 size = IVAL(pdata,0);
6492 #ifdef LARGE_SMB_OFF_T
6493 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6494 #else /* LARGE_SMB_OFF_T */
6495 if (IVAL(pdata,4) != 0) {
6496 /* more than 32 bits? */
6497 return NT_STATUS_INVALID_PARAMETER;
6499 #endif /* LARGE_SMB_OFF_T */
6500 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6501 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6504 return smb_set_file_size(conn, req,
6511 /****************************************************************************
6512 Allow a UNIX info mknod.
6513 ****************************************************************************/
6515 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6518 const struct smb_filename *smb_fname)
6520 uint32 file_type = IVAL(pdata,56);
6521 #if defined(HAVE_MAKEDEV)
6522 uint32 dev_major = IVAL(pdata,60);
6523 uint32 dev_minor = IVAL(pdata,68);
6525 SMB_DEV_T dev = (SMB_DEV_T)0;
6526 uint32 raw_unixmode = IVAL(pdata,84);
6530 if (total_data < 100) {
6531 return NT_STATUS_INVALID_PARAMETER;
6534 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6535 PERM_NEW_FILE, &unixmode);
6536 if (!NT_STATUS_IS_OK(status)) {
6540 #if defined(HAVE_MAKEDEV)
6541 dev = makedev(dev_major, dev_minor);
6544 switch (file_type) {
6545 #if defined(S_IFIFO)
6546 case UNIX_TYPE_FIFO:
6547 unixmode |= S_IFIFO;
6550 #if defined(S_IFSOCK)
6551 case UNIX_TYPE_SOCKET:
6552 unixmode |= S_IFSOCK;
6555 #if defined(S_IFCHR)
6556 case UNIX_TYPE_CHARDEV:
6557 unixmode |= S_IFCHR;
6560 #if defined(S_IFBLK)
6561 case UNIX_TYPE_BLKDEV:
6562 unixmode |= S_IFBLK;
6566 return NT_STATUS_INVALID_PARAMETER;
6569 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6570 "%.0f mode 0%o for file %s\n", (double)dev,
6571 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6573 /* Ok - do the mknod. */
6574 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6575 return map_nt_error_from_unix(errno);
6578 /* If any of the other "set" calls fail we
6579 * don't want to end up with a half-constructed mknod.
6582 if (lp_inherit_perms(SNUM(conn))) {
6584 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6586 return NT_STATUS_NO_MEMORY;
6588 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6590 TALLOC_FREE(parent);
6593 return NT_STATUS_OK;
6596 /****************************************************************************
6597 Deal with SMB_SET_FILE_UNIX_BASIC.
6598 ****************************************************************************/
6600 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6601 struct smb_request *req,
6605 const struct smb_filename *smb_fname)
6607 struct smb_file_time ft;
6608 uint32 raw_unixmode;
6611 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6612 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6613 NTSTATUS status = NT_STATUS_OK;
6614 bool delete_on_fail = False;
6615 enum perm_type ptype;
6616 files_struct *all_fsps = NULL;
6617 bool modify_mtime = true;
6619 SMB_STRUCT_STAT sbuf;
6623 if (total_data < 100) {
6624 return NT_STATUS_INVALID_PARAMETER;
6627 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6628 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6629 size=IVAL(pdata,0); /* first 8 Bytes are size */
6630 #ifdef LARGE_SMB_OFF_T
6631 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6632 #else /* LARGE_SMB_OFF_T */
6633 if (IVAL(pdata,4) != 0) {
6634 /* more than 32 bits? */
6635 return NT_STATUS_INVALID_PARAMETER;
6637 #endif /* LARGE_SMB_OFF_T */
6640 ft.atime = interpret_long_date(pdata+24); /* access_time */
6641 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6642 set_owner = (uid_t)IVAL(pdata,40);
6643 set_grp = (gid_t)IVAL(pdata,48);
6644 raw_unixmode = IVAL(pdata,84);
6646 if (VALID_STAT(smb_fname->st)) {
6647 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6648 ptype = PERM_EXISTING_DIR;
6650 ptype = PERM_EXISTING_FILE;
6653 ptype = PERM_NEW_FILE;
6656 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6658 if (!NT_STATUS_IS_OK(status)) {
6662 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6663 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6664 smb_fname_str_dbg(smb_fname), (double)size,
6665 (unsigned int)set_owner, (unsigned int)set_grp,
6666 (int)raw_unixmode));
6668 sbuf = smb_fname->st;
6670 if (!VALID_STAT(sbuf)) {
6671 struct smb_filename *smb_fname_tmp = NULL;
6673 * The only valid use of this is to create character and block
6674 * devices, and named pipes. This is deprecated (IMHO) and
6675 * a new info level should be used for mknod. JRA.
6678 status = smb_unix_mknod(conn,
6682 if (!NT_STATUS_IS_OK(status)) {
6686 status = copy_smb_filename(talloc_tos(), smb_fname,
6688 if (!NT_STATUS_IS_OK(status)) {
6692 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6693 status = map_nt_error_from_unix(errno);
6694 TALLOC_FREE(smb_fname_tmp);
6695 SMB_VFS_UNLINK(conn, smb_fname);
6699 sbuf = smb_fname_tmp->st;
6700 TALLOC_FREE(smb_fname_tmp);
6702 /* Ensure we don't try and change anything else. */
6703 raw_unixmode = SMB_MODE_NO_CHANGE;
6704 size = get_file_size_stat(&sbuf);
6705 ft.atime = sbuf.st_ex_atime;
6706 ft.mtime = sbuf.st_ex_mtime;
6708 * We continue here as we might want to change the
6711 delete_on_fail = True;
6715 /* Horrible backwards compatibility hack as an old server bug
6716 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6720 size = get_file_size_stat(&sbuf);
6725 * Deal with the UNIX specific mode set.
6728 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6729 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6730 "setting mode 0%o for file %s\n",
6731 (unsigned int)unixmode,
6732 smb_fname_str_dbg(smb_fname)));
6733 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6734 return map_nt_error_from_unix(errno);
6739 * Deal with the UNIX specific uid set.
6742 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6743 (sbuf.st_ex_uid != set_owner)) {
6746 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6747 "changing owner %u for path %s\n",
6748 (unsigned int)set_owner,
6749 smb_fname_str_dbg(smb_fname)));
6751 if (S_ISLNK(sbuf.st_ex_mode)) {
6752 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6753 set_owner, (gid_t)-1);
6755 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6756 set_owner, (gid_t)-1);
6760 status = map_nt_error_from_unix(errno);
6761 if (delete_on_fail) {
6762 SMB_VFS_UNLINK(conn, smb_fname);
6769 * Deal with the UNIX specific gid set.
6772 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6773 (sbuf.st_ex_gid != set_grp)) {
6774 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6775 "changing group %u for file %s\n",
6776 (unsigned int)set_owner,
6777 smb_fname_str_dbg(smb_fname)));
6778 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6780 status = map_nt_error_from_unix(errno);
6781 if (delete_on_fail) {
6782 SMB_VFS_UNLINK(conn, smb_fname);
6788 /* Deal with any size changes. */
6790 status = smb_set_file_size(conn, req,
6795 if (!NT_STATUS_IS_OK(status)) {
6799 /* Deal with any time changes. */
6800 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6801 /* No change, don't cancel anything. */
6805 id = vfs_file_id_from_sbuf(conn, &sbuf);
6806 for(all_fsps = file_find_di_first(id); all_fsps;
6807 all_fsps = file_find_di_next(all_fsps)) {
6809 * We're setting the time explicitly for UNIX.
6810 * Cancel any pending changes over all handles.
6812 all_fsps->update_write_time_on_close = false;
6813 TALLOC_FREE(all_fsps->update_write_time_event);
6817 * Override the "setting_write_time"
6818 * parameter here as it almost does what
6819 * we need. Just remember if we modified
6820 * mtime and send the notify ourselves.
6822 if (null_timespec(ft.mtime)) {
6823 modify_mtime = false;
6826 status = smb_set_file_time(conn,
6832 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6833 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6838 /****************************************************************************
6839 Deal with SMB_SET_FILE_UNIX_INFO2.
6840 ****************************************************************************/
6842 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6843 struct smb_request *req,
6847 const struct smb_filename *smb_fname)
6853 if (total_data < 116) {
6854 return NT_STATUS_INVALID_PARAMETER;
6857 /* Start by setting all the fields that are common between UNIX_BASIC
6860 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6862 if (!NT_STATUS_IS_OK(status)) {
6866 smb_fflags = IVAL(pdata, 108);
6867 smb_fmask = IVAL(pdata, 112);
6869 /* NB: We should only attempt to alter the file flags if the client
6870 * sends a non-zero mask.
6872 if (smb_fmask != 0) {
6873 int stat_fflags = 0;
6875 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6876 smb_fmask, &stat_fflags)) {
6877 /* Client asked to alter a flag we don't understand. */
6878 return NT_STATUS_INVALID_PARAMETER;
6881 if (fsp && fsp->fh->fd != -1) {
6882 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6883 return NT_STATUS_NOT_SUPPORTED;
6885 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
6886 stat_fflags) != 0) {
6887 return map_nt_error_from_unix(errno);
6892 /* XXX: need to add support for changing the create_time here. You
6893 * can do this for paths on Darwin with setattrlist(2). The right way
6894 * to hook this up is probably by extending the VFS utimes interface.
6897 return NT_STATUS_OK;
6900 /****************************************************************************
6901 Create a directory with POSIX semantics.
6902 ****************************************************************************/
6904 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6905 struct smb_request *req,
6908 struct smb_filename *smb_fname,
6909 int *pdata_return_size)
6911 NTSTATUS status = NT_STATUS_OK;
6912 uint32 raw_unixmode = 0;
6913 uint32 mod_unixmode = 0;
6914 mode_t unixmode = (mode_t)0;
6915 files_struct *fsp = NULL;
6916 uint16 info_level_return = 0;
6918 char *pdata = *ppdata;
6920 if (total_data < 18) {
6921 return NT_STATUS_INVALID_PARAMETER;
6924 raw_unixmode = IVAL(pdata,8);
6925 /* Next 4 bytes are not yet defined. */
6927 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6928 PERM_NEW_DIR, &unixmode);
6929 if (!NT_STATUS_IS_OK(status)) {
6933 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6935 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6936 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
6938 status = SMB_VFS_CREATE_FILE(
6941 0, /* root_dir_fid */
6942 smb_fname, /* fname */
6943 FILE_READ_ATTRIBUTES, /* access_mask */
6944 FILE_SHARE_NONE, /* share_access */
6945 FILE_CREATE, /* create_disposition*/
6946 FILE_DIRECTORY_FILE, /* create_options */
6947 mod_unixmode, /* file_attributes */
6948 0, /* oplock_request */
6949 0, /* allocation_size */
6955 if (NT_STATUS_IS_OK(status)) {
6956 close_file(req, fsp, NORMAL_CLOSE);
6959 info_level_return = SVAL(pdata,16);
6961 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6962 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6963 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6964 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6966 *pdata_return_size = 12;
6969 /* Realloc the data size */
6970 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6971 if (*ppdata == NULL) {
6972 *pdata_return_size = 0;
6973 return NT_STATUS_NO_MEMORY;
6977 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6978 SSVAL(pdata,2,0); /* No fnum. */
6979 SIVAL(pdata,4,info); /* Was directory created. */
6981 switch (info_level_return) {
6982 case SMB_QUERY_FILE_UNIX_BASIC:
6983 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6984 SSVAL(pdata,10,0); /* Padding. */
6985 store_file_unix_basic(conn, pdata + 12, fsp,
6988 case SMB_QUERY_FILE_UNIX_INFO2:
6989 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6990 SSVAL(pdata,10,0); /* Padding. */
6991 store_file_unix_basic_info2(conn, pdata + 12, fsp,
6995 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6996 SSVAL(pdata,10,0); /* Padding. */
7003 /****************************************************************************
7004 Open/Create a file with POSIX semantics.
7005 ****************************************************************************/
7007 static NTSTATUS smb_posix_open(connection_struct *conn,
7008 struct smb_request *req,
7011 struct smb_filename *smb_fname,
7012 int *pdata_return_size)
7014 bool extended_oplock_granted = False;
7015 char *pdata = *ppdata;
7017 uint32 wire_open_mode = 0;
7018 uint32 raw_unixmode = 0;
7019 uint32 mod_unixmode = 0;
7020 uint32 create_disp = 0;
7021 uint32 access_mask = 0;
7022 uint32 create_options = 0;
7023 NTSTATUS status = NT_STATUS_OK;
7024 mode_t unixmode = (mode_t)0;
7025 files_struct *fsp = NULL;
7026 int oplock_request = 0;
7028 uint16 info_level_return = 0;
7030 if (total_data < 18) {
7031 return NT_STATUS_INVALID_PARAMETER;
7034 flags = IVAL(pdata,0);
7035 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7036 if (oplock_request) {
7037 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7040 wire_open_mode = IVAL(pdata,4);
7042 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7043 return smb_posix_mkdir(conn, req,
7050 switch (wire_open_mode & SMB_ACCMODE) {
7052 access_mask = FILE_READ_DATA;
7055 access_mask = FILE_WRITE_DATA;
7058 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
7061 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7062 (unsigned int)wire_open_mode ));
7063 return NT_STATUS_INVALID_PARAMETER;
7066 wire_open_mode &= ~SMB_ACCMODE;
7068 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
7069 create_disp = FILE_CREATE;
7070 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
7071 create_disp = FILE_OVERWRITE_IF;
7072 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
7073 create_disp = FILE_OPEN_IF;
7074 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
7075 create_disp = FILE_OPEN;
7077 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7078 (unsigned int)wire_open_mode ));
7079 return NT_STATUS_INVALID_PARAMETER;
7082 raw_unixmode = IVAL(pdata,8);
7083 /* Next 4 bytes are not yet defined. */
7085 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7086 (VALID_STAT(smb_fname->st) ?
7087 PERM_EXISTING_FILE : PERM_NEW_FILE),
7090 if (!NT_STATUS_IS_OK(status)) {
7094 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7096 if (wire_open_mode & SMB_O_SYNC) {
7097 create_options |= FILE_WRITE_THROUGH;
7099 if (wire_open_mode & SMB_O_APPEND) {
7100 access_mask |= FILE_APPEND_DATA;
7102 if (wire_open_mode & SMB_O_DIRECT) {
7103 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7106 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7107 smb_fname_str_dbg(smb_fname),
7108 (unsigned int)wire_open_mode,
7109 (unsigned int)unixmode ));
7111 status = SMB_VFS_CREATE_FILE(
7114 0, /* root_dir_fid */
7115 smb_fname, /* fname */
7116 access_mask, /* access_mask */
7117 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7119 create_disp, /* create_disposition*/
7120 FILE_NON_DIRECTORY_FILE, /* create_options */
7121 mod_unixmode, /* file_attributes */
7122 oplock_request, /* oplock_request */
7123 0, /* allocation_size */
7129 if (!NT_STATUS_IS_OK(status)) {
7133 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7134 extended_oplock_granted = True;
7137 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7138 extended_oplock_granted = True;
7141 info_level_return = SVAL(pdata,16);
7143 /* Allocate the correct return size. */
7145 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7146 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7147 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7148 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7150 *pdata_return_size = 12;
7153 /* Realloc the data size */
7154 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7155 if (*ppdata == NULL) {
7156 close_file(req, fsp, ERROR_CLOSE);
7157 *pdata_return_size = 0;
7158 return NT_STATUS_NO_MEMORY;
7162 if (extended_oplock_granted) {
7163 if (flags & REQUEST_BATCH_OPLOCK) {
7164 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7166 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7168 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7169 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7171 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7174 SSVAL(pdata,2,fsp->fnum);
7175 SIVAL(pdata,4,info); /* Was file created etc. */
7177 switch (info_level_return) {
7178 case SMB_QUERY_FILE_UNIX_BASIC:
7179 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7180 SSVAL(pdata,10,0); /* padding. */
7181 store_file_unix_basic(conn, pdata + 12, fsp,
7184 case SMB_QUERY_FILE_UNIX_INFO2:
7185 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7186 SSVAL(pdata,10,0); /* padding. */
7187 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7191 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7192 SSVAL(pdata,10,0); /* padding. */
7195 return NT_STATUS_OK;
7198 /****************************************************************************
7199 Delete a file with POSIX semantics.
7200 ****************************************************************************/
7202 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7203 struct smb_request *req,
7206 struct smb_filename *smb_fname)
7208 NTSTATUS status = NT_STATUS_OK;
7209 files_struct *fsp = NULL;
7213 int create_options = 0;
7215 struct share_mode_lock *lck = NULL;
7217 if (total_data < 2) {
7218 return NT_STATUS_INVALID_PARAMETER;
7221 flags = SVAL(pdata,0);
7223 if (!VALID_STAT(smb_fname->st)) {
7224 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7227 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7228 !VALID_STAT_OF_DIR(smb_fname->st)) {
7229 return NT_STATUS_NOT_A_DIRECTORY;
7232 DEBUG(10,("smb_posix_unlink: %s %s\n",
7233 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7234 smb_fname_str_dbg(smb_fname)));
7236 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7237 create_options |= FILE_DIRECTORY_FILE;
7240 status = SMB_VFS_CREATE_FILE(
7243 0, /* root_dir_fid */
7244 smb_fname, /* fname */
7245 DELETE_ACCESS, /* access_mask */
7246 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7248 FILE_OPEN, /* create_disposition*/
7249 create_options, /* create_options */
7250 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7251 0, /* oplock_request */
7252 0, /* allocation_size */
7258 if (!NT_STATUS_IS_OK(status)) {
7263 * Don't lie to client. If we can't really delete due to
7264 * non-POSIX opens return SHARING_VIOLATION.
7267 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7270 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7271 "lock for file %s\n", fsp_str_dbg(fsp)));
7272 close_file(req, fsp, NORMAL_CLOSE);
7273 return NT_STATUS_INVALID_PARAMETER;
7277 * See if others still have the file open. If this is the case, then
7278 * don't delete. If all opens are POSIX delete we can set the delete
7279 * on close disposition.
7281 for (i=0; i<lck->num_share_modes; i++) {
7282 struct share_mode_entry *e = &lck->share_modes[i];
7283 if (is_valid_share_mode_entry(e)) {
7284 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7287 /* Fail with sharing violation. */
7288 close_file(req, fsp, NORMAL_CLOSE);
7290 return NT_STATUS_SHARING_VIOLATION;
7295 * Set the delete on close.
7297 status = smb_set_file_disposition_info(conn,
7303 if (!NT_STATUS_IS_OK(status)) {
7304 close_file(req, fsp, NORMAL_CLOSE);
7309 return close_file(req, fsp, NORMAL_CLOSE);
7312 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7313 struct smb_request *req,
7314 TALLOC_CTX *mem_ctx,
7315 uint16_t info_level,
7317 struct smb_filename *smb_fname,
7318 char **ppdata, int total_data,
7321 char *pdata = *ppdata;
7322 NTSTATUS status = NT_STATUS_OK;
7323 int data_return_size = 0;
7327 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7328 return NT_STATUS_INVALID_LEVEL;
7331 if (!CAN_WRITE(conn)) {
7332 /* Allow POSIX opens. The open path will deny
7333 * any non-readonly opens. */
7334 if (info_level != SMB_POSIX_PATH_OPEN) {
7335 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7339 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7340 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7341 fsp ? fsp->fnum : -1, info_level, total_data));
7343 switch (info_level) {
7345 case SMB_INFO_STANDARD:
7347 status = smb_set_info_standard(conn,
7355 case SMB_INFO_SET_EA:
7357 status = smb_info_set_ea(conn,
7365 case SMB_SET_FILE_BASIC_INFO:
7366 case SMB_FILE_BASIC_INFORMATION:
7368 status = smb_set_file_basic_info(conn,
7376 case SMB_FILE_ALLOCATION_INFORMATION:
7377 case SMB_SET_FILE_ALLOCATION_INFO:
7379 status = smb_set_file_allocation_info(conn, req,
7387 case SMB_FILE_END_OF_FILE_INFORMATION:
7388 case SMB_SET_FILE_END_OF_FILE_INFO:
7390 status = smb_set_file_end_of_file_info(conn, req,
7398 case SMB_FILE_DISPOSITION_INFORMATION:
7399 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7402 /* JRA - We used to just ignore this on a path ?
7403 * Shouldn't this be invalid level on a pathname
7406 if (tran_call != TRANSACT2_SETFILEINFO) {
7407 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7410 status = smb_set_file_disposition_info(conn,
7418 case SMB_FILE_POSITION_INFORMATION:
7420 status = smb_file_position_information(conn,
7427 case SMB_FILE_FULL_EA_INFORMATION:
7429 status = smb_set_file_full_ea_info(conn,
7436 /* From tridge Samba4 :
7437 * MODE_INFORMATION in setfileinfo (I have no
7438 * idea what "mode information" on a file is - it takes a value of 0,
7439 * 2, 4 or 6. What could it be?).
7442 case SMB_FILE_MODE_INFORMATION:
7444 status = smb_file_mode_information(conn,
7451 * CIFS UNIX extensions.
7454 case SMB_SET_FILE_UNIX_BASIC:
7456 status = smb_set_file_unix_basic(conn, req,
7464 case SMB_SET_FILE_UNIX_INFO2:
7466 status = smb_set_file_unix_info2(conn, req,
7474 case SMB_SET_FILE_UNIX_LINK:
7477 /* We must have a pathname for this. */
7478 return NT_STATUS_INVALID_LEVEL;
7480 status = smb_set_file_unix_link(conn, req, pdata,
7481 total_data, smb_fname);
7485 case SMB_SET_FILE_UNIX_HLINK:
7488 /* We must have a pathname for this. */
7489 return NT_STATUS_INVALID_LEVEL;
7491 status = smb_set_file_unix_hlink(conn, req,
7497 case SMB_FILE_RENAME_INFORMATION:
7499 status = smb_file_rename_information(conn, req,
7505 #if defined(HAVE_POSIX_ACLS)
7506 case SMB_SET_POSIX_ACL:
7508 status = smb_set_posix_acl(conn,
7517 case SMB_SET_POSIX_LOCK:
7520 return NT_STATUS_INVALID_LEVEL;
7522 status = smb_set_posix_lock(conn, req,
7523 pdata, total_data, fsp);
7527 case SMB_POSIX_PATH_OPEN:
7530 /* We must have a pathname for this. */
7531 return NT_STATUS_INVALID_LEVEL;
7534 status = smb_posix_open(conn, req,
7542 case SMB_POSIX_PATH_UNLINK:
7545 /* We must have a pathname for this. */
7546 return NT_STATUS_INVALID_LEVEL;
7549 status = smb_posix_unlink(conn, req,
7557 return NT_STATUS_INVALID_LEVEL;
7560 if (!NT_STATUS_IS_OK(status)) {
7564 *ret_data_size = data_return_size;
7565 return NT_STATUS_OK;
7568 /****************************************************************************
7569 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7570 ****************************************************************************/
7572 static void call_trans2setfilepathinfo(connection_struct *conn,
7573 struct smb_request *req,
7574 unsigned int tran_call,
7575 char **pparams, int total_params,
7576 char **ppdata, int total_data,
7577 unsigned int max_data_bytes)
7579 char *params = *pparams;
7580 char *pdata = *ppdata;
7582 struct smb_filename *smb_fname = NULL;
7583 files_struct *fsp = NULL;
7584 NTSTATUS status = NT_STATUS_OK;
7585 int data_return_size = 0;
7588 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7592 if (tran_call == TRANSACT2_SETFILEINFO) {
7593 if (total_params < 4) {
7594 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7598 fsp = file_fsp(req, SVAL(params,0));
7599 /* Basic check for non-null fsp. */
7600 if (!check_fsp_open(conn, req, fsp)) {
7603 info_level = SVAL(params,2);
7605 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7607 if (!NT_STATUS_IS_OK(status)) {
7608 reply_nterror(req, status);
7612 if(fsp->is_directory || fsp->fh->fd == -1) {
7614 * This is actually a SETFILEINFO on a directory
7615 * handle (returned from an NT SMB). NT5.0 seems
7616 * to do this call. JRA.
7618 if (INFO_LEVEL_IS_UNIX(info_level)) {
7619 /* Always do lstat for UNIX calls. */
7620 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7621 DEBUG(3,("call_trans2setfilepathinfo: "
7622 "SMB_VFS_LSTAT of %s failed "
7624 smb_fname_str_dbg(smb_fname),
7626 reply_nterror(req, map_nt_error_from_unix(errno));
7630 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7631 DEBUG(3,("call_trans2setfilepathinfo: "
7632 "fileinfo of %s failed (%s)\n",
7633 smb_fname_str_dbg(smb_fname),
7635 reply_nterror(req, map_nt_error_from_unix(errno));
7639 } else if (fsp->print_file) {
7641 * Doing a DELETE_ON_CLOSE should cancel a print job.
7643 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7644 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
7646 DEBUG(3,("call_trans2setfilepathinfo: "
7647 "Cancelling print job (%s)\n",
7651 send_trans2_replies(conn, req, params, 2,
7656 reply_doserror(req, ERRDOS, ERRbadpath);
7661 * Original code - this is an open file.
7663 if (!check_fsp(conn, req, fsp)) {
7667 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7668 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7669 "of fnum %d failed (%s)\n", fsp->fnum,
7671 reply_nterror(req, map_nt_error_from_unix(errno));
7679 if (total_params < 7) {
7680 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7684 info_level = SVAL(params,0);
7685 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
7686 total_params - 6, STR_TERMINATE,
7688 if (!NT_STATUS_IS_OK(status)) {
7689 reply_nterror(req, status);
7693 status = filename_convert(req, conn,
7694 req->flags2 & FLAGS2_DFS_PATHNAMES,
7699 if (!NT_STATUS_IS_OK(status)) {
7700 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7701 reply_botherror(req,
7702 NT_STATUS_PATH_NOT_COVERED,
7703 ERRSRV, ERRbadpath);
7706 reply_nterror(req, status);
7710 if (INFO_LEVEL_IS_UNIX(info_level)) {
7712 * For CIFS UNIX extensions the target name may not exist.
7715 /* Always do lstat for UNIX calls. */
7716 SMB_VFS_LSTAT(conn, smb_fname);
7718 } else if (!VALID_STAT(smb_fname->st) &&
7719 SMB_VFS_STAT(conn, smb_fname)) {
7720 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7722 smb_fname_str_dbg(smb_fname),
7724 reply_nterror(req, map_nt_error_from_unix(errno));
7729 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7730 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
7731 fsp ? fsp->fnum : -1, info_level,total_data));
7733 /* Realloc the parameter size */
7734 *pparams = (char *)SMB_REALLOC(*pparams,2);
7735 if (*pparams == NULL) {
7736 reply_nterror(req, NT_STATUS_NO_MEMORY);
7743 status = smbd_do_setfilepathinfo(conn, req, req,
7749 if (!NT_STATUS_IS_OK(status)) {
7750 if (open_was_deferred(req->mid)) {
7751 /* We have re-scheduled this call. */
7754 if (blocking_lock_was_deferred(req->mid)) {
7755 /* We have re-scheduled this call. */
7758 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7759 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7760 ERRSRV, ERRbadpath);
7763 if (info_level == SMB_POSIX_PATH_OPEN) {
7764 reply_openerror(req, status);
7768 reply_nterror(req, status);
7772 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7778 /****************************************************************************
7779 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7780 ****************************************************************************/
7782 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7783 char **pparams, int total_params,
7784 char **ppdata, int total_data,
7785 unsigned int max_data_bytes)
7787 struct smb_filename *smb_dname = NULL;
7788 char *params = *pparams;
7789 char *pdata = *ppdata;
7790 char *directory = NULL;
7791 NTSTATUS status = NT_STATUS_OK;
7792 struct ea_list *ea_list = NULL;
7793 TALLOC_CTX *ctx = talloc_tos();
7795 if (!CAN_WRITE(conn)) {
7796 reply_doserror(req, ERRSRV, ERRaccess);
7800 if (total_params < 5) {
7801 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7805 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7806 total_params - 4, STR_TERMINATE,
7808 if (!NT_STATUS_IS_OK(status)) {
7809 reply_nterror(req, status);
7813 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7815 status = filename_convert(ctx,
7817 req->flags2 & FLAGS2_DFS_PATHNAMES,
7823 if (!NT_STATUS_IS_OK(status)) {
7824 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7825 reply_botherror(req,
7826 NT_STATUS_PATH_NOT_COVERED,
7827 ERRSRV, ERRbadpath);
7830 reply_nterror(req, status);
7834 /* Any data in this call is an EA list. */
7835 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7836 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7841 * OS/2 workplace shell seems to send SET_EA requests of "null"
7842 * length (4 bytes containing IVAL 4).
7843 * They seem to have no effect. Bug #3212. JRA.
7846 if (total_data != 4) {
7847 if (total_data < 10) {
7848 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7852 if (IVAL(pdata,0) > total_data) {
7853 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7854 IVAL(pdata,0), (unsigned int)total_data));
7855 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7859 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7862 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7866 /* If total_data == 4 Windows doesn't care what values
7867 * are placed in that field, it just ignores them.
7868 * The System i QNTC IBM SMB client puts bad values here,
7869 * so ignore them. */
7871 status = create_directory(conn, req, smb_dname);
7873 if (!NT_STATUS_IS_OK(status)) {
7874 reply_nterror(req, status);
7878 /* Try and set any given EA. */
7880 status = set_ea(conn, NULL, smb_dname, ea_list);
7881 if (!NT_STATUS_IS_OK(status)) {
7882 reply_nterror(req, status);
7887 /* Realloc the parameter and data sizes */
7888 *pparams = (char *)SMB_REALLOC(*pparams,2);
7889 if(*pparams == NULL) {
7890 reply_nterror(req, NT_STATUS_NO_MEMORY);
7897 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7900 TALLOC_FREE(smb_dname);
7904 /****************************************************************************
7905 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7906 We don't actually do this - we just send a null response.
7907 ****************************************************************************/
7909 static void call_trans2findnotifyfirst(connection_struct *conn,
7910 struct smb_request *req,
7911 char **pparams, int total_params,
7912 char **ppdata, int total_data,
7913 unsigned int max_data_bytes)
7915 char *params = *pparams;
7918 if (total_params < 6) {
7919 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7923 info_level = SVAL(params,4);
7924 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7926 switch (info_level) {
7931 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7935 /* Realloc the parameter and data sizes */
7936 *pparams = (char *)SMB_REALLOC(*pparams,6);
7937 if (*pparams == NULL) {
7938 reply_nterror(req, NT_STATUS_NO_MEMORY);
7943 SSVAL(params,0,fnf_handle);
7944 SSVAL(params,2,0); /* No changes */
7945 SSVAL(params,4,0); /* No EA errors */
7952 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7957 /****************************************************************************
7958 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7959 changes). Currently this does nothing.
7960 ****************************************************************************/
7962 static void call_trans2findnotifynext(connection_struct *conn,
7963 struct smb_request *req,
7964 char **pparams, int total_params,
7965 char **ppdata, int total_data,
7966 unsigned int max_data_bytes)
7968 char *params = *pparams;
7970 DEBUG(3,("call_trans2findnotifynext\n"));
7972 /* Realloc the parameter and data sizes */
7973 *pparams = (char *)SMB_REALLOC(*pparams,4);
7974 if (*pparams == NULL) {
7975 reply_nterror(req, NT_STATUS_NO_MEMORY);
7980 SSVAL(params,0,0); /* No changes */
7981 SSVAL(params,2,0); /* No EA errors */
7983 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7988 /****************************************************************************
7989 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7990 ****************************************************************************/
7992 static void call_trans2getdfsreferral(connection_struct *conn,
7993 struct smb_request *req,
7994 char **pparams, int total_params,
7995 char **ppdata, int total_data,
7996 unsigned int max_data_bytes)
7998 char *params = *pparams;
7999 char *pathname = NULL;
8001 int max_referral_level;
8002 NTSTATUS status = NT_STATUS_OK;
8003 TALLOC_CTX *ctx = talloc_tos();
8005 DEBUG(10,("call_trans2getdfsreferral\n"));
8007 if (total_params < 3) {
8008 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8012 max_referral_level = SVAL(params,0);
8014 if(!lp_host_msdfs()) {
8015 reply_doserror(req, ERRDOS, ERRbadfunc);
8019 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
8020 total_params - 2, STR_TERMINATE);
8022 reply_nterror(req, NT_STATUS_NOT_FOUND);
8025 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8026 ppdata,&status)) < 0) {
8027 reply_nterror(req, status);
8031 SSVAL(req->inbuf, smb_flg2,
8032 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8033 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8038 #define LMCAT_SPL 0x53
8039 #define LMFUNC_GETJOBID 0x60
8041 /****************************************************************************
8042 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8043 ****************************************************************************/
8045 static void call_trans2ioctl(connection_struct *conn,
8046 struct smb_request *req,
8047 char **pparams, int total_params,
8048 char **ppdata, int total_data,
8049 unsigned int max_data_bytes)
8051 char *pdata = *ppdata;
8052 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8054 /* check for an invalid fid before proceeding */
8057 reply_doserror(req, ERRDOS, ERRbadfid);
8061 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8062 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8063 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8064 if (*ppdata == NULL) {
8065 reply_nterror(req, NT_STATUS_NO_MEMORY);
8070 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8071 CAN ACCEPT THIS IN UNICODE. JRA. */
8073 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
8074 srvstr_push(pdata, req->flags2, pdata + 2,
8075 global_myname(), 15,
8076 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8077 srvstr_push(pdata, req->flags2, pdata+18,
8078 lp_servicename(SNUM(conn)), 13,
8079 STR_ASCII|STR_TERMINATE); /* Service name */
8080 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8085 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8086 reply_doserror(req, ERRSRV, ERRerror);
8089 /****************************************************************************
8090 Reply to a SMBfindclose (stop trans2 directory search).
8091 ****************************************************************************/
8093 void reply_findclose(struct smb_request *req)
8096 struct smbd_server_connection *sconn = smbd_server_conn;
8098 START_PROFILE(SMBfindclose);
8101 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8102 END_PROFILE(SMBfindclose);
8106 dptr_num = SVALS(req->vwv+0, 0);
8108 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8110 dptr_close(sconn, &dptr_num);
8112 reply_outbuf(req, 0, 0);
8114 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8116 END_PROFILE(SMBfindclose);
8120 /****************************************************************************
8121 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8122 ****************************************************************************/
8124 void reply_findnclose(struct smb_request *req)
8128 START_PROFILE(SMBfindnclose);
8131 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8132 END_PROFILE(SMBfindnclose);
8136 dptr_num = SVAL(req->vwv+0, 0);
8138 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8140 /* We never give out valid handles for a
8141 findnotifyfirst - so any dptr_num is ok here.
8144 reply_outbuf(req, 0, 0);
8146 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8148 END_PROFILE(SMBfindnclose);
8152 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8153 struct trans_state *state)
8155 if (Protocol >= PROTOCOL_NT1) {
8156 req->flags2 |= 0x40; /* IS_LONG_NAME */
8157 SSVAL(req->inbuf,smb_flg2,req->flags2);
8160 if (conn->encrypt_level == Required && !req->encrypted) {
8161 if (state->call != TRANSACT2_QFSINFO &&
8162 state->call != TRANSACT2_SETFSINFO) {
8163 DEBUG(0,("handle_trans2: encryption required "
8165 (unsigned int)state->call));
8166 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8171 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8173 /* Now we must call the relevant TRANS2 function */
8174 switch(state->call) {
8175 case TRANSACT2_OPEN:
8177 START_PROFILE(Trans2_open);
8178 call_trans2open(conn, req,
8179 &state->param, state->total_param,
8180 &state->data, state->total_data,
8181 state->max_data_return);
8182 END_PROFILE(Trans2_open);
8186 case TRANSACT2_FINDFIRST:
8188 START_PROFILE(Trans2_findfirst);
8189 call_trans2findfirst(conn, req,
8190 &state->param, state->total_param,
8191 &state->data, state->total_data,
8192 state->max_data_return);
8193 END_PROFILE(Trans2_findfirst);
8197 case TRANSACT2_FINDNEXT:
8199 START_PROFILE(Trans2_findnext);
8200 call_trans2findnext(conn, req,
8201 &state->param, state->total_param,
8202 &state->data, state->total_data,
8203 state->max_data_return);
8204 END_PROFILE(Trans2_findnext);
8208 case TRANSACT2_QFSINFO:
8210 START_PROFILE(Trans2_qfsinfo);
8211 call_trans2qfsinfo(conn, req,
8212 &state->param, state->total_param,
8213 &state->data, state->total_data,
8214 state->max_data_return);
8215 END_PROFILE(Trans2_qfsinfo);
8219 case TRANSACT2_SETFSINFO:
8221 START_PROFILE(Trans2_setfsinfo);
8222 call_trans2setfsinfo(conn, req,
8223 &state->param, state->total_param,
8224 &state->data, state->total_data,
8225 state->max_data_return);
8226 END_PROFILE(Trans2_setfsinfo);
8230 case TRANSACT2_QPATHINFO:
8231 case TRANSACT2_QFILEINFO:
8233 START_PROFILE(Trans2_qpathinfo);
8234 call_trans2qfilepathinfo(conn, req, state->call,
8235 &state->param, state->total_param,
8236 &state->data, state->total_data,
8237 state->max_data_return);
8238 END_PROFILE(Trans2_qpathinfo);
8242 case TRANSACT2_SETPATHINFO:
8243 case TRANSACT2_SETFILEINFO:
8245 START_PROFILE(Trans2_setpathinfo);
8246 call_trans2setfilepathinfo(conn, req, state->call,
8247 &state->param, state->total_param,
8248 &state->data, state->total_data,
8249 state->max_data_return);
8250 END_PROFILE(Trans2_setpathinfo);
8254 case TRANSACT2_FINDNOTIFYFIRST:
8256 START_PROFILE(Trans2_findnotifyfirst);
8257 call_trans2findnotifyfirst(conn, req,
8258 &state->param, state->total_param,
8259 &state->data, state->total_data,
8260 state->max_data_return);
8261 END_PROFILE(Trans2_findnotifyfirst);
8265 case TRANSACT2_FINDNOTIFYNEXT:
8267 START_PROFILE(Trans2_findnotifynext);
8268 call_trans2findnotifynext(conn, req,
8269 &state->param, state->total_param,
8270 &state->data, state->total_data,
8271 state->max_data_return);
8272 END_PROFILE(Trans2_findnotifynext);
8276 case TRANSACT2_MKDIR:
8278 START_PROFILE(Trans2_mkdir);
8279 call_trans2mkdir(conn, req,
8280 &state->param, state->total_param,
8281 &state->data, state->total_data,
8282 state->max_data_return);
8283 END_PROFILE(Trans2_mkdir);
8287 case TRANSACT2_GET_DFS_REFERRAL:
8289 START_PROFILE(Trans2_get_dfs_referral);
8290 call_trans2getdfsreferral(conn, req,
8291 &state->param, state->total_param,
8292 &state->data, state->total_data,
8293 state->max_data_return);
8294 END_PROFILE(Trans2_get_dfs_referral);
8298 case TRANSACT2_IOCTL:
8300 START_PROFILE(Trans2_ioctl);
8301 call_trans2ioctl(conn, req,
8302 &state->param, state->total_param,
8303 &state->data, state->total_data,
8304 state->max_data_return);
8305 END_PROFILE(Trans2_ioctl);
8310 /* Error in request */
8311 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8312 reply_doserror(req, ERRSRV,ERRerror);
8316 /****************************************************************************
8317 Reply to a SMBtrans2.
8318 ****************************************************************************/
8320 void reply_trans2(struct smb_request *req)
8322 connection_struct *conn = req->conn;
8327 unsigned int tran_call;
8328 struct trans_state *state;
8331 START_PROFILE(SMBtrans2);
8333 if (req->wct < 14) {
8334 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8335 END_PROFILE(SMBtrans2);
8339 dsoff = SVAL(req->vwv+12, 0);
8340 dscnt = SVAL(req->vwv+11, 0);
8341 psoff = SVAL(req->vwv+10, 0);
8342 pscnt = SVAL(req->vwv+9, 0);
8343 tran_call = SVAL(req->vwv+14, 0);
8345 result = allow_new_trans(conn->pending_trans, req->mid);
8346 if (!NT_STATUS_IS_OK(result)) {
8347 DEBUG(2, ("Got invalid trans2 request: %s\n",
8348 nt_errstr(result)));
8349 reply_nterror(req, result);
8350 END_PROFILE(SMBtrans2);
8355 switch (tran_call) {
8356 /* List the allowed trans2 calls on IPC$ */
8357 case TRANSACT2_OPEN:
8358 case TRANSACT2_GET_DFS_REFERRAL:
8359 case TRANSACT2_QFILEINFO:
8360 case TRANSACT2_QFSINFO:
8361 case TRANSACT2_SETFSINFO:
8364 reply_doserror(req, ERRSRV, ERRaccess);
8365 END_PROFILE(SMBtrans2);
8370 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8371 DEBUG(0, ("talloc failed\n"));
8372 reply_nterror(req, NT_STATUS_NO_MEMORY);
8373 END_PROFILE(SMBtrans2);
8377 state->cmd = SMBtrans2;
8379 state->mid = req->mid;
8380 state->vuid = req->vuid;
8381 state->setup_count = SVAL(req->vwv+13, 0);
8382 state->setup = NULL;
8383 state->total_param = SVAL(req->vwv+0, 0);
8384 state->param = NULL;
8385 state->total_data = SVAL(req->vwv+1, 0);
8387 state->max_param_return = SVAL(req->vwv+2, 0);
8388 state->max_data_return = SVAL(req->vwv+3, 0);
8389 state->max_setup_return = SVAL(req->vwv+4, 0);
8390 state->close_on_completion = BITSETW(req->vwv+5, 0);
8391 state->one_way = BITSETW(req->vwv+5, 1);
8393 state->call = tran_call;
8395 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8396 is so as a sanity check */
8397 if (state->setup_count != 1) {
8399 * Need to have rc=0 for ioctl to get job id for OS/2.
8400 * Network printing will fail if function is not successful.
8401 * Similar function in reply.c will be used if protocol
8402 * is LANMAN1.0 instead of LM1.2X002.
8403 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8404 * outbuf doesn't have to be set(only job id is used).
8406 if ( (state->setup_count == 4)
8407 && (tran_call == TRANSACT2_IOCTL)
8408 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8409 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8410 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8412 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8413 DEBUG(2,("Transaction is %d\n",tran_call));
8415 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8416 END_PROFILE(SMBtrans2);
8421 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8424 if (state->total_data) {
8426 if (trans_oob(state->total_data, 0, dscnt)
8427 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8431 /* Can't use talloc here, the core routines do realloc on the
8432 * params and data. */
8433 state->data = (char *)SMB_MALLOC(state->total_data);
8434 if (state->data == NULL) {
8435 DEBUG(0,("reply_trans2: data malloc fail for %u "
8436 "bytes !\n", (unsigned int)state->total_data));
8438 reply_nterror(req, NT_STATUS_NO_MEMORY);
8439 END_PROFILE(SMBtrans2);
8443 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8446 if (state->total_param) {
8448 if (trans_oob(state->total_param, 0, pscnt)
8449 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8453 /* Can't use talloc here, the core routines do realloc on the
8454 * params and data. */
8455 state->param = (char *)SMB_MALLOC(state->total_param);
8456 if (state->param == NULL) {
8457 DEBUG(0,("reply_trans: param malloc fail for %u "
8458 "bytes !\n", (unsigned int)state->total_param));
8459 SAFE_FREE(state->data);
8461 reply_nterror(req, NT_STATUS_NO_MEMORY);
8462 END_PROFILE(SMBtrans2);
8466 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8469 state->received_data = dscnt;
8470 state->received_param = pscnt;
8472 if ((state->received_param == state->total_param) &&
8473 (state->received_data == state->total_data)) {
8475 handle_trans2(conn, req, state);
8477 SAFE_FREE(state->data);
8478 SAFE_FREE(state->param);
8480 END_PROFILE(SMBtrans2);
8484 DLIST_ADD(conn->pending_trans, state);
8486 /* We need to send an interim response then receive the rest
8487 of the parameter/data bytes */
8488 reply_outbuf(req, 0, 0);
8489 show_msg((char *)req->outbuf);
8490 END_PROFILE(SMBtrans2);
8495 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8496 SAFE_FREE(state->data);
8497 SAFE_FREE(state->param);
8499 END_PROFILE(SMBtrans2);
8500 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8504 /****************************************************************************
8505 Reply to a SMBtranss2
8506 ****************************************************************************/
8508 void reply_transs2(struct smb_request *req)
8510 connection_struct *conn = req->conn;
8511 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8512 struct trans_state *state;
8514 START_PROFILE(SMBtranss2);
8516 show_msg((char *)req->inbuf);
8519 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8520 END_PROFILE(SMBtranss2);
8524 for (state = conn->pending_trans; state != NULL;
8525 state = state->next) {
8526 if (state->mid == req->mid) {
8531 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8532 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8533 END_PROFILE(SMBtranss2);
8537 /* Revise state->total_param and state->total_data in case they have
8538 changed downwards */
8540 if (SVAL(req->vwv+0, 0) < state->total_param)
8541 state->total_param = SVAL(req->vwv+0, 0);
8542 if (SVAL(req->vwv+1, 0) < state->total_data)
8543 state->total_data = SVAL(req->vwv+1, 0);
8545 pcnt = SVAL(req->vwv+2, 0);
8546 poff = SVAL(req->vwv+3, 0);
8547 pdisp = SVAL(req->vwv+4, 0);
8549 dcnt = SVAL(req->vwv+5, 0);
8550 doff = SVAL(req->vwv+6, 0);
8551 ddisp = SVAL(req->vwv+7, 0);
8553 state->received_param += pcnt;
8554 state->received_data += dcnt;
8556 if ((state->received_data > state->total_data) ||
8557 (state->received_param > state->total_param))
8561 if (trans_oob(state->total_param, pdisp, pcnt)
8562 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8565 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8569 if (trans_oob(state->total_data, ddisp, dcnt)
8570 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8573 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8576 if ((state->received_param < state->total_param) ||
8577 (state->received_data < state->total_data)) {
8578 END_PROFILE(SMBtranss2);
8582 handle_trans2(conn, req, state);
8584 DLIST_REMOVE(conn->pending_trans, state);
8585 SAFE_FREE(state->data);
8586 SAFE_FREE(state->param);
8589 END_PROFILE(SMBtranss2);
8594 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8595 DLIST_REMOVE(conn->pending_trans, state);
8596 SAFE_FREE(state->data);
8597 SAFE_FREE(state->param);
8599 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8600 END_PROFILE(SMBtranss2);