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 /* We have data_size bytes to put EA's into. */
4383 size_t total_ea_len = 0;
4384 struct ea_list *ea_file_list = NULL;
4386 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4388 /*TODO: add filtering and index handling */
4391 get_ea_list_from_file(mem_ctx, conn, fsp,
4392 smb_fname->base_name,
4394 if (!ea_file_list) {
4395 return NT_STATUS_NO_EAS_ON_FILE;
4398 status = fill_ea_chained_buffer(mem_ctx,
4402 conn, ea_file_list);
4403 if (!NT_STATUS_IS_OK(status)) {
4409 case SMB_FILE_BASIC_INFORMATION:
4410 case SMB_QUERY_FILE_BASIC_INFO:
4412 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4413 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4414 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4416 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4420 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4421 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4422 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4423 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4424 SIVAL(pdata,32,mode);
4426 DEBUG(5,("SMB_QFBI - "));
4427 DEBUG(5,("create: %s ", ctime(&create_time)));
4428 DEBUG(5,("access: %s ", ctime(&atime)));
4429 DEBUG(5,("write: %s ", ctime(&mtime)));
4430 DEBUG(5,("change: %s ", ctime(&c_time)));
4431 DEBUG(5,("mode: %x\n", mode));
4434 case SMB_FILE_STANDARD_INFORMATION:
4435 case SMB_QUERY_FILE_STANDARD_INFO:
4437 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4439 SOFF_T(pdata,0,allocation_size);
4440 SOFF_T(pdata,8,file_size);
4441 SIVAL(pdata,16,nlink);
4442 SCVAL(pdata,20,delete_pending?1:0);
4443 SCVAL(pdata,21,(mode&aDIR)?1:0);
4444 SSVAL(pdata,22,0); /* Padding. */
4447 case SMB_FILE_EA_INFORMATION:
4448 case SMB_QUERY_FILE_EA_INFO:
4450 unsigned int ea_size =
4451 estimate_ea_size(conn, fsp, smb_fname->base_name);
4452 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4454 SIVAL(pdata,0,ea_size);
4458 /* Get the 8.3 name - used if NT SMB was negotiated. */
4459 case SMB_QUERY_FILE_ALT_NAME_INFO:
4460 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4463 char mangled_name[13];
4464 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4465 if (!name_to_8_3(base_name,mangled_name,
4466 True,conn->params)) {
4467 return NT_STATUS_NO_MEMORY;
4469 len = srvstr_push(dstart, flags2,
4470 pdata+4, mangled_name,
4471 PTR_DIFF(dend, pdata+4),
4473 data_size = 4 + len;
4478 case SMB_QUERY_FILE_NAME_INFO:
4482 this must be *exactly* right for ACLs on mapped drives to work
4484 len = srvstr_push(dstart, flags2,
4486 PTR_DIFF(dend, pdata+4),
4488 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4489 data_size = 4 + len;
4494 case SMB_FILE_ALLOCATION_INFORMATION:
4495 case SMB_QUERY_FILE_ALLOCATION_INFO:
4496 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4498 SOFF_T(pdata,0,allocation_size);
4501 case SMB_FILE_END_OF_FILE_INFORMATION:
4502 case SMB_QUERY_FILE_END_OF_FILEINFO:
4503 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4505 SOFF_T(pdata,0,file_size);
4508 case SMB_QUERY_FILE_ALL_INFO:
4509 case SMB_FILE_ALL_INFORMATION:
4512 unsigned int ea_size =
4513 estimate_ea_size(conn, fsp, smb_fname->base_name);
4514 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4515 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4516 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4517 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4518 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4519 SIVAL(pdata,32,mode);
4520 SIVAL(pdata,36,0); /* padding. */
4522 SOFF_T(pdata,0,allocation_size);
4523 SOFF_T(pdata,8,file_size);
4524 SIVAL(pdata,16,nlink);
4525 SCVAL(pdata,20,delete_pending);
4526 SCVAL(pdata,21,(mode&aDIR)?1:0);
4529 SIVAL(pdata,0,ea_size);
4530 pdata += 4; /* EA info */
4531 len = srvstr_push(dstart, flags2,
4533 PTR_DIFF(dend, pdata+4),
4537 data_size = PTR_DIFF(pdata,(*ppdata));
4541 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4544 unsigned int ea_size =
4545 estimate_ea_size(conn, fsp, smb_fname->base_name);
4546 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4547 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4548 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4549 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4550 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4551 SIVAL(pdata, 0x20, mode);
4552 SIVAL(pdata, 0x24, 0); /* padding. */
4553 SBVAL(pdata, 0x28, allocation_size);
4554 SBVAL(pdata, 0x30, file_size);
4555 SIVAL(pdata, 0x38, nlink);
4556 SCVAL(pdata, 0x3C, delete_pending);
4557 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4558 SSVAL(pdata, 0x3E, 0); /* padding */
4559 SBVAL(pdata, 0x40, file_index);
4560 SIVAL(pdata, 0x48, ea_size);
4561 SIVAL(pdata, 0x4C, access_mask);
4562 SBVAL(pdata, 0x50, pos);
4563 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4564 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4568 len = srvstr_push(dstart, flags2,
4570 PTR_DIFF(dend, pdata+4),
4574 data_size = PTR_DIFF(pdata,(*ppdata));
4577 case SMB_FILE_INTERNAL_INFORMATION:
4579 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4580 SBVAL(pdata, 0, file_index);
4584 case SMB_FILE_ACCESS_INFORMATION:
4585 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4586 SIVAL(pdata, 0, access_mask);
4590 case SMB_FILE_NAME_INFORMATION:
4591 /* Pathname with leading '\'. */
4594 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4595 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4596 SIVAL(pdata,0,byte_len);
4597 data_size = 4 + byte_len;
4601 case SMB_FILE_DISPOSITION_INFORMATION:
4602 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4604 SCVAL(pdata,0,delete_pending);
4607 case SMB_FILE_POSITION_INFORMATION:
4608 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4610 SOFF_T(pdata,0,pos);
4613 case SMB_FILE_MODE_INFORMATION:
4614 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4615 SIVAL(pdata,0,mode);
4619 case SMB_FILE_ALIGNMENT_INFORMATION:
4620 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4621 SIVAL(pdata,0,0); /* No alignment needed. */
4626 * NT4 server just returns "invalid query" to this - if we try
4627 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4630 /* The first statement above is false - verified using Thursby
4631 * client against NT4 -- gcolley.
4633 case SMB_QUERY_FILE_STREAM_INFO:
4634 case SMB_FILE_STREAM_INFORMATION: {
4635 unsigned int num_streams;
4636 struct stream_struct *streams;
4638 DEBUG(10,("smbd_do_qfilepathinfo: "
4639 "SMB_FILE_STREAM_INFORMATION\n"));
4641 if (is_ntfs_stream_smb_fname(smb_fname)) {
4642 return NT_STATUS_INVALID_PARAMETER;
4645 status = SMB_VFS_STREAMINFO(
4646 conn, fsp, smb_fname->base_name, talloc_tos(),
4647 &num_streams, &streams);
4649 if (!NT_STATUS_IS_OK(status)) {
4650 DEBUG(10, ("could not get stream info: %s\n",
4651 nt_errstr(status)));
4655 status = marshall_stream_info(num_streams, streams,
4656 pdata, max_data_bytes,
4659 if (!NT_STATUS_IS_OK(status)) {
4660 DEBUG(10, ("marshall_stream_info failed: %s\n",
4661 nt_errstr(status)));
4665 TALLOC_FREE(streams);
4669 case SMB_QUERY_COMPRESSION_INFO:
4670 case SMB_FILE_COMPRESSION_INFORMATION:
4671 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4672 SOFF_T(pdata,0,file_size);
4673 SIVAL(pdata,8,0); /* ??? */
4674 SIVAL(pdata,12,0); /* ??? */
4678 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4679 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4680 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4681 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4682 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4683 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4684 SOFF_T(pdata,32,allocation_size);
4685 SOFF_T(pdata,40,file_size);
4686 SIVAL(pdata,48,mode);
4687 SIVAL(pdata,52,0); /* ??? */
4691 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4692 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4693 SIVAL(pdata,0,mode);
4699 * CIFS UNIX Extensions.
4702 case SMB_QUERY_FILE_UNIX_BASIC:
4704 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4705 data_size = PTR_DIFF(pdata,(*ppdata));
4709 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4711 for (i=0; i<100; i++)
4712 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4718 case SMB_QUERY_FILE_UNIX_INFO2:
4720 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4721 data_size = PTR_DIFF(pdata,(*ppdata));
4725 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4727 for (i=0; i<100; i++)
4728 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4734 case SMB_QUERY_FILE_UNIX_LINK:
4737 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4740 return NT_STATUS_NO_MEMORY;
4743 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4745 if(!S_ISLNK(psbuf->st_ex_mode)) {
4746 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4749 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4751 len = SMB_VFS_READLINK(conn,
4752 smb_fname->base_name,
4755 return map_nt_error_from_unix(errno);
4758 len = srvstr_push(dstart, flags2,
4760 PTR_DIFF(dend, pdata),
4763 data_size = PTR_DIFF(pdata,(*ppdata));
4768 #if defined(HAVE_POSIX_ACLS)
4769 case SMB_QUERY_POSIX_ACL:
4771 SMB_ACL_T file_acl = NULL;
4772 SMB_ACL_T def_acl = NULL;
4773 uint16 num_file_acls = 0;
4774 uint16 num_def_acls = 0;
4776 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4777 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4780 SMB_VFS_SYS_ACL_GET_FILE(conn,
4781 smb_fname->base_name,
4782 SMB_ACL_TYPE_ACCESS);
4785 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4786 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4787 "not implemented on "
4788 "filesystem containing %s\n",
4789 smb_fname->base_name));
4790 return NT_STATUS_NOT_IMPLEMENTED;
4793 if (S_ISDIR(psbuf->st_ex_mode)) {
4794 if (fsp && fsp->is_directory) {
4796 SMB_VFS_SYS_ACL_GET_FILE(
4798 fsp->fsp_name->base_name,
4799 SMB_ACL_TYPE_DEFAULT);
4802 SMB_VFS_SYS_ACL_GET_FILE(
4804 smb_fname->base_name,
4805 SMB_ACL_TYPE_DEFAULT);
4807 def_acl = free_empty_sys_acl(conn, def_acl);
4810 num_file_acls = count_acl_entries(conn, file_acl);
4811 num_def_acls = count_acl_entries(conn, def_acl);
4813 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4814 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4816 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4817 SMB_POSIX_ACL_HEADER_SIZE) ));
4819 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4822 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4824 return NT_STATUS_BUFFER_TOO_SMALL;
4827 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4828 SSVAL(pdata,2,num_file_acls);
4829 SSVAL(pdata,4,num_def_acls);
4830 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4832 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4835 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4837 return NT_STATUS_INTERNAL_ERROR;
4839 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4841 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4844 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4846 return NT_STATUS_INTERNAL_ERROR;
4850 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4853 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4855 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4861 case SMB_QUERY_POSIX_LOCK:
4866 enum brl_type lock_type;
4868 /* We need an open file with a real fd for this. */
4869 if (!fsp || fsp->is_directory || fsp->fh->fd == -1) {
4870 return NT_STATUS_INVALID_LEVEL;
4873 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4874 return NT_STATUS_INVALID_PARAMETER;
4877 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4878 case POSIX_LOCK_TYPE_READ:
4879 lock_type = READ_LOCK;
4881 case POSIX_LOCK_TYPE_WRITE:
4882 lock_type = WRITE_LOCK;
4884 case POSIX_LOCK_TYPE_UNLOCK:
4886 /* There's no point in asking for an unlock... */
4887 return NT_STATUS_INVALID_PARAMETER;
4890 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4891 #if defined(HAVE_LONGLONG)
4892 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4893 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4894 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4895 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4896 #else /* HAVE_LONGLONG */
4897 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4898 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4899 #endif /* HAVE_LONGLONG */
4901 status = query_lock(fsp,
4908 if (ERROR_WAS_LOCK_DENIED(status)) {
4909 /* Here we need to report who has it locked... */
4910 data_size = POSIX_LOCK_DATA_SIZE;
4912 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4913 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4914 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4915 #if defined(HAVE_LONGLONG)
4916 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4917 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4918 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4919 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4920 #else /* HAVE_LONGLONG */
4921 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4922 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4923 #endif /* HAVE_LONGLONG */
4925 } else if (NT_STATUS_IS_OK(status)) {
4926 /* For success we just return a copy of what we sent
4927 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4928 data_size = POSIX_LOCK_DATA_SIZE;
4929 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4930 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4938 return NT_STATUS_INVALID_LEVEL;
4941 *pdata_size = data_size;
4942 return NT_STATUS_OK;
4945 /****************************************************************************
4946 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4947 file name or file id).
4948 ****************************************************************************/
4950 static void call_trans2qfilepathinfo(connection_struct *conn,
4951 struct smb_request *req,
4952 unsigned int tran_call,
4953 char **pparams, int total_params,
4954 char **ppdata, int total_data,
4955 unsigned int max_data_bytes)
4957 char *params = *pparams;
4958 char *pdata = *ppdata;
4960 unsigned int data_size = 0;
4961 unsigned int param_size = 2;
4962 struct smb_filename *smb_fname = NULL;
4963 bool delete_pending = False;
4964 struct timespec write_time_ts;
4965 files_struct *fsp = NULL;
4966 struct file_id fileid;
4967 struct ea_list *ea_list = NULL;
4968 int lock_data_count = 0;
4969 char *lock_data = NULL;
4970 bool ms_dfs_link = false;
4971 NTSTATUS status = NT_STATUS_OK;
4974 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4978 ZERO_STRUCT(write_time_ts);
4980 if (tran_call == TRANSACT2_QFILEINFO) {
4981 if (total_params < 4) {
4982 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4987 call_trans2qpipeinfo(conn, req, tran_call,
4988 pparams, total_params,
4994 fsp = file_fsp(req, SVAL(params,0));
4995 info_level = SVAL(params,2);
4997 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
4999 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5000 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5004 /* Initial check for valid fsp ptr. */
5005 if (!check_fsp_open(conn, req, fsp)) {
5009 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5011 if (!NT_STATUS_IS_OK(status)) {
5012 reply_nterror(req, status);
5016 if(fsp->fake_file_handle) {
5018 * This is actually for the QUOTA_FAKE_FILE --metze
5021 /* We know this name is ok, it's already passed the checks. */
5023 } else if(fsp->is_directory || fsp->fh->fd == -1) {
5025 * This is actually a QFILEINFO on a directory
5026 * handle (returned from an NT SMB). NT5.0 seems
5027 * to do this call. JRA.
5030 if (INFO_LEVEL_IS_UNIX(info_level)) {
5031 /* Always do lstat for UNIX calls. */
5032 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5033 DEBUG(3,("call_trans2qfilepathinfo: "
5034 "SMB_VFS_LSTAT of %s failed "
5036 smb_fname_str_dbg(smb_fname),
5039 map_nt_error_from_unix(errno));
5042 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5043 DEBUG(3,("call_trans2qfilepathinfo: "
5044 "SMB_VFS_STAT of %s failed (%s)\n",
5045 smb_fname_str_dbg(smb_fname),
5048 map_nt_error_from_unix(errno));
5052 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5053 get_file_infos(fileid, &delete_pending, &write_time_ts);
5056 * Original code - this is an open file.
5058 if (!check_fsp(conn, req, fsp)) {
5062 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5063 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5064 fsp->fnum, strerror(errno)));
5066 map_nt_error_from_unix(errno));
5069 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5070 get_file_infos(fileid, &delete_pending, &write_time_ts);
5077 if (total_params < 7) {
5078 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5082 info_level = SVAL(params,0);
5084 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5086 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5087 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5091 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
5093 STR_TERMINATE, &status);
5094 if (!NT_STATUS_IS_OK(status)) {
5095 reply_nterror(req, status);
5099 status = filename_convert(req,
5101 req->flags2 & FLAGS2_DFS_PATHNAMES,
5106 if (!NT_STATUS_IS_OK(status)) {
5107 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5108 reply_botherror(req,
5109 NT_STATUS_PATH_NOT_COVERED,
5110 ERRSRV, ERRbadpath);
5113 reply_nterror(req, status);
5117 /* If this is a stream, check if there is a delete_pending. */
5118 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5119 && is_ntfs_stream_smb_fname(smb_fname)) {
5120 struct smb_filename *smb_fname_base = NULL;
5122 /* Create an smb_filename with stream_name == NULL. */
5124 create_synthetic_smb_fname(talloc_tos(),
5125 smb_fname->base_name,
5128 if (!NT_STATUS_IS_OK(status)) {
5129 reply_nterror(req, status);
5133 if (INFO_LEVEL_IS_UNIX(info_level)) {
5134 /* Always do lstat for UNIX calls. */
5135 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5136 DEBUG(3,("call_trans2qfilepathinfo: "
5137 "SMB_VFS_LSTAT of %s failed "
5139 smb_fname_str_dbg(smb_fname_base),
5141 TALLOC_FREE(smb_fname_base);
5143 map_nt_error_from_unix(errno));
5147 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5148 DEBUG(3,("call_trans2qfilepathinfo: "
5149 "fileinfo of %s failed "
5151 smb_fname_str_dbg(smb_fname_base),
5153 TALLOC_FREE(smb_fname_base);
5155 map_nt_error_from_unix(errno));
5160 fileid = vfs_file_id_from_sbuf(conn,
5161 &smb_fname_base->st);
5162 TALLOC_FREE(smb_fname_base);
5163 get_file_infos(fileid, &delete_pending, NULL);
5164 if (delete_pending) {
5165 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5170 if (INFO_LEVEL_IS_UNIX(info_level)) {
5171 /* Always do lstat for UNIX calls. */
5172 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5173 DEBUG(3,("call_trans2qfilepathinfo: "
5174 "SMB_VFS_LSTAT of %s failed (%s)\n",
5175 smb_fname_str_dbg(smb_fname),
5178 map_nt_error_from_unix(errno));
5182 } else if (!VALID_STAT(smb_fname->st) &&
5183 SMB_VFS_STAT(conn, smb_fname) &&
5184 (info_level != SMB_INFO_IS_NAME_VALID)) {
5185 ms_dfs_link = check_msdfs_link(conn,
5186 smb_fname->base_name,
5190 DEBUG(3,("call_trans2qfilepathinfo: "
5191 "SMB_VFS_STAT of %s failed (%s)\n",
5192 smb_fname_str_dbg(smb_fname),
5195 map_nt_error_from_unix(errno));
5200 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5201 get_file_infos(fileid, &delete_pending, &write_time_ts);
5202 if (delete_pending) {
5203 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5208 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5209 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5210 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5212 /* Pull out any data sent here before we realloc. */
5213 switch (info_level) {
5214 case SMB_INFO_QUERY_EAS_FROM_LIST:
5216 /* Pull any EA list from the data portion. */
5219 if (total_data < 4) {
5221 req, NT_STATUS_INVALID_PARAMETER);
5224 ea_size = IVAL(pdata,0);
5226 if (total_data > 0 && ea_size != total_data) {
5227 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5228 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5230 req, NT_STATUS_INVALID_PARAMETER);
5234 if (!lp_ea_support(SNUM(conn))) {
5235 reply_doserror(req, ERRDOS,
5236 ERReasnotsupported);
5240 /* Pull out the list of names. */
5241 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5244 req, NT_STATUS_INVALID_PARAMETER);
5250 case SMB_QUERY_POSIX_LOCK:
5252 if (fsp == NULL || fsp->fh->fd == -1) {
5253 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5257 if (total_data != POSIX_LOCK_DATA_SIZE) {
5259 req, NT_STATUS_INVALID_PARAMETER);
5263 /* Copy the lock range data. */
5264 lock_data = (char *)TALLOC_MEMDUP(
5265 req, pdata, total_data);
5267 reply_nterror(req, NT_STATUS_NO_MEMORY);
5270 lock_data_count = total_data;
5276 *pparams = (char *)SMB_REALLOC(*pparams,2);
5277 if (*pparams == NULL) {
5278 reply_nterror(req, NT_STATUS_NO_MEMORY);
5285 * draft-leach-cifs-v1-spec-02.txt
5286 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5289 * The requested information is placed in the Data portion of the
5290 * transaction response. For the information levels greater than 0x100,
5291 * the transaction response has 1 parameter word which should be
5292 * ignored by the client.
5294 * However Windows only follows this rule for the IS_NAME_VALID call.
5296 switch (info_level) {
5297 case SMB_INFO_IS_NAME_VALID:
5302 if ((info_level & 0xFF00) == 0xFF00) {
5304 * We use levels that start with 0xFF00
5305 * internally to represent SMB2 specific levels
5307 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5311 status = smbd_do_qfilepathinfo(conn, req, info_level,
5313 delete_pending, write_time_ts,
5314 ms_dfs_link, ea_list,
5315 lock_data_count, lock_data,
5316 req->flags2, max_data_bytes,
5317 ppdata, &data_size);
5318 if (!NT_STATUS_IS_OK(status)) {
5319 reply_nterror(req, status);
5323 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5329 /****************************************************************************
5330 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5332 ****************************************************************************/
5334 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5335 connection_struct *conn,
5336 const struct smb_filename *smb_fname_old,
5337 const struct smb_filename *smb_fname_new)
5339 NTSTATUS status = NT_STATUS_OK;
5341 /* source must already exist. */
5342 if (!VALID_STAT(smb_fname_old->st)) {
5343 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5346 /* Disallow if newname already exists. */
5347 if (VALID_STAT(smb_fname_new->st)) {
5348 return NT_STATUS_OBJECT_NAME_COLLISION;
5351 /* No links from a directory. */
5352 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5353 return NT_STATUS_FILE_IS_A_DIRECTORY;
5356 /* Setting a hardlink to/from a stream isn't currently supported. */
5357 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5358 is_ntfs_stream_smb_fname(smb_fname_new)) {
5359 return NT_STATUS_INVALID_PARAMETER;
5362 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5363 smb_fname_old->base_name, smb_fname_new->base_name));
5365 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5366 smb_fname_new->base_name) != 0) {
5367 status = map_nt_error_from_unix(errno);
5368 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5369 nt_errstr(status), smb_fname_old->base_name,
5370 smb_fname_new->base_name));
5375 /****************************************************************************
5376 Deal with setting the time from any of the setfilepathinfo functions.
5377 ****************************************************************************/
5379 NTSTATUS smb_set_file_time(connection_struct *conn,
5381 const struct smb_filename *smb_fname,
5382 struct smb_file_time *ft,
5383 bool setting_write_time)
5385 struct smb_filename *smb_fname_base = NULL;
5387 FILE_NOTIFY_CHANGE_LAST_ACCESS
5388 |FILE_NOTIFY_CHANGE_LAST_WRITE
5389 |FILE_NOTIFY_CHANGE_CREATION;
5392 if (!VALID_STAT(smb_fname->st)) {
5393 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5396 /* get some defaults (no modifications) if any info is zero or -1. */
5397 if (null_timespec(ft->create_time)) {
5398 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5401 if (null_timespec(ft->atime)) {
5402 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5405 if (null_timespec(ft->mtime)) {
5406 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5409 if (!setting_write_time) {
5410 /* ft->mtime comes from change time, not write time. */
5411 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5414 /* Ensure the resolution is the correct for
5415 * what we can store on this filesystem. */
5417 round_timespec(conn->ts_res, &ft->create_time);
5418 round_timespec(conn->ts_res, &ft->ctime);
5419 round_timespec(conn->ts_res, &ft->atime);
5420 round_timespec(conn->ts_res, &ft->mtime);
5422 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5423 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5424 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5425 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5426 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5427 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5428 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5429 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5431 if (setting_write_time) {
5433 * This was a Windows setfileinfo on an open file.
5434 * NT does this a lot. We also need to
5435 * set the time here, as it can be read by
5436 * FindFirst/FindNext and with the patch for bug #2045
5437 * in smbd/fileio.c it ensures that this timestamp is
5438 * kept sticky even after a write. We save the request
5439 * away and will set it on file close and after a write. JRA.
5442 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5443 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5446 if (fsp->base_fsp) {
5447 set_sticky_write_time_fsp(fsp->base_fsp,
5450 set_sticky_write_time_fsp(fsp, ft->mtime);
5453 set_sticky_write_time_path(
5454 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5459 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5461 /* Always call ntimes on the base, even if a stream was passed in. */
5462 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5463 NULL, &smb_fname->st,
5465 if (!NT_STATUS_IS_OK(status)) {
5469 if(file_ntimes(conn, smb_fname_base, ft)!=0) {
5470 TALLOC_FREE(smb_fname_base);
5471 return map_nt_error_from_unix(errno);
5473 TALLOC_FREE(smb_fname_base);
5475 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5476 smb_fname->base_name);
5477 return NT_STATUS_OK;
5480 /****************************************************************************
5481 Deal with setting the dosmode from any of the setfilepathinfo functions.
5482 ****************************************************************************/
5484 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5485 const struct smb_filename *smb_fname,
5488 struct smb_filename *smb_fname_base = NULL;
5491 if (!VALID_STAT(smb_fname->st)) {
5492 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5495 /* Always operate on the base_name, even if a stream was passed in. */
5496 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5497 NULL, &smb_fname->st,
5499 if (!NT_STATUS_IS_OK(status)) {
5504 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5511 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5513 /* check the mode isn't different, before changing it */
5514 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5515 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5516 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5517 (unsigned int)dosmode));
5519 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5521 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5523 smb_fname_str_dbg(smb_fname_base),
5525 status = map_nt_error_from_unix(errno);
5529 status = NT_STATUS_OK;
5531 TALLOC_FREE(smb_fname_base);
5535 /****************************************************************************
5536 Deal with setting the size from any of the setfilepathinfo functions.
5537 ****************************************************************************/
5539 static NTSTATUS smb_set_file_size(connection_struct *conn,
5540 struct smb_request *req,
5542 const struct smb_filename *smb_fname,
5543 const SMB_STRUCT_STAT *psbuf,
5546 NTSTATUS status = NT_STATUS_OK;
5547 struct smb_filename *smb_fname_tmp = NULL;
5548 files_struct *new_fsp = NULL;
5550 if (!VALID_STAT(*psbuf)) {
5551 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5554 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5556 if (size == get_file_size_stat(psbuf)) {
5557 return NT_STATUS_OK;
5560 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5561 smb_fname_str_dbg(smb_fname), (double)size));
5563 if (fsp && fsp->fh->fd != -1) {
5564 /* Handle based call. */
5565 if (vfs_set_filelen(fsp, size) == -1) {
5566 return map_nt_error_from_unix(errno);
5568 trigger_write_time_update_immediate(fsp);
5569 return NT_STATUS_OK;
5572 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5573 if (!NT_STATUS_IS_OK(status)) {
5577 smb_fname_tmp->st = *psbuf;
5579 status = SMB_VFS_CREATE_FILE(
5582 0, /* root_dir_fid */
5583 smb_fname_tmp, /* fname */
5584 FILE_WRITE_ATTRIBUTES, /* access_mask */
5585 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5587 FILE_OPEN, /* create_disposition*/
5588 0, /* create_options */
5589 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5590 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5591 0, /* allocation_size */
5594 &new_fsp, /* result */
5597 TALLOC_FREE(smb_fname_tmp);
5599 if (!NT_STATUS_IS_OK(status)) {
5600 /* NB. We check for open_was_deferred in the caller. */
5604 if (vfs_set_filelen(new_fsp, size) == -1) {
5605 status = map_nt_error_from_unix(errno);
5606 close_file(req, new_fsp,NORMAL_CLOSE);
5610 trigger_write_time_update_immediate(new_fsp);
5611 close_file(req, new_fsp,NORMAL_CLOSE);
5612 return NT_STATUS_OK;
5615 /****************************************************************************
5616 Deal with SMB_INFO_SET_EA.
5617 ****************************************************************************/
5619 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5623 const struct smb_filename *smb_fname)
5625 struct ea_list *ea_list = NULL;
5626 TALLOC_CTX *ctx = NULL;
5627 NTSTATUS status = NT_STATUS_OK;
5629 if (total_data < 10) {
5631 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5632 length. They seem to have no effect. Bug #3212. JRA */
5634 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5635 /* We're done. We only get EA info in this call. */
5636 return NT_STATUS_OK;
5639 return NT_STATUS_INVALID_PARAMETER;
5642 if (IVAL(pdata,0) > total_data) {
5643 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5644 IVAL(pdata,0), (unsigned int)total_data));
5645 return NT_STATUS_INVALID_PARAMETER;
5649 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5651 return NT_STATUS_INVALID_PARAMETER;
5653 status = set_ea(conn, fsp, smb_fname, ea_list);
5658 /****************************************************************************
5659 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5660 ****************************************************************************/
5662 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5666 const struct smb_filename *smb_fname)
5668 NTSTATUS status = NT_STATUS_OK;
5669 bool delete_on_close;
5672 if (total_data < 1) {
5673 return NT_STATUS_INVALID_PARAMETER;
5677 return NT_STATUS_INVALID_HANDLE;
5680 delete_on_close = (CVAL(pdata,0) ? True : False);
5681 dosmode = dos_mode(conn, smb_fname);
5683 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5684 "delete_on_close = %u\n",
5685 smb_fname_str_dbg(smb_fname),
5686 (unsigned int)dosmode,
5687 (unsigned int)delete_on_close ));
5689 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5691 if (!NT_STATUS_IS_OK(status)) {
5695 /* The set is across all open files on this dev/inode pair. */
5696 if (!set_delete_on_close(fsp, delete_on_close,
5697 &conn->server_info->utok)) {
5698 return NT_STATUS_ACCESS_DENIED;
5700 return NT_STATUS_OK;
5703 /****************************************************************************
5704 Deal with SMB_FILE_POSITION_INFORMATION.
5705 ****************************************************************************/
5707 static NTSTATUS smb_file_position_information(connection_struct *conn,
5712 uint64_t position_information;
5714 if (total_data < 8) {
5715 return NT_STATUS_INVALID_PARAMETER;
5719 /* Ignore on pathname based set. */
5720 return NT_STATUS_OK;
5723 position_information = (uint64_t)IVAL(pdata,0);
5724 #ifdef LARGE_SMB_OFF_T
5725 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5726 #else /* LARGE_SMB_OFF_T */
5727 if (IVAL(pdata,4) != 0) {
5728 /* more than 32 bits? */
5729 return NT_STATUS_INVALID_PARAMETER;
5731 #endif /* LARGE_SMB_OFF_T */
5733 DEBUG(10,("smb_file_position_information: Set file position "
5734 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5735 (double)position_information));
5736 fsp->fh->position_information = position_information;
5737 return NT_STATUS_OK;
5740 /****************************************************************************
5741 Deal with SMB_FILE_MODE_INFORMATION.
5742 ****************************************************************************/
5744 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5750 if (total_data < 4) {
5751 return NT_STATUS_INVALID_PARAMETER;
5753 mode = IVAL(pdata,0);
5754 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5755 return NT_STATUS_INVALID_PARAMETER;
5757 return NT_STATUS_OK;
5760 /****************************************************************************
5761 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5762 ****************************************************************************/
5764 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5765 struct smb_request *req,
5768 const struct smb_filename *smb_fname)
5770 char *link_target = NULL;
5771 const char *newname = smb_fname->base_name;
5772 NTSTATUS status = NT_STATUS_OK;
5773 TALLOC_CTX *ctx = talloc_tos();
5775 /* Set a symbolic link. */
5776 /* Don't allow this if follow links is false. */
5778 if (total_data == 0) {
5779 return NT_STATUS_INVALID_PARAMETER;
5782 if (!lp_symlinks(SNUM(conn))) {
5783 return NT_STATUS_ACCESS_DENIED;
5786 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5787 total_data, STR_TERMINATE);
5790 return NT_STATUS_INVALID_PARAMETER;
5793 /* !widelinks forces the target path to be within the share. */
5794 /* This means we can interpret the target as a pathname. */
5795 if (!lp_widelinks(SNUM(conn))) {
5796 char *rel_name = NULL;
5797 char *last_dirp = NULL;
5799 if (*link_target == '/') {
5800 /* No absolute paths allowed. */
5801 return NT_STATUS_ACCESS_DENIED;
5803 rel_name = talloc_strdup(ctx,newname);
5805 return NT_STATUS_NO_MEMORY;
5807 last_dirp = strrchr_m(rel_name, '/');
5809 last_dirp[1] = '\0';
5811 rel_name = talloc_strdup(ctx,"./");
5813 return NT_STATUS_NO_MEMORY;
5816 rel_name = talloc_asprintf_append(rel_name,
5820 return NT_STATUS_NO_MEMORY;
5823 status = check_name(conn, rel_name);
5824 if (!NT_STATUS_IS_OK(status)) {
5829 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5830 newname, link_target ));
5832 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5833 return map_nt_error_from_unix(errno);
5836 return NT_STATUS_OK;
5839 /****************************************************************************
5840 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5841 ****************************************************************************/
5843 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5844 struct smb_request *req,
5845 const char *pdata, int total_data,
5846 const struct smb_filename *smb_fname_new)
5848 char *oldname = NULL;
5849 struct smb_filename *smb_fname_old = NULL;
5850 TALLOC_CTX *ctx = talloc_tos();
5851 NTSTATUS status = NT_STATUS_OK;
5853 /* Set a hard link. */
5854 if (total_data == 0) {
5855 return NT_STATUS_INVALID_PARAMETER;
5858 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5859 total_data, STR_TERMINATE, &status);
5860 if (!NT_STATUS_IS_OK(status)) {
5864 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5865 smb_fname_str_dbg(smb_fname_new), oldname));
5867 status = filename_convert(ctx,
5869 req->flags2 & FLAGS2_DFS_PATHNAMES,
5874 if (!NT_STATUS_IS_OK(status)) {
5878 return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
5881 /****************************************************************************
5882 Deal with SMB_FILE_RENAME_INFORMATION.
5883 ****************************************************************************/
5885 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5886 struct smb_request *req,
5890 struct smb_filename *smb_fname_src)
5895 char *newname = NULL;
5896 struct smb_filename *smb_fname_dst = NULL;
5897 bool dest_has_wcard = False;
5898 NTSTATUS status = NT_STATUS_OK;
5900 TALLOC_CTX *ctx = talloc_tos();
5902 if (total_data < 13) {
5903 return NT_STATUS_INVALID_PARAMETER;
5906 overwrite = (CVAL(pdata,0) ? True : False);
5907 root_fid = IVAL(pdata,4);
5908 len = IVAL(pdata,8);
5910 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5911 return NT_STATUS_INVALID_PARAMETER;
5914 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5917 if (!NT_STATUS_IS_OK(status)) {
5921 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5924 status = resolve_dfspath_wcard(ctx, conn,
5925 req->flags2 & FLAGS2_DFS_PATHNAMES,
5929 if (!NT_STATUS_IS_OK(status)) {
5933 /* Check the new name has no '/' characters. */
5934 if (strchr_m(newname, '/')) {
5935 return NT_STATUS_NOT_SUPPORTED;
5938 if (fsp && fsp->base_fsp) {
5939 /* newname must be a stream name. */
5940 if (newname[0] != ':') {
5941 return NT_STATUS_NOT_SUPPORTED;
5944 /* Create an smb_fname to call rename_internals_fsp() with. */
5945 status = create_synthetic_smb_fname(talloc_tos(),
5946 fsp->base_fsp->fsp_name->base_name, newname, NULL,
5948 if (!NT_STATUS_IS_OK(status)) {
5953 * Set the original last component, since
5954 * rename_internals_fsp() requires it.
5956 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
5958 if (smb_fname_dst->original_lcomp == NULL) {
5959 status = NT_STATUS_NO_MEMORY;
5965 * Build up an smb_fname_dst based on the filename passed in.
5966 * We basically just strip off the last component, and put on
5967 * the newname instead.
5969 char *base_name = NULL;
5971 /* newname must *not* be a stream name. */
5972 if (newname[0] == ':') {
5973 return NT_STATUS_NOT_SUPPORTED;
5977 * Strip off the last component (filename) of the path passed
5980 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
5982 return NT_STATUS_NO_MEMORY;
5984 p = strrchr_m(base_name, '/');
5988 base_name = talloc_strdup(ctx, "./");
5990 return NT_STATUS_NO_MEMORY;
5993 /* Append the new name. */
5994 base_name = talloc_asprintf_append(base_name,
5998 return NT_STATUS_NO_MEMORY;
6001 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6004 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6007 /* If an error we expect this to be
6008 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6010 if (!NT_STATUS_IS_OK(status)) {
6011 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6015 /* Create an smb_fname to call rename_internals_fsp() */
6016 status = create_synthetic_smb_fname(ctx,
6020 if (!NT_STATUS_IS_OK(status)) {
6027 DEBUG(10,("smb_file_rename_information: "
6028 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6029 fsp->fnum, fsp_str_dbg(fsp),
6030 smb_fname_str_dbg(smb_fname_dst)));
6031 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6034 DEBUG(10,("smb_file_rename_information: "
6035 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6036 smb_fname_str_dbg(smb_fname_src),
6037 smb_fname_str_dbg(smb_fname_dst)));
6038 status = rename_internals(ctx, conn, req, smb_fname_src,
6039 smb_fname_dst, 0, overwrite, false,
6041 FILE_WRITE_ATTRIBUTES);
6044 TALLOC_FREE(smb_fname_dst);
6048 /****************************************************************************
6049 Deal with SMB_SET_POSIX_ACL.
6050 ****************************************************************************/
6052 #if defined(HAVE_POSIX_ACLS)
6053 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6057 const struct smb_filename *smb_fname)
6059 uint16 posix_acl_version;
6060 uint16 num_file_acls;
6061 uint16 num_def_acls;
6062 bool valid_file_acls = True;
6063 bool valid_def_acls = True;
6065 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6066 return NT_STATUS_INVALID_PARAMETER;
6068 posix_acl_version = SVAL(pdata,0);
6069 num_file_acls = SVAL(pdata,2);
6070 num_def_acls = SVAL(pdata,4);
6072 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6073 valid_file_acls = False;
6077 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6078 valid_def_acls = False;
6082 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6083 return NT_STATUS_INVALID_PARAMETER;
6086 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6087 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6088 return NT_STATUS_INVALID_PARAMETER;
6091 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6092 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6093 (unsigned int)num_file_acls,
6094 (unsigned int)num_def_acls));
6096 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6097 smb_fname->base_name, num_file_acls,
6098 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6099 return map_nt_error_from_unix(errno);
6102 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6103 smb_fname->base_name, &smb_fname->st, num_def_acls,
6104 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6105 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6106 return map_nt_error_from_unix(errno);
6108 return NT_STATUS_OK;
6112 /****************************************************************************
6113 Deal with SMB_SET_POSIX_LOCK.
6114 ****************************************************************************/
6116 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6117 struct smb_request *req,
6125 bool blocking_lock = False;
6126 enum brl_type lock_type;
6128 NTSTATUS status = NT_STATUS_OK;
6130 if (fsp == NULL || fsp->fh->fd == -1) {
6131 return NT_STATUS_INVALID_HANDLE;
6134 if (total_data != POSIX_LOCK_DATA_SIZE) {
6135 return NT_STATUS_INVALID_PARAMETER;
6138 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6139 case POSIX_LOCK_TYPE_READ:
6140 lock_type = READ_LOCK;
6142 case POSIX_LOCK_TYPE_WRITE:
6143 /* Return the right POSIX-mappable error code for files opened read-only. */
6144 if (!fsp->can_write) {
6145 return NT_STATUS_INVALID_HANDLE;
6147 lock_type = WRITE_LOCK;
6149 case POSIX_LOCK_TYPE_UNLOCK:
6150 lock_type = UNLOCK_LOCK;
6153 return NT_STATUS_INVALID_PARAMETER;
6156 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6157 blocking_lock = False;
6158 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6159 blocking_lock = True;
6161 return NT_STATUS_INVALID_PARAMETER;
6164 if (!lp_blocking_locks(SNUM(conn))) {
6165 blocking_lock = False;
6168 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6169 #if defined(HAVE_LONGLONG)
6170 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6171 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6172 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6173 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6174 #else /* HAVE_LONGLONG */
6175 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6176 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6177 #endif /* HAVE_LONGLONG */
6179 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6180 "lock_pid = %u, count = %.0f, offset = %.0f\n",
6182 (unsigned int)lock_type,
6183 (unsigned int)lock_pid,
6187 if (lock_type == UNLOCK_LOCK) {
6188 status = do_unlock(smbd_messaging_context(),
6195 uint32 block_smbpid;
6197 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
6209 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6211 * A blocking lock was requested. Package up
6212 * this smb into a queued request and push it
6213 * onto the blocking lock queue.
6215 if(push_blocking_lock_request(br_lck,
6218 -1, /* infinite timeout. */
6226 TALLOC_FREE(br_lck);
6230 TALLOC_FREE(br_lck);
6236 /****************************************************************************
6237 Deal with SMB_SET_FILE_BASIC_INFO.
6238 ****************************************************************************/
6240 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6244 const struct smb_filename *smb_fname)
6246 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6247 struct smb_file_time ft;
6249 NTSTATUS status = NT_STATUS_OK;
6253 if (total_data < 36) {
6254 return NT_STATUS_INVALID_PARAMETER;
6257 /* Set the attributes */
6258 dosmode = IVAL(pdata,32);
6259 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6260 if (!NT_STATUS_IS_OK(status)) {
6265 ft.create_time = interpret_long_date(pdata);
6268 ft.atime = interpret_long_date(pdata+8);
6271 ft.mtime = interpret_long_date(pdata+16);
6274 ft.ctime = interpret_long_date(pdata+24);
6276 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6277 smb_fname_str_dbg(smb_fname)));
6279 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6283 /****************************************************************************
6284 Deal with SMB_INFO_STANDARD.
6285 ****************************************************************************/
6287 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6291 const struct smb_filename *smb_fname)
6293 struct smb_file_time ft;
6297 if (total_data < 12) {
6298 return NT_STATUS_INVALID_PARAMETER;
6302 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6304 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6306 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6308 DEBUG(10,("smb_set_info_standard: file %s\n",
6309 smb_fname_str_dbg(smb_fname)));
6311 return smb_set_file_time(conn,
6318 /****************************************************************************
6319 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6320 ****************************************************************************/
6322 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6323 struct smb_request *req,
6327 struct smb_filename *smb_fname)
6329 uint64_t allocation_size = 0;
6330 NTSTATUS status = NT_STATUS_OK;
6331 files_struct *new_fsp = NULL;
6333 if (!VALID_STAT(smb_fname->st)) {
6334 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6337 if (total_data < 8) {
6338 return NT_STATUS_INVALID_PARAMETER;
6341 allocation_size = (uint64_t)IVAL(pdata,0);
6342 #ifdef LARGE_SMB_OFF_T
6343 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6344 #else /* LARGE_SMB_OFF_T */
6345 if (IVAL(pdata,4) != 0) {
6346 /* more than 32 bits? */
6347 return NT_STATUS_INVALID_PARAMETER;
6349 #endif /* LARGE_SMB_OFF_T */
6351 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6352 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6353 (double)allocation_size));
6355 if (allocation_size) {
6356 allocation_size = smb_roundup(conn, allocation_size);
6359 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6360 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6361 (double)allocation_size));
6363 if (fsp && fsp->fh->fd != -1) {
6364 /* Open file handle. */
6365 /* Only change if needed. */
6366 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6367 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6368 return map_nt_error_from_unix(errno);
6371 /* But always update the time. */
6373 * This is equivalent to a write. Ensure it's seen immediately
6374 * if there are no pending writes.
6376 trigger_write_time_update_immediate(fsp);
6377 return NT_STATUS_OK;
6380 /* Pathname or stat or directory file. */
6381 status = SMB_VFS_CREATE_FILE(
6384 0, /* root_dir_fid */
6385 smb_fname, /* fname */
6386 FILE_WRITE_DATA, /* access_mask */
6387 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6389 FILE_OPEN, /* create_disposition*/
6390 0, /* create_options */
6391 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6392 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6393 0, /* allocation_size */
6396 &new_fsp, /* result */
6399 if (!NT_STATUS_IS_OK(status)) {
6400 /* NB. We check for open_was_deferred in the caller. */
6404 /* Only change if needed. */
6405 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6406 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6407 status = map_nt_error_from_unix(errno);
6408 close_file(req, new_fsp, NORMAL_CLOSE);
6413 /* Changing the allocation size should set the last mod time. */
6415 * This is equivalent to a write. Ensure it's seen immediately
6416 * if there are no pending writes.
6418 trigger_write_time_update_immediate(new_fsp);
6420 close_file(req, new_fsp, NORMAL_CLOSE);
6421 return NT_STATUS_OK;
6424 /****************************************************************************
6425 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6426 ****************************************************************************/
6428 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6429 struct smb_request *req,
6433 const struct smb_filename *smb_fname)
6437 if (total_data < 8) {
6438 return NT_STATUS_INVALID_PARAMETER;
6441 size = IVAL(pdata,0);
6442 #ifdef LARGE_SMB_OFF_T
6443 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6444 #else /* LARGE_SMB_OFF_T */
6445 if (IVAL(pdata,4) != 0) {
6446 /* more than 32 bits? */
6447 return NT_STATUS_INVALID_PARAMETER;
6449 #endif /* LARGE_SMB_OFF_T */
6450 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6451 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6454 return smb_set_file_size(conn, req,
6461 /****************************************************************************
6462 Allow a UNIX info mknod.
6463 ****************************************************************************/
6465 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6468 const struct smb_filename *smb_fname)
6470 uint32 file_type = IVAL(pdata,56);
6471 #if defined(HAVE_MAKEDEV)
6472 uint32 dev_major = IVAL(pdata,60);
6473 uint32 dev_minor = IVAL(pdata,68);
6475 SMB_DEV_T dev = (SMB_DEV_T)0;
6476 uint32 raw_unixmode = IVAL(pdata,84);
6480 if (total_data < 100) {
6481 return NT_STATUS_INVALID_PARAMETER;
6484 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6485 PERM_NEW_FILE, &unixmode);
6486 if (!NT_STATUS_IS_OK(status)) {
6490 #if defined(HAVE_MAKEDEV)
6491 dev = makedev(dev_major, dev_minor);
6494 switch (file_type) {
6495 #if defined(S_IFIFO)
6496 case UNIX_TYPE_FIFO:
6497 unixmode |= S_IFIFO;
6500 #if defined(S_IFSOCK)
6501 case UNIX_TYPE_SOCKET:
6502 unixmode |= S_IFSOCK;
6505 #if defined(S_IFCHR)
6506 case UNIX_TYPE_CHARDEV:
6507 unixmode |= S_IFCHR;
6510 #if defined(S_IFBLK)
6511 case UNIX_TYPE_BLKDEV:
6512 unixmode |= S_IFBLK;
6516 return NT_STATUS_INVALID_PARAMETER;
6519 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6520 "%.0f mode 0%o for file %s\n", (double)dev,
6521 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6523 /* Ok - do the mknod. */
6524 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6525 return map_nt_error_from_unix(errno);
6528 /* If any of the other "set" calls fail we
6529 * don't want to end up with a half-constructed mknod.
6532 if (lp_inherit_perms(SNUM(conn))) {
6534 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6536 return NT_STATUS_NO_MEMORY;
6538 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6540 TALLOC_FREE(parent);
6543 return NT_STATUS_OK;
6546 /****************************************************************************
6547 Deal with SMB_SET_FILE_UNIX_BASIC.
6548 ****************************************************************************/
6550 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6551 struct smb_request *req,
6555 const struct smb_filename *smb_fname)
6557 struct smb_file_time ft;
6558 uint32 raw_unixmode;
6561 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6562 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6563 NTSTATUS status = NT_STATUS_OK;
6564 bool delete_on_fail = False;
6565 enum perm_type ptype;
6566 files_struct *all_fsps = NULL;
6567 bool modify_mtime = true;
6569 SMB_STRUCT_STAT sbuf;
6573 if (total_data < 100) {
6574 return NT_STATUS_INVALID_PARAMETER;
6577 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6578 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6579 size=IVAL(pdata,0); /* first 8 Bytes are size */
6580 #ifdef LARGE_SMB_OFF_T
6581 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6582 #else /* LARGE_SMB_OFF_T */
6583 if (IVAL(pdata,4) != 0) {
6584 /* more than 32 bits? */
6585 return NT_STATUS_INVALID_PARAMETER;
6587 #endif /* LARGE_SMB_OFF_T */
6590 ft.atime = interpret_long_date(pdata+24); /* access_time */
6591 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6592 set_owner = (uid_t)IVAL(pdata,40);
6593 set_grp = (gid_t)IVAL(pdata,48);
6594 raw_unixmode = IVAL(pdata,84);
6596 if (VALID_STAT(smb_fname->st)) {
6597 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6598 ptype = PERM_EXISTING_DIR;
6600 ptype = PERM_EXISTING_FILE;
6603 ptype = PERM_NEW_FILE;
6606 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6608 if (!NT_STATUS_IS_OK(status)) {
6612 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6613 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6614 smb_fname_str_dbg(smb_fname), (double)size,
6615 (unsigned int)set_owner, (unsigned int)set_grp,
6616 (int)raw_unixmode));
6618 sbuf = smb_fname->st;
6620 if (!VALID_STAT(sbuf)) {
6621 struct smb_filename *smb_fname_tmp = NULL;
6623 * The only valid use of this is to create character and block
6624 * devices, and named pipes. This is deprecated (IMHO) and
6625 * a new info level should be used for mknod. JRA.
6628 status = smb_unix_mknod(conn,
6632 if (!NT_STATUS_IS_OK(status)) {
6636 status = copy_smb_filename(talloc_tos(), smb_fname,
6638 if (!NT_STATUS_IS_OK(status)) {
6642 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6643 status = map_nt_error_from_unix(errno);
6644 TALLOC_FREE(smb_fname_tmp);
6645 SMB_VFS_UNLINK(conn, smb_fname);
6649 sbuf = smb_fname_tmp->st;
6650 TALLOC_FREE(smb_fname_tmp);
6652 /* Ensure we don't try and change anything else. */
6653 raw_unixmode = SMB_MODE_NO_CHANGE;
6654 size = get_file_size_stat(&sbuf);
6655 ft.atime = sbuf.st_ex_atime;
6656 ft.mtime = sbuf.st_ex_mtime;
6658 * We continue here as we might want to change the
6661 delete_on_fail = True;
6665 /* Horrible backwards compatibility hack as an old server bug
6666 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6670 size = get_file_size_stat(&sbuf);
6675 * Deal with the UNIX specific mode set.
6678 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6679 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6680 "setting mode 0%o for file %s\n",
6681 (unsigned int)unixmode,
6682 smb_fname_str_dbg(smb_fname)));
6683 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6684 return map_nt_error_from_unix(errno);
6689 * Deal with the UNIX specific uid set.
6692 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6693 (sbuf.st_ex_uid != set_owner)) {
6696 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6697 "changing owner %u for path %s\n",
6698 (unsigned int)set_owner,
6699 smb_fname_str_dbg(smb_fname)));
6701 if (S_ISLNK(sbuf.st_ex_mode)) {
6702 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6703 set_owner, (gid_t)-1);
6705 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6706 set_owner, (gid_t)-1);
6710 status = map_nt_error_from_unix(errno);
6711 if (delete_on_fail) {
6712 SMB_VFS_UNLINK(conn, smb_fname);
6719 * Deal with the UNIX specific gid set.
6722 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6723 (sbuf.st_ex_gid != set_grp)) {
6724 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6725 "changing group %u for file %s\n",
6726 (unsigned int)set_owner,
6727 smb_fname_str_dbg(smb_fname)));
6728 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6730 status = map_nt_error_from_unix(errno);
6731 if (delete_on_fail) {
6732 SMB_VFS_UNLINK(conn, smb_fname);
6738 /* Deal with any size changes. */
6740 status = smb_set_file_size(conn, req,
6745 if (!NT_STATUS_IS_OK(status)) {
6749 /* Deal with any time changes. */
6750 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6751 /* No change, don't cancel anything. */
6755 id = vfs_file_id_from_sbuf(conn, &sbuf);
6756 for(all_fsps = file_find_di_first(id); all_fsps;
6757 all_fsps = file_find_di_next(all_fsps)) {
6759 * We're setting the time explicitly for UNIX.
6760 * Cancel any pending changes over all handles.
6762 all_fsps->update_write_time_on_close = false;
6763 TALLOC_FREE(all_fsps->update_write_time_event);
6767 * Override the "setting_write_time"
6768 * parameter here as it almost does what
6769 * we need. Just remember if we modified
6770 * mtime and send the notify ourselves.
6772 if (null_timespec(ft.mtime)) {
6773 modify_mtime = false;
6776 status = smb_set_file_time(conn,
6782 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6783 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6788 /****************************************************************************
6789 Deal with SMB_SET_FILE_UNIX_INFO2.
6790 ****************************************************************************/
6792 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6793 struct smb_request *req,
6797 const struct smb_filename *smb_fname)
6803 if (total_data < 116) {
6804 return NT_STATUS_INVALID_PARAMETER;
6807 /* Start by setting all the fields that are common between UNIX_BASIC
6810 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6812 if (!NT_STATUS_IS_OK(status)) {
6816 smb_fflags = IVAL(pdata, 108);
6817 smb_fmask = IVAL(pdata, 112);
6819 /* NB: We should only attempt to alter the file flags if the client
6820 * sends a non-zero mask.
6822 if (smb_fmask != 0) {
6823 int stat_fflags = 0;
6825 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6826 smb_fmask, &stat_fflags)) {
6827 /* Client asked to alter a flag we don't understand. */
6828 return NT_STATUS_INVALID_PARAMETER;
6831 if (fsp && fsp->fh->fd != -1) {
6832 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6833 return NT_STATUS_NOT_SUPPORTED;
6835 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
6836 stat_fflags) != 0) {
6837 return map_nt_error_from_unix(errno);
6842 /* XXX: need to add support for changing the create_time here. You
6843 * can do this for paths on Darwin with setattrlist(2). The right way
6844 * to hook this up is probably by extending the VFS utimes interface.
6847 return NT_STATUS_OK;
6850 /****************************************************************************
6851 Create a directory with POSIX semantics.
6852 ****************************************************************************/
6854 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6855 struct smb_request *req,
6858 struct smb_filename *smb_fname,
6859 int *pdata_return_size)
6861 NTSTATUS status = NT_STATUS_OK;
6862 uint32 raw_unixmode = 0;
6863 uint32 mod_unixmode = 0;
6864 mode_t unixmode = (mode_t)0;
6865 files_struct *fsp = NULL;
6866 uint16 info_level_return = 0;
6868 char *pdata = *ppdata;
6870 if (total_data < 18) {
6871 return NT_STATUS_INVALID_PARAMETER;
6874 raw_unixmode = IVAL(pdata,8);
6875 /* Next 4 bytes are not yet defined. */
6877 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6878 PERM_NEW_DIR, &unixmode);
6879 if (!NT_STATUS_IS_OK(status)) {
6883 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6885 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6886 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
6888 status = SMB_VFS_CREATE_FILE(
6891 0, /* root_dir_fid */
6892 smb_fname, /* fname */
6893 FILE_READ_ATTRIBUTES, /* access_mask */
6894 FILE_SHARE_NONE, /* share_access */
6895 FILE_CREATE, /* create_disposition*/
6896 FILE_DIRECTORY_FILE, /* create_options */
6897 mod_unixmode, /* file_attributes */
6898 0, /* oplock_request */
6899 0, /* allocation_size */
6905 if (NT_STATUS_IS_OK(status)) {
6906 close_file(req, fsp, NORMAL_CLOSE);
6909 info_level_return = SVAL(pdata,16);
6911 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6912 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6913 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6914 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6916 *pdata_return_size = 12;
6919 /* Realloc the data size */
6920 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6921 if (*ppdata == NULL) {
6922 *pdata_return_size = 0;
6923 return NT_STATUS_NO_MEMORY;
6927 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6928 SSVAL(pdata,2,0); /* No fnum. */
6929 SIVAL(pdata,4,info); /* Was directory created. */
6931 switch (info_level_return) {
6932 case SMB_QUERY_FILE_UNIX_BASIC:
6933 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6934 SSVAL(pdata,10,0); /* Padding. */
6935 store_file_unix_basic(conn, pdata + 12, fsp,
6938 case SMB_QUERY_FILE_UNIX_INFO2:
6939 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6940 SSVAL(pdata,10,0); /* Padding. */
6941 store_file_unix_basic_info2(conn, pdata + 12, fsp,
6945 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6946 SSVAL(pdata,10,0); /* Padding. */
6953 /****************************************************************************
6954 Open/Create a file with POSIX semantics.
6955 ****************************************************************************/
6957 static NTSTATUS smb_posix_open(connection_struct *conn,
6958 struct smb_request *req,
6961 struct smb_filename *smb_fname,
6962 int *pdata_return_size)
6964 bool extended_oplock_granted = False;
6965 char *pdata = *ppdata;
6967 uint32 wire_open_mode = 0;
6968 uint32 raw_unixmode = 0;
6969 uint32 mod_unixmode = 0;
6970 uint32 create_disp = 0;
6971 uint32 access_mask = 0;
6972 uint32 create_options = 0;
6973 NTSTATUS status = NT_STATUS_OK;
6974 mode_t unixmode = (mode_t)0;
6975 files_struct *fsp = NULL;
6976 int oplock_request = 0;
6978 uint16 info_level_return = 0;
6980 if (total_data < 18) {
6981 return NT_STATUS_INVALID_PARAMETER;
6984 flags = IVAL(pdata,0);
6985 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6986 if (oplock_request) {
6987 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6990 wire_open_mode = IVAL(pdata,4);
6992 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6993 return smb_posix_mkdir(conn, req,
7000 switch (wire_open_mode & SMB_ACCMODE) {
7002 access_mask = FILE_READ_DATA;
7005 access_mask = FILE_WRITE_DATA;
7008 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
7011 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7012 (unsigned int)wire_open_mode ));
7013 return NT_STATUS_INVALID_PARAMETER;
7016 wire_open_mode &= ~SMB_ACCMODE;
7018 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
7019 create_disp = FILE_CREATE;
7020 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
7021 create_disp = FILE_OVERWRITE_IF;
7022 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
7023 create_disp = FILE_OPEN_IF;
7024 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
7025 create_disp = FILE_OPEN;
7027 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7028 (unsigned int)wire_open_mode ));
7029 return NT_STATUS_INVALID_PARAMETER;
7032 raw_unixmode = IVAL(pdata,8);
7033 /* Next 4 bytes are not yet defined. */
7035 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7036 (VALID_STAT(smb_fname->st) ?
7037 PERM_EXISTING_FILE : PERM_NEW_FILE),
7040 if (!NT_STATUS_IS_OK(status)) {
7044 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7046 if (wire_open_mode & SMB_O_SYNC) {
7047 create_options |= FILE_WRITE_THROUGH;
7049 if (wire_open_mode & SMB_O_APPEND) {
7050 access_mask |= FILE_APPEND_DATA;
7052 if (wire_open_mode & SMB_O_DIRECT) {
7053 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7056 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7057 smb_fname_str_dbg(smb_fname),
7058 (unsigned int)wire_open_mode,
7059 (unsigned int)unixmode ));
7061 status = SMB_VFS_CREATE_FILE(
7064 0, /* root_dir_fid */
7065 smb_fname, /* fname */
7066 access_mask, /* access_mask */
7067 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7069 create_disp, /* create_disposition*/
7070 FILE_NON_DIRECTORY_FILE, /* create_options */
7071 mod_unixmode, /* file_attributes */
7072 oplock_request, /* oplock_request */
7073 0, /* allocation_size */
7079 if (!NT_STATUS_IS_OK(status)) {
7083 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7084 extended_oplock_granted = True;
7087 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7088 extended_oplock_granted = True;
7091 info_level_return = SVAL(pdata,16);
7093 /* Allocate the correct return size. */
7095 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7096 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7097 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7098 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7100 *pdata_return_size = 12;
7103 /* Realloc the data size */
7104 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7105 if (*ppdata == NULL) {
7106 close_file(req, fsp, ERROR_CLOSE);
7107 *pdata_return_size = 0;
7108 return NT_STATUS_NO_MEMORY;
7112 if (extended_oplock_granted) {
7113 if (flags & REQUEST_BATCH_OPLOCK) {
7114 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7116 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7118 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7119 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7121 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7124 SSVAL(pdata,2,fsp->fnum);
7125 SIVAL(pdata,4,info); /* Was file created etc. */
7127 switch (info_level_return) {
7128 case SMB_QUERY_FILE_UNIX_BASIC:
7129 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7130 SSVAL(pdata,10,0); /* padding. */
7131 store_file_unix_basic(conn, pdata + 12, fsp,
7134 case SMB_QUERY_FILE_UNIX_INFO2:
7135 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7136 SSVAL(pdata,10,0); /* padding. */
7137 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7141 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7142 SSVAL(pdata,10,0); /* padding. */
7145 return NT_STATUS_OK;
7148 /****************************************************************************
7149 Delete a file with POSIX semantics.
7150 ****************************************************************************/
7152 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7153 struct smb_request *req,
7156 struct smb_filename *smb_fname)
7158 NTSTATUS status = NT_STATUS_OK;
7159 files_struct *fsp = NULL;
7163 int create_options = 0;
7165 struct share_mode_lock *lck = NULL;
7167 if (total_data < 2) {
7168 return NT_STATUS_INVALID_PARAMETER;
7171 flags = SVAL(pdata,0);
7173 if (!VALID_STAT(smb_fname->st)) {
7174 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7177 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7178 !VALID_STAT_OF_DIR(smb_fname->st)) {
7179 return NT_STATUS_NOT_A_DIRECTORY;
7182 DEBUG(10,("smb_posix_unlink: %s %s\n",
7183 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7184 smb_fname_str_dbg(smb_fname)));
7186 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7187 create_options |= FILE_DIRECTORY_FILE;
7190 status = SMB_VFS_CREATE_FILE(
7193 0, /* root_dir_fid */
7194 smb_fname, /* fname */
7195 DELETE_ACCESS, /* access_mask */
7196 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7198 FILE_OPEN, /* create_disposition*/
7199 create_options, /* create_options */
7200 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7201 0, /* oplock_request */
7202 0, /* allocation_size */
7208 if (!NT_STATUS_IS_OK(status)) {
7213 * Don't lie to client. If we can't really delete due to
7214 * non-POSIX opens return SHARING_VIOLATION.
7217 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7220 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7221 "lock for file %s\n", fsp_str_dbg(fsp)));
7222 close_file(req, fsp, NORMAL_CLOSE);
7223 return NT_STATUS_INVALID_PARAMETER;
7227 * See if others still have the file open. If this is the case, then
7228 * don't delete. If all opens are POSIX delete we can set the delete
7229 * on close disposition.
7231 for (i=0; i<lck->num_share_modes; i++) {
7232 struct share_mode_entry *e = &lck->share_modes[i];
7233 if (is_valid_share_mode_entry(e)) {
7234 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7237 /* Fail with sharing violation. */
7238 close_file(req, fsp, NORMAL_CLOSE);
7240 return NT_STATUS_SHARING_VIOLATION;
7245 * Set the delete on close.
7247 status = smb_set_file_disposition_info(conn,
7253 if (!NT_STATUS_IS_OK(status)) {
7254 close_file(req, fsp, NORMAL_CLOSE);
7259 return close_file(req, fsp, NORMAL_CLOSE);
7262 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7263 struct smb_request *req,
7264 TALLOC_CTX *mem_ctx,
7265 uint16_t info_level,
7267 struct smb_filename *smb_fname,
7268 char **ppdata, int total_data,
7271 char *pdata = *ppdata;
7272 NTSTATUS status = NT_STATUS_OK;
7273 int data_return_size = 0;
7277 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7278 return NT_STATUS_INVALID_LEVEL;
7281 if (!CAN_WRITE(conn)) {
7282 /* Allow POSIX opens. The open path will deny
7283 * any non-readonly opens. */
7284 if (info_level != SMB_POSIX_PATH_OPEN) {
7285 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7289 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7290 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7291 fsp ? fsp->fnum : -1, info_level, total_data));
7293 switch (info_level) {
7295 case SMB_INFO_STANDARD:
7297 status = smb_set_info_standard(conn,
7305 case SMB_INFO_SET_EA:
7307 status = smb_info_set_ea(conn,
7315 case SMB_SET_FILE_BASIC_INFO:
7316 case SMB_FILE_BASIC_INFORMATION:
7318 status = smb_set_file_basic_info(conn,
7326 case SMB_FILE_ALLOCATION_INFORMATION:
7327 case SMB_SET_FILE_ALLOCATION_INFO:
7329 status = smb_set_file_allocation_info(conn, req,
7337 case SMB_FILE_END_OF_FILE_INFORMATION:
7338 case SMB_SET_FILE_END_OF_FILE_INFO:
7340 status = smb_set_file_end_of_file_info(conn, req,
7348 case SMB_FILE_DISPOSITION_INFORMATION:
7349 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7352 /* JRA - We used to just ignore this on a path ?
7353 * Shouldn't this be invalid level on a pathname
7356 if (tran_call != TRANSACT2_SETFILEINFO) {
7357 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7360 status = smb_set_file_disposition_info(conn,
7368 case SMB_FILE_POSITION_INFORMATION:
7370 status = smb_file_position_information(conn,
7377 /* From tridge Samba4 :
7378 * MODE_INFORMATION in setfileinfo (I have no
7379 * idea what "mode information" on a file is - it takes a value of 0,
7380 * 2, 4 or 6. What could it be?).
7383 case SMB_FILE_MODE_INFORMATION:
7385 status = smb_file_mode_information(conn,
7392 * CIFS UNIX extensions.
7395 case SMB_SET_FILE_UNIX_BASIC:
7397 status = smb_set_file_unix_basic(conn, req,
7405 case SMB_SET_FILE_UNIX_INFO2:
7407 status = smb_set_file_unix_info2(conn, req,
7415 case SMB_SET_FILE_UNIX_LINK:
7418 /* We must have a pathname for this. */
7419 return NT_STATUS_INVALID_LEVEL;
7421 status = smb_set_file_unix_link(conn, req, pdata,
7422 total_data, smb_fname);
7426 case SMB_SET_FILE_UNIX_HLINK:
7429 /* We must have a pathname for this. */
7430 return NT_STATUS_INVALID_LEVEL;
7432 status = smb_set_file_unix_hlink(conn, req,
7438 case SMB_FILE_RENAME_INFORMATION:
7440 status = smb_file_rename_information(conn, req,
7446 #if defined(HAVE_POSIX_ACLS)
7447 case SMB_SET_POSIX_ACL:
7449 status = smb_set_posix_acl(conn,
7458 case SMB_SET_POSIX_LOCK:
7461 return NT_STATUS_INVALID_LEVEL;
7463 status = smb_set_posix_lock(conn, req,
7464 pdata, total_data, fsp);
7468 case SMB_POSIX_PATH_OPEN:
7471 /* We must have a pathname for this. */
7472 return NT_STATUS_INVALID_LEVEL;
7475 status = smb_posix_open(conn, req,
7483 case SMB_POSIX_PATH_UNLINK:
7486 /* We must have a pathname for this. */
7487 return NT_STATUS_INVALID_LEVEL;
7490 status = smb_posix_unlink(conn, req,
7498 return NT_STATUS_INVALID_LEVEL;
7501 if (!NT_STATUS_IS_OK(status)) {
7505 *ret_data_size = data_return_size;
7506 return NT_STATUS_OK;
7509 /****************************************************************************
7510 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7511 ****************************************************************************/
7513 static void call_trans2setfilepathinfo(connection_struct *conn,
7514 struct smb_request *req,
7515 unsigned int tran_call,
7516 char **pparams, int total_params,
7517 char **ppdata, int total_data,
7518 unsigned int max_data_bytes)
7520 char *params = *pparams;
7521 char *pdata = *ppdata;
7523 struct smb_filename *smb_fname = NULL;
7524 files_struct *fsp = NULL;
7525 NTSTATUS status = NT_STATUS_OK;
7526 int data_return_size = 0;
7529 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7533 if (tran_call == TRANSACT2_SETFILEINFO) {
7534 if (total_params < 4) {
7535 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7539 fsp = file_fsp(req, SVAL(params,0));
7540 /* Basic check for non-null fsp. */
7541 if (!check_fsp_open(conn, req, fsp)) {
7544 info_level = SVAL(params,2);
7546 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7548 if (!NT_STATUS_IS_OK(status)) {
7549 reply_nterror(req, status);
7553 if(fsp->is_directory || fsp->fh->fd == -1) {
7555 * This is actually a SETFILEINFO on a directory
7556 * handle (returned from an NT SMB). NT5.0 seems
7557 * to do this call. JRA.
7559 if (INFO_LEVEL_IS_UNIX(info_level)) {
7560 /* Always do lstat for UNIX calls. */
7561 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7562 DEBUG(3,("call_trans2setfilepathinfo: "
7563 "SMB_VFS_LSTAT of %s failed "
7565 smb_fname_str_dbg(smb_fname),
7567 reply_nterror(req, map_nt_error_from_unix(errno));
7571 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7572 DEBUG(3,("call_trans2setfilepathinfo: "
7573 "fileinfo of %s failed (%s)\n",
7574 smb_fname_str_dbg(smb_fname),
7576 reply_nterror(req, map_nt_error_from_unix(errno));
7580 } else if (fsp->print_file) {
7582 * Doing a DELETE_ON_CLOSE should cancel a print job.
7584 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7585 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
7587 DEBUG(3,("call_trans2setfilepathinfo: "
7588 "Cancelling print job (%s)\n",
7592 send_trans2_replies(conn, req, params, 2,
7597 reply_doserror(req, ERRDOS, ERRbadpath);
7602 * Original code - this is an open file.
7604 if (!check_fsp(conn, req, fsp)) {
7608 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7609 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7610 "of fnum %d failed (%s)\n", fsp->fnum,
7612 reply_nterror(req, map_nt_error_from_unix(errno));
7620 if (total_params < 7) {
7621 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7625 info_level = SVAL(params,0);
7626 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
7627 total_params - 6, STR_TERMINATE,
7629 if (!NT_STATUS_IS_OK(status)) {
7630 reply_nterror(req, status);
7634 status = filename_convert(req, conn,
7635 req->flags2 & FLAGS2_DFS_PATHNAMES,
7640 if (!NT_STATUS_IS_OK(status)) {
7641 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7642 reply_botherror(req,
7643 NT_STATUS_PATH_NOT_COVERED,
7644 ERRSRV, ERRbadpath);
7647 reply_nterror(req, status);
7651 if (INFO_LEVEL_IS_UNIX(info_level)) {
7653 * For CIFS UNIX extensions the target name may not exist.
7656 /* Always do lstat for UNIX calls. */
7657 SMB_VFS_LSTAT(conn, smb_fname);
7659 } else if (!VALID_STAT(smb_fname->st) &&
7660 SMB_VFS_STAT(conn, smb_fname)) {
7661 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7663 smb_fname_str_dbg(smb_fname),
7665 reply_nterror(req, map_nt_error_from_unix(errno));
7670 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7671 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
7672 fsp ? fsp->fnum : -1, info_level,total_data));
7674 /* Realloc the parameter size */
7675 *pparams = (char *)SMB_REALLOC(*pparams,2);
7676 if (*pparams == NULL) {
7677 reply_nterror(req, NT_STATUS_NO_MEMORY);
7684 status = smbd_do_setfilepathinfo(conn, req, req,
7690 if (!NT_STATUS_IS_OK(status)) {
7691 if (open_was_deferred(req->mid)) {
7692 /* We have re-scheduled this call. */
7695 if (blocking_lock_was_deferred(req->mid)) {
7696 /* We have re-scheduled this call. */
7699 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7700 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7701 ERRSRV, ERRbadpath);
7704 if (info_level == SMB_POSIX_PATH_OPEN) {
7705 reply_openerror(req, status);
7709 reply_nterror(req, status);
7713 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7719 /****************************************************************************
7720 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7721 ****************************************************************************/
7723 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7724 char **pparams, int total_params,
7725 char **ppdata, int total_data,
7726 unsigned int max_data_bytes)
7728 struct smb_filename *smb_dname = NULL;
7729 char *params = *pparams;
7730 char *pdata = *ppdata;
7731 char *directory = NULL;
7732 NTSTATUS status = NT_STATUS_OK;
7733 struct ea_list *ea_list = NULL;
7734 TALLOC_CTX *ctx = talloc_tos();
7736 if (!CAN_WRITE(conn)) {
7737 reply_doserror(req, ERRSRV, ERRaccess);
7741 if (total_params < 5) {
7742 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7746 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7747 total_params - 4, STR_TERMINATE,
7749 if (!NT_STATUS_IS_OK(status)) {
7750 reply_nterror(req, status);
7754 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7756 status = filename_convert(ctx,
7758 req->flags2 & FLAGS2_DFS_PATHNAMES,
7764 if (!NT_STATUS_IS_OK(status)) {
7765 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7766 reply_botherror(req,
7767 NT_STATUS_PATH_NOT_COVERED,
7768 ERRSRV, ERRbadpath);
7771 reply_nterror(req, status);
7775 /* Any data in this call is an EA list. */
7776 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7777 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7782 * OS/2 workplace shell seems to send SET_EA requests of "null"
7783 * length (4 bytes containing IVAL 4).
7784 * They seem to have no effect. Bug #3212. JRA.
7787 if (total_data != 4) {
7788 if (total_data < 10) {
7789 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7793 if (IVAL(pdata,0) > total_data) {
7794 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7795 IVAL(pdata,0), (unsigned int)total_data));
7796 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7800 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7803 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7807 /* If total_data == 4 Windows doesn't care what values
7808 * are placed in that field, it just ignores them.
7809 * The System i QNTC IBM SMB client puts bad values here,
7810 * so ignore them. */
7812 status = create_directory(conn, req, smb_dname);
7814 if (!NT_STATUS_IS_OK(status)) {
7815 reply_nterror(req, status);
7819 /* Try and set any given EA. */
7821 status = set_ea(conn, NULL, smb_dname, ea_list);
7822 if (!NT_STATUS_IS_OK(status)) {
7823 reply_nterror(req, status);
7828 /* Realloc the parameter and data sizes */
7829 *pparams = (char *)SMB_REALLOC(*pparams,2);
7830 if(*pparams == NULL) {
7831 reply_nterror(req, NT_STATUS_NO_MEMORY);
7838 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7841 TALLOC_FREE(smb_dname);
7845 /****************************************************************************
7846 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7847 We don't actually do this - we just send a null response.
7848 ****************************************************************************/
7850 static void call_trans2findnotifyfirst(connection_struct *conn,
7851 struct smb_request *req,
7852 char **pparams, int total_params,
7853 char **ppdata, int total_data,
7854 unsigned int max_data_bytes)
7856 char *params = *pparams;
7859 if (total_params < 6) {
7860 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7864 info_level = SVAL(params,4);
7865 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7867 switch (info_level) {
7872 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7876 /* Realloc the parameter and data sizes */
7877 *pparams = (char *)SMB_REALLOC(*pparams,6);
7878 if (*pparams == NULL) {
7879 reply_nterror(req, NT_STATUS_NO_MEMORY);
7884 SSVAL(params,0,fnf_handle);
7885 SSVAL(params,2,0); /* No changes */
7886 SSVAL(params,4,0); /* No EA errors */
7893 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7898 /****************************************************************************
7899 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7900 changes). Currently this does nothing.
7901 ****************************************************************************/
7903 static void call_trans2findnotifynext(connection_struct *conn,
7904 struct smb_request *req,
7905 char **pparams, int total_params,
7906 char **ppdata, int total_data,
7907 unsigned int max_data_bytes)
7909 char *params = *pparams;
7911 DEBUG(3,("call_trans2findnotifynext\n"));
7913 /* Realloc the parameter and data sizes */
7914 *pparams = (char *)SMB_REALLOC(*pparams,4);
7915 if (*pparams == NULL) {
7916 reply_nterror(req, NT_STATUS_NO_MEMORY);
7921 SSVAL(params,0,0); /* No changes */
7922 SSVAL(params,2,0); /* No EA errors */
7924 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7929 /****************************************************************************
7930 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7931 ****************************************************************************/
7933 static void call_trans2getdfsreferral(connection_struct *conn,
7934 struct smb_request *req,
7935 char **pparams, int total_params,
7936 char **ppdata, int total_data,
7937 unsigned int max_data_bytes)
7939 char *params = *pparams;
7940 char *pathname = NULL;
7942 int max_referral_level;
7943 NTSTATUS status = NT_STATUS_OK;
7944 TALLOC_CTX *ctx = talloc_tos();
7946 DEBUG(10,("call_trans2getdfsreferral\n"));
7948 if (total_params < 3) {
7949 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7953 max_referral_level = SVAL(params,0);
7955 if(!lp_host_msdfs()) {
7956 reply_doserror(req, ERRDOS, ERRbadfunc);
7960 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7961 total_params - 2, STR_TERMINATE);
7963 reply_nterror(req, NT_STATUS_NOT_FOUND);
7966 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7967 ppdata,&status)) < 0) {
7968 reply_nterror(req, status);
7972 SSVAL(req->inbuf, smb_flg2,
7973 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7974 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7979 #define LMCAT_SPL 0x53
7980 #define LMFUNC_GETJOBID 0x60
7982 /****************************************************************************
7983 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7984 ****************************************************************************/
7986 static void call_trans2ioctl(connection_struct *conn,
7987 struct smb_request *req,
7988 char **pparams, int total_params,
7989 char **ppdata, int total_data,
7990 unsigned int max_data_bytes)
7992 char *pdata = *ppdata;
7993 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7995 /* check for an invalid fid before proceeding */
7998 reply_doserror(req, ERRDOS, ERRbadfid);
8002 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8003 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8004 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8005 if (*ppdata == NULL) {
8006 reply_nterror(req, NT_STATUS_NO_MEMORY);
8011 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8012 CAN ACCEPT THIS IN UNICODE. JRA. */
8014 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
8015 srvstr_push(pdata, req->flags2, pdata + 2,
8016 global_myname(), 15,
8017 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8018 srvstr_push(pdata, req->flags2, pdata+18,
8019 lp_servicename(SNUM(conn)), 13,
8020 STR_ASCII|STR_TERMINATE); /* Service name */
8021 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8026 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8027 reply_doserror(req, ERRSRV, ERRerror);
8030 /****************************************************************************
8031 Reply to a SMBfindclose (stop trans2 directory search).
8032 ****************************************************************************/
8034 void reply_findclose(struct smb_request *req)
8037 struct smbd_server_connection *sconn = smbd_server_conn;
8039 START_PROFILE(SMBfindclose);
8042 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8043 END_PROFILE(SMBfindclose);
8047 dptr_num = SVALS(req->vwv+0, 0);
8049 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8051 dptr_close(sconn, &dptr_num);
8053 reply_outbuf(req, 0, 0);
8055 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8057 END_PROFILE(SMBfindclose);
8061 /****************************************************************************
8062 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8063 ****************************************************************************/
8065 void reply_findnclose(struct smb_request *req)
8069 START_PROFILE(SMBfindnclose);
8072 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8073 END_PROFILE(SMBfindnclose);
8077 dptr_num = SVAL(req->vwv+0, 0);
8079 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8081 /* We never give out valid handles for a
8082 findnotifyfirst - so any dptr_num is ok here.
8085 reply_outbuf(req, 0, 0);
8087 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8089 END_PROFILE(SMBfindnclose);
8093 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8094 struct trans_state *state)
8096 if (Protocol >= PROTOCOL_NT1) {
8097 req->flags2 |= 0x40; /* IS_LONG_NAME */
8098 SSVAL(req->inbuf,smb_flg2,req->flags2);
8101 if (conn->encrypt_level == Required && !req->encrypted) {
8102 if (state->call != TRANSACT2_QFSINFO &&
8103 state->call != TRANSACT2_SETFSINFO) {
8104 DEBUG(0,("handle_trans2: encryption required "
8106 (unsigned int)state->call));
8107 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8112 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8114 /* Now we must call the relevant TRANS2 function */
8115 switch(state->call) {
8116 case TRANSACT2_OPEN:
8118 START_PROFILE(Trans2_open);
8119 call_trans2open(conn, req,
8120 &state->param, state->total_param,
8121 &state->data, state->total_data,
8122 state->max_data_return);
8123 END_PROFILE(Trans2_open);
8127 case TRANSACT2_FINDFIRST:
8129 START_PROFILE(Trans2_findfirst);
8130 call_trans2findfirst(conn, req,
8131 &state->param, state->total_param,
8132 &state->data, state->total_data,
8133 state->max_data_return);
8134 END_PROFILE(Trans2_findfirst);
8138 case TRANSACT2_FINDNEXT:
8140 START_PROFILE(Trans2_findnext);
8141 call_trans2findnext(conn, req,
8142 &state->param, state->total_param,
8143 &state->data, state->total_data,
8144 state->max_data_return);
8145 END_PROFILE(Trans2_findnext);
8149 case TRANSACT2_QFSINFO:
8151 START_PROFILE(Trans2_qfsinfo);
8152 call_trans2qfsinfo(conn, req,
8153 &state->param, state->total_param,
8154 &state->data, state->total_data,
8155 state->max_data_return);
8156 END_PROFILE(Trans2_qfsinfo);
8160 case TRANSACT2_SETFSINFO:
8162 START_PROFILE(Trans2_setfsinfo);
8163 call_trans2setfsinfo(conn, req,
8164 &state->param, state->total_param,
8165 &state->data, state->total_data,
8166 state->max_data_return);
8167 END_PROFILE(Trans2_setfsinfo);
8171 case TRANSACT2_QPATHINFO:
8172 case TRANSACT2_QFILEINFO:
8174 START_PROFILE(Trans2_qpathinfo);
8175 call_trans2qfilepathinfo(conn, req, state->call,
8176 &state->param, state->total_param,
8177 &state->data, state->total_data,
8178 state->max_data_return);
8179 END_PROFILE(Trans2_qpathinfo);
8183 case TRANSACT2_SETPATHINFO:
8184 case TRANSACT2_SETFILEINFO:
8186 START_PROFILE(Trans2_setpathinfo);
8187 call_trans2setfilepathinfo(conn, req, state->call,
8188 &state->param, state->total_param,
8189 &state->data, state->total_data,
8190 state->max_data_return);
8191 END_PROFILE(Trans2_setpathinfo);
8195 case TRANSACT2_FINDNOTIFYFIRST:
8197 START_PROFILE(Trans2_findnotifyfirst);
8198 call_trans2findnotifyfirst(conn, req,
8199 &state->param, state->total_param,
8200 &state->data, state->total_data,
8201 state->max_data_return);
8202 END_PROFILE(Trans2_findnotifyfirst);
8206 case TRANSACT2_FINDNOTIFYNEXT:
8208 START_PROFILE(Trans2_findnotifynext);
8209 call_trans2findnotifynext(conn, req,
8210 &state->param, state->total_param,
8211 &state->data, state->total_data,
8212 state->max_data_return);
8213 END_PROFILE(Trans2_findnotifynext);
8217 case TRANSACT2_MKDIR:
8219 START_PROFILE(Trans2_mkdir);
8220 call_trans2mkdir(conn, req,
8221 &state->param, state->total_param,
8222 &state->data, state->total_data,
8223 state->max_data_return);
8224 END_PROFILE(Trans2_mkdir);
8228 case TRANSACT2_GET_DFS_REFERRAL:
8230 START_PROFILE(Trans2_get_dfs_referral);
8231 call_trans2getdfsreferral(conn, req,
8232 &state->param, state->total_param,
8233 &state->data, state->total_data,
8234 state->max_data_return);
8235 END_PROFILE(Trans2_get_dfs_referral);
8239 case TRANSACT2_IOCTL:
8241 START_PROFILE(Trans2_ioctl);
8242 call_trans2ioctl(conn, req,
8243 &state->param, state->total_param,
8244 &state->data, state->total_data,
8245 state->max_data_return);
8246 END_PROFILE(Trans2_ioctl);
8251 /* Error in request */
8252 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8253 reply_doserror(req, ERRSRV,ERRerror);
8257 /****************************************************************************
8258 Reply to a SMBtrans2.
8259 ****************************************************************************/
8261 void reply_trans2(struct smb_request *req)
8263 connection_struct *conn = req->conn;
8268 unsigned int tran_call;
8269 struct trans_state *state;
8272 START_PROFILE(SMBtrans2);
8274 if (req->wct < 14) {
8275 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8276 END_PROFILE(SMBtrans2);
8280 dsoff = SVAL(req->vwv+12, 0);
8281 dscnt = SVAL(req->vwv+11, 0);
8282 psoff = SVAL(req->vwv+10, 0);
8283 pscnt = SVAL(req->vwv+9, 0);
8284 tran_call = SVAL(req->vwv+14, 0);
8286 result = allow_new_trans(conn->pending_trans, req->mid);
8287 if (!NT_STATUS_IS_OK(result)) {
8288 DEBUG(2, ("Got invalid trans2 request: %s\n",
8289 nt_errstr(result)));
8290 reply_nterror(req, result);
8291 END_PROFILE(SMBtrans2);
8296 switch (tran_call) {
8297 /* List the allowed trans2 calls on IPC$ */
8298 case TRANSACT2_OPEN:
8299 case TRANSACT2_GET_DFS_REFERRAL:
8300 case TRANSACT2_QFILEINFO:
8301 case TRANSACT2_QFSINFO:
8302 case TRANSACT2_SETFSINFO:
8305 reply_doserror(req, ERRSRV, ERRaccess);
8306 END_PROFILE(SMBtrans2);
8311 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8312 DEBUG(0, ("talloc failed\n"));
8313 reply_nterror(req, NT_STATUS_NO_MEMORY);
8314 END_PROFILE(SMBtrans2);
8318 state->cmd = SMBtrans2;
8320 state->mid = req->mid;
8321 state->vuid = req->vuid;
8322 state->setup_count = SVAL(req->vwv+13, 0);
8323 state->setup = NULL;
8324 state->total_param = SVAL(req->vwv+0, 0);
8325 state->param = NULL;
8326 state->total_data = SVAL(req->vwv+1, 0);
8328 state->max_param_return = SVAL(req->vwv+2, 0);
8329 state->max_data_return = SVAL(req->vwv+3, 0);
8330 state->max_setup_return = SVAL(req->vwv+4, 0);
8331 state->close_on_completion = BITSETW(req->vwv+5, 0);
8332 state->one_way = BITSETW(req->vwv+5, 1);
8334 state->call = tran_call;
8336 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8337 is so as a sanity check */
8338 if (state->setup_count != 1) {
8340 * Need to have rc=0 for ioctl to get job id for OS/2.
8341 * Network printing will fail if function is not successful.
8342 * Similar function in reply.c will be used if protocol
8343 * is LANMAN1.0 instead of LM1.2X002.
8344 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8345 * outbuf doesn't have to be set(only job id is used).
8347 if ( (state->setup_count == 4)
8348 && (tran_call == TRANSACT2_IOCTL)
8349 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8350 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8351 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8353 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8354 DEBUG(2,("Transaction is %d\n",tran_call));
8356 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8357 END_PROFILE(SMBtrans2);
8362 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8365 if (state->total_data) {
8367 if (trans_oob(state->total_data, 0, dscnt)
8368 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8372 /* Can't use talloc here, the core routines do realloc on the
8373 * params and data. */
8374 state->data = (char *)SMB_MALLOC(state->total_data);
8375 if (state->data == NULL) {
8376 DEBUG(0,("reply_trans2: data malloc fail for %u "
8377 "bytes !\n", (unsigned int)state->total_data));
8379 reply_nterror(req, NT_STATUS_NO_MEMORY);
8380 END_PROFILE(SMBtrans2);
8384 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8387 if (state->total_param) {
8389 if (trans_oob(state->total_param, 0, pscnt)
8390 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8394 /* Can't use talloc here, the core routines do realloc on the
8395 * params and data. */
8396 state->param = (char *)SMB_MALLOC(state->total_param);
8397 if (state->param == NULL) {
8398 DEBUG(0,("reply_trans: param malloc fail for %u "
8399 "bytes !\n", (unsigned int)state->total_param));
8400 SAFE_FREE(state->data);
8402 reply_nterror(req, NT_STATUS_NO_MEMORY);
8403 END_PROFILE(SMBtrans2);
8407 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8410 state->received_data = dscnt;
8411 state->received_param = pscnt;
8413 if ((state->received_param == state->total_param) &&
8414 (state->received_data == state->total_data)) {
8416 handle_trans2(conn, req, state);
8418 SAFE_FREE(state->data);
8419 SAFE_FREE(state->param);
8421 END_PROFILE(SMBtrans2);
8425 DLIST_ADD(conn->pending_trans, state);
8427 /* We need to send an interim response then receive the rest
8428 of the parameter/data bytes */
8429 reply_outbuf(req, 0, 0);
8430 show_msg((char *)req->outbuf);
8431 END_PROFILE(SMBtrans2);
8436 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8437 SAFE_FREE(state->data);
8438 SAFE_FREE(state->param);
8440 END_PROFILE(SMBtrans2);
8441 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8445 /****************************************************************************
8446 Reply to a SMBtranss2
8447 ****************************************************************************/
8449 void reply_transs2(struct smb_request *req)
8451 connection_struct *conn = req->conn;
8452 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8453 struct trans_state *state;
8455 START_PROFILE(SMBtranss2);
8457 show_msg((char *)req->inbuf);
8460 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8461 END_PROFILE(SMBtranss2);
8465 for (state = conn->pending_trans; state != NULL;
8466 state = state->next) {
8467 if (state->mid == req->mid) {
8472 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8473 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8474 END_PROFILE(SMBtranss2);
8478 /* Revise state->total_param and state->total_data in case they have
8479 changed downwards */
8481 if (SVAL(req->vwv+0, 0) < state->total_param)
8482 state->total_param = SVAL(req->vwv+0, 0);
8483 if (SVAL(req->vwv+1, 0) < state->total_data)
8484 state->total_data = SVAL(req->vwv+1, 0);
8486 pcnt = SVAL(req->vwv+2, 0);
8487 poff = SVAL(req->vwv+3, 0);
8488 pdisp = SVAL(req->vwv+4, 0);
8490 dcnt = SVAL(req->vwv+5, 0);
8491 doff = SVAL(req->vwv+6, 0);
8492 ddisp = SVAL(req->vwv+7, 0);
8494 state->received_param += pcnt;
8495 state->received_data += dcnt;
8497 if ((state->received_data > state->total_data) ||
8498 (state->received_param > state->total_param))
8502 if (trans_oob(state->total_param, pdisp, pcnt)
8503 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8506 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8510 if (trans_oob(state->total_data, ddisp, dcnt)
8511 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8514 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8517 if ((state->received_param < state->total_param) ||
8518 (state->received_data < state->total_data)) {
8519 END_PROFILE(SMBtranss2);
8523 handle_trans2(conn, req, state);
8525 DLIST_REMOVE(conn->pending_trans, state);
8526 SAFE_FREE(state->data);
8527 SAFE_FREE(state->param);
8530 END_PROFILE(SMBtranss2);
8535 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8536 DLIST_REMOVE(conn->pending_trans, state);
8537 SAFE_FREE(state->data);
8538 SAFE_FREE(state->param);
8540 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8541 END_PROFILE(SMBtranss2);