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 #define DIR_ENTRY_SAFETY_MARGIN 4096
33 static char *store_file_unix_basic(connection_struct *conn,
36 const SMB_STRUCT_STAT *psbuf);
38 static char *store_file_unix_basic_info2(connection_struct *conn,
41 const SMB_STRUCT_STAT *psbuf);
43 /********************************************************************
44 Roundup a value to the nearest allocation roundup size boundary.
45 Only do this for Windows clients.
46 ********************************************************************/
48 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
50 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
52 /* Only roundup for Windows clients. */
53 enum remote_arch_types ra_type = get_remote_arch();
54 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
55 val = SMB_ROUNDUP(val,rval);
60 /****************************************************************************
61 Utility functions for dealing with extended attributes.
62 ****************************************************************************/
64 /****************************************************************************
65 Refuse to allow clients to overwrite our private xattrs.
66 ****************************************************************************/
68 static bool samba_private_attr_name(const char *unix_ea_name)
70 static const char * const prohibited_ea_names[] = {
71 SAMBA_POSIX_INHERITANCE_EA_NAME,
72 SAMBA_XATTR_DOS_ATTRIB,
73 SAMBA_XATTR_DOSTIMESTAMPS,
80 for (i = 0; prohibited_ea_names[i]; i++) {
81 if (strequal( prohibited_ea_names[i], unix_ea_name))
84 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
85 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
91 /****************************************************************************
92 Get one EA value. Fill in a struct ea_struct.
93 ****************************************************************************/
95 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
96 files_struct *fsp, const char *fname,
97 const char *ea_name, struct ea_struct *pea)
99 /* Get the value of this xattr. Max size is 64k. */
100 size_t attr_size = 256;
106 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
108 return NT_STATUS_NO_MEMORY;
111 if (fsp && fsp->fh->fd != -1) {
112 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
114 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
117 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
123 return map_nt_error_from_unix(errno);
126 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
127 dump_data(10, (uint8 *)val, sizeret);
130 if (strnequal(ea_name, "user.", 5)) {
131 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
133 pea->name = talloc_strdup(mem_ctx, ea_name);
135 if (pea->name == NULL) {
137 return NT_STATUS_NO_MEMORY;
139 pea->value.data = (unsigned char *)val;
140 pea->value.length = (size_t)sizeret;
144 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
145 files_struct *fsp, const char *fname,
146 char ***pnames, size_t *pnum_names)
148 /* Get a list of all xattrs. Max namesize is 64k. */
149 size_t ea_namelist_size = 1024;
150 char *ea_namelist = NULL;
155 ssize_t sizeret = -1;
157 if (!lp_ea_support(SNUM(conn))) {
166 * TALLOC the result early to get the talloc hierarchy right.
169 names = TALLOC_ARRAY(mem_ctx, char *, 1);
171 DEBUG(0, ("talloc failed\n"));
172 return NT_STATUS_NO_MEMORY;
175 while (ea_namelist_size <= 65536) {
177 ea_namelist = TALLOC_REALLOC_ARRAY(
178 names, ea_namelist, char, ea_namelist_size);
179 if (ea_namelist == NULL) {
180 DEBUG(0, ("talloc failed\n"));
182 return NT_STATUS_NO_MEMORY;
185 if (fsp && fsp->fh->fd != -1) {
186 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
189 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
193 if ((sizeret == -1) && (errno == ERANGE)) {
194 ea_namelist_size *= 2;
203 return map_nt_error_from_unix(errno);
206 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
207 (unsigned int)sizeret));
219 * Ensure the result is 0-terminated
222 if (ea_namelist[sizeret-1] != '\0') {
224 return NT_STATUS_INTERNAL_ERROR;
232 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
236 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
238 DEBUG(0, ("talloc failed\n"));
240 return NT_STATUS_NO_MEMORY;
246 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
247 names[num_names++] = p;
255 *pnum_names = num_names;
259 /****************************************************************************
260 Return a linked list of the total EA's. Plus the total size
261 ****************************************************************************/
263 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
264 const char *fname, size_t *pea_total_len)
266 /* Get a list of all xattrs. Max namesize is 64k. */
269 struct ea_list *ea_list_head = NULL;
274 if (!lp_ea_support(SNUM(conn))) {
278 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
281 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
285 for (i=0; i<num_names; i++) {
286 struct ea_list *listp;
289 if (strnequal(names[i], "system.", 7)
290 || samba_private_attr_name(names[i]))
293 listp = TALLOC_P(mem_ctx, struct ea_list);
298 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
304 push_ascii_fstring(dos_ea_name, listp->ea.name);
307 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
309 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
310 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
311 (unsigned int)listp->ea.value.length));
313 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
317 /* Add on 4 for total length. */
318 if (*pea_total_len) {
322 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
323 (unsigned int)*pea_total_len));
328 /****************************************************************************
329 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
331 ****************************************************************************/
333 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
334 connection_struct *conn, struct ea_list *ea_list)
336 unsigned int ret_data_size = 4;
339 SMB_ASSERT(total_data_size >= 4);
341 if (!lp_ea_support(SNUM(conn))) {
346 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
349 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
350 dos_namelen = strlen(dos_ea_name);
351 if (dos_namelen > 255 || dos_namelen == 0) {
354 if (ea_list->ea.value.length > 65535) {
357 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
361 /* We know we have room. */
362 SCVAL(p,0,ea_list->ea.flags);
363 SCVAL(p,1,dos_namelen);
364 SSVAL(p,2,ea_list->ea.value.length);
365 fstrcpy(p+4, dos_ea_name);
366 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
368 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
369 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
372 ret_data_size = PTR_DIFF(p, pdata);
373 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
374 SIVAL(pdata,0,ret_data_size);
375 return ret_data_size;
378 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
380 unsigned int total_data_size,
381 unsigned int *ret_data_size,
382 connection_struct *conn,
383 struct ea_list *ea_list)
385 uint8_t *p = (uint8_t *)pdata;
386 uint8_t *last_start = NULL;
390 if (!lp_ea_support(SNUM(conn))) {
391 return NT_STATUS_NO_EAS_ON_FILE;
394 for (; ea_list; ea_list = ea_list->next) {
400 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
404 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
405 dos_namelen = strlen(dos_ea_name);
406 if (dos_namelen > 255 || dos_namelen == 0) {
407 return NT_STATUS_INTERNAL_ERROR;
409 if (ea_list->ea.value.length > 65535) {
410 return NT_STATUS_INTERNAL_ERROR;
413 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
416 size_t pad = 4 - (this_size % 4);
420 if (this_size > total_data_size) {
421 return NT_STATUS_INFO_LENGTH_MISMATCH;
424 /* We know we have room. */
425 SIVAL(p, 0x00, 0); /* next offset */
426 SCVAL(p, 0x04, ea_list->ea.flags);
427 SCVAL(p, 0x05, dos_namelen);
428 SSVAL(p, 0x06, ea_list->ea.value.length);
429 fstrcpy((char *)(p+0x08), dos_ea_name);
430 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
432 total_data_size -= this_size;
436 *ret_data_size = PTR_DIFF(p, pdata);
437 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
441 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
443 size_t total_ea_len = 0;
444 TALLOC_CTX *mem_ctx = NULL;
446 if (!lp_ea_support(SNUM(conn))) {
449 mem_ctx = talloc_tos();
450 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
454 /****************************************************************************
455 Ensure the EA name is case insensitive by matching any existing EA name.
456 ****************************************************************************/
458 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
461 TALLOC_CTX *mem_ctx = talloc_tos();
462 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
464 for (; ea_list; ea_list = ea_list->next) {
465 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
466 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
467 &unix_ea_name[5], ea_list->ea.name));
468 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
474 /****************************************************************************
475 Set or delete an extended attribute.
476 ****************************************************************************/
478 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
479 const struct smb_filename *smb_fname, struct ea_list *ea_list)
483 if (!lp_ea_support(SNUM(conn))) {
484 return NT_STATUS_EAS_NOT_SUPPORTED;
487 /* For now setting EAs on streams isn't supported. */
488 fname = smb_fname->base_name;
490 for (;ea_list; ea_list = ea_list->next) {
492 fstring unix_ea_name;
494 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
495 fstrcat(unix_ea_name, ea_list->ea.name);
497 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
499 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
501 if (samba_private_attr_name(unix_ea_name)) {
502 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
503 return NT_STATUS_ACCESS_DENIED;
506 if (ea_list->ea.value.length == 0) {
507 /* Remove the attribute. */
508 if (fsp && (fsp->fh->fd != -1)) {
509 DEBUG(10,("set_ea: deleting ea name %s on "
510 "file %s by file descriptor.\n",
511 unix_ea_name, fsp_str_dbg(fsp)));
512 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
514 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
515 unix_ea_name, fname));
516 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
519 /* Removing a non existent attribute always succeeds. */
520 if (ret == -1 && errno == ENOATTR) {
521 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
527 if (fsp && (fsp->fh->fd != -1)) {
528 DEBUG(10,("set_ea: setting ea name %s on file "
529 "%s by file descriptor.\n",
530 unix_ea_name, fsp_str_dbg(fsp)));
531 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
532 ea_list->ea.value.data, ea_list->ea.value.length, 0);
534 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
535 unix_ea_name, fname));
536 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
537 ea_list->ea.value.data, ea_list->ea.value.length, 0);
543 if (errno == ENOTSUP) {
544 return NT_STATUS_EAS_NOT_SUPPORTED;
547 return map_nt_error_from_unix(errno);
553 /****************************************************************************
554 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
555 ****************************************************************************/
557 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
559 struct ea_list *ea_list_head = NULL;
560 size_t converted_size, offset = 0;
562 while (offset + 2 < data_size) {
563 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
564 unsigned int namelen = CVAL(pdata,offset);
566 offset++; /* Go past the namelen byte. */
568 /* integer wrap paranioa. */
569 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
570 (offset > data_size) || (namelen > data_size) ||
571 (offset + namelen >= data_size)) {
574 /* Ensure the name is null terminated. */
575 if (pdata[offset + namelen] != '\0') {
578 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
580 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
581 "failed: %s", strerror(errno)));
587 offset += (namelen + 1); /* Go past the name + terminating zero. */
588 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
589 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
595 /****************************************************************************
596 Read one EA list entry from the buffer.
597 ****************************************************************************/
599 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
601 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
603 unsigned int namelen;
604 size_t converted_size;
614 eal->ea.flags = CVAL(pdata,0);
615 namelen = CVAL(pdata,1);
616 val_len = SVAL(pdata,2);
618 if (4 + namelen + 1 + val_len > data_size) {
622 /* Ensure the name is null terminated. */
623 if (pdata[namelen + 4] != '\0') {
626 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
627 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
634 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
635 if (!eal->ea.value.data) {
639 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
641 /* Ensure we're null terminated just in case we print the value. */
642 eal->ea.value.data[val_len] = '\0';
643 /* But don't count the null. */
644 eal->ea.value.length--;
647 *pbytes_used = 4 + namelen + 1 + val_len;
650 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
651 dump_data(10, eal->ea.value.data, eal->ea.value.length);
656 /****************************************************************************
657 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
658 ****************************************************************************/
660 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
662 struct ea_list *ea_list_head = NULL;
664 size_t bytes_used = 0;
666 while (offset < data_size) {
667 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
673 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
674 offset += bytes_used;
680 /****************************************************************************
681 Count the total EA size needed.
682 ****************************************************************************/
684 static size_t ea_list_size(struct ea_list *ealist)
687 struct ea_list *listp;
690 for (listp = ealist; listp; listp = listp->next) {
691 push_ascii_fstring(dos_ea_name, listp->ea.name);
692 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
694 /* Add on 4 for total length. */
702 /****************************************************************************
703 Return a union of EA's from a file list and a list of names.
704 The TALLOC context for the two lists *MUST* be identical as we steal
705 memory from one list to add to another. JRA.
706 ****************************************************************************/
708 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
710 struct ea_list *nlistp, *flistp;
712 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
713 for (flistp = file_list; flistp; flistp = flistp->next) {
714 if (strequal(nlistp->ea.name, flistp->ea.name)) {
720 /* Copy the data from this entry. */
721 nlistp->ea.flags = flistp->ea.flags;
722 nlistp->ea.value = flistp->ea.value;
725 nlistp->ea.flags = 0;
726 ZERO_STRUCT(nlistp->ea.value);
730 *total_ea_len = ea_list_size(name_list);
734 /****************************************************************************
735 Send the required number of replies back.
736 We assume all fields other than the data fields are
737 set correctly for the type of call.
738 HACK ! Always assumes smb_setup field is zero.
739 ****************************************************************************/
741 void send_trans2_replies(connection_struct *conn,
742 struct smb_request *req,
749 /* As we are using a protocol > LANMAN1 then the max_send
750 variable must have been set in the sessetupX call.
751 This takes precedence over the max_xmit field in the
752 global struct. These different max_xmit variables should
753 be merged as this is now too confusing */
755 int data_to_send = datasize;
756 int params_to_send = paramsize;
758 const char *pp = params;
759 const char *pd = pdata;
760 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
761 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
762 int data_alignment_offset = 0;
763 bool overflow = False;
764 struct smbd_server_connection *sconn = smbd_server_conn;
765 int max_send = sconn->smb1.sessions.max_send;
767 /* Modify the data_to_send and datasize and set the error if
768 we're trying to send more than max_data_bytes. We still send
769 the part of the packet(s) that fit. Strange, but needed
772 if (max_data_bytes > 0 && datasize > max_data_bytes) {
773 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
774 max_data_bytes, datasize ));
775 datasize = data_to_send = max_data_bytes;
779 /* If there genuinely are no parameters or data to send just send the empty packet */
781 if(params_to_send == 0 && data_to_send == 0) {
782 reply_outbuf(req, 10, 0);
783 show_msg((char *)req->outbuf);
784 if (!srv_send_smb(smbd_server_fd(),
787 IS_CONN_ENCRYPTED(conn),
789 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
791 TALLOC_FREE(req->outbuf);
795 /* When sending params and data ensure that both are nicely aligned */
796 /* Only do this alignment when there is also data to send - else
797 can cause NT redirector problems. */
799 if (((params_to_send % 4) != 0) && (data_to_send != 0))
800 data_alignment_offset = 4 - (params_to_send % 4);
802 /* Space is bufsize minus Netbios over TCP header minus SMB header */
803 /* The alignment_offset is to align the param bytes on an even byte
804 boundary. NT 4.0 Beta needs this to work correctly. */
806 useable_space = max_send - (smb_size
809 + data_alignment_offset);
811 if (useable_space < 0) {
812 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
813 "= %d!!!", useable_space));
814 exit_server_cleanly("send_trans2_replies: Not enough space");
817 while (params_to_send || data_to_send) {
818 /* Calculate whether we will totally or partially fill this packet */
820 total_sent_thistime = params_to_send + data_to_send;
822 /* We can never send more than useable_space */
824 * Note that 'useable_space' does not include the alignment offsets,
825 * but we must include the alignment offsets in the calculation of
826 * the length of the data we send over the wire, as the alignment offsets
827 * are sent here. Fix from Marc_Jacobsen@hp.com.
830 total_sent_thistime = MIN(total_sent_thistime, useable_space);
832 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
833 + data_alignment_offset);
836 * We might have SMBtrans2s in req which was transferred to
837 * the outbuf, fix that.
839 SCVAL(req->outbuf, smb_com, SMBtrans2);
841 /* Set total params and data to be sent */
842 SSVAL(req->outbuf,smb_tprcnt,paramsize);
843 SSVAL(req->outbuf,smb_tdrcnt,datasize);
845 /* Calculate how many parameters and data we can fit into
846 * this packet. Parameters get precedence
849 params_sent_thistime = MIN(params_to_send,useable_space);
850 data_sent_thistime = useable_space - params_sent_thistime;
851 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
853 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
855 /* smb_proff is the offset from the start of the SMB header to the
856 parameter bytes, however the first 4 bytes of outbuf are
857 the Netbios over TCP header. Thus use smb_base() to subtract
858 them from the calculation */
860 SSVAL(req->outbuf,smb_proff,
861 ((smb_buf(req->outbuf)+alignment_offset)
862 - smb_base(req->outbuf)));
864 if(params_sent_thistime == 0)
865 SSVAL(req->outbuf,smb_prdisp,0);
867 /* Absolute displacement of param bytes sent in this packet */
868 SSVAL(req->outbuf,smb_prdisp,pp - params);
870 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
871 if(data_sent_thistime == 0) {
872 SSVAL(req->outbuf,smb_droff,0);
873 SSVAL(req->outbuf,smb_drdisp, 0);
875 /* The offset of the data bytes is the offset of the
876 parameter bytes plus the number of parameters being sent this time */
877 SSVAL(req->outbuf, smb_droff,
878 ((smb_buf(req->outbuf)+alignment_offset)
879 - smb_base(req->outbuf))
880 + params_sent_thistime + data_alignment_offset);
881 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
884 /* Initialize the padding for alignment */
886 if (alignment_offset != 0) {
887 memset(smb_buf(req->outbuf), 0, alignment_offset);
890 /* Copy the param bytes into the packet */
892 if(params_sent_thistime) {
893 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
894 params_sent_thistime);
897 /* Copy in the data bytes */
898 if(data_sent_thistime) {
899 if (data_alignment_offset != 0) {
900 memset((smb_buf(req->outbuf)+alignment_offset+
901 params_sent_thistime), 0,
902 data_alignment_offset);
904 memcpy(smb_buf(req->outbuf)+alignment_offset
905 +params_sent_thistime+data_alignment_offset,
906 pd,data_sent_thistime);
909 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
910 params_sent_thistime, data_sent_thistime, useable_space));
911 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
912 params_to_send, data_to_send, paramsize, datasize));
915 error_packet_set((char *)req->outbuf,
916 ERRDOS,ERRbufferoverflow,
917 STATUS_BUFFER_OVERFLOW,
921 /* Send the packet */
922 show_msg((char *)req->outbuf);
923 if (!srv_send_smb(smbd_server_fd(),
926 IS_CONN_ENCRYPTED(conn),
928 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
930 TALLOC_FREE(req->outbuf);
932 pp += params_sent_thistime;
933 pd += data_sent_thistime;
935 params_to_send -= params_sent_thistime;
936 data_to_send -= data_sent_thistime;
939 if(params_to_send < 0 || data_to_send < 0) {
940 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
941 params_to_send, data_to_send));
949 /****************************************************************************
950 Reply to a TRANSACT2_OPEN.
951 ****************************************************************************/
953 static void call_trans2open(connection_struct *conn,
954 struct smb_request *req,
955 char **pparams, int total_params,
956 char **ppdata, int total_data,
957 unsigned int max_data_bytes)
959 struct smb_filename *smb_fname = NULL;
960 char *params = *pparams;
961 char *pdata = *ppdata;
966 bool return_additional_info;
979 struct ea_list *ea_list = NULL;
984 uint32 create_disposition;
985 uint32 create_options = 0;
986 TALLOC_CTX *ctx = talloc_tos();
989 * Ensure we have enough parameters to perform the operation.
992 if (total_params < 29) {
993 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
997 flags = SVAL(params, 0);
998 deny_mode = SVAL(params, 2);
999 open_attr = SVAL(params,6);
1000 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1001 if (oplock_request) {
1002 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1006 return_additional_info = BITSETW(params,0);
1007 open_sattr = SVAL(params, 4);
1008 open_time = make_unix_date3(params+8);
1010 open_ofun = SVAL(params,12);
1011 open_size = IVAL(params,14);
1012 pname = ¶ms[28];
1015 reply_doserror(req, ERRSRV, ERRaccess);
1019 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1020 total_params - 28, STR_TERMINATE,
1022 if (!NT_STATUS_IS_OK(status)) {
1023 reply_nterror(req, status);
1027 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1028 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1029 (unsigned int)open_ofun, open_size));
1031 status = filename_convert(ctx,
1033 req->flags2 & FLAGS2_DFS_PATHNAMES,
1038 if (!NT_STATUS_IS_OK(status)) {
1039 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1040 reply_botherror(req,
1041 NT_STATUS_PATH_NOT_COVERED,
1042 ERRSRV, ERRbadpath);
1045 reply_nterror(req, status);
1049 if (open_ofun == 0) {
1050 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1054 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, open_ofun,
1055 &access_mask, &share_mode,
1056 &create_disposition,
1058 reply_doserror(req, ERRDOS, ERRbadaccess);
1062 /* Any data in this call is an EA list. */
1063 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
1064 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1068 if (total_data != 4) {
1069 if (total_data < 10) {
1070 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1074 if (IVAL(pdata,0) > total_data) {
1075 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1076 IVAL(pdata,0), (unsigned int)total_data));
1077 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1081 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1084 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1087 } else if (IVAL(pdata,0) != 4) {
1088 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1092 status = SMB_VFS_CREATE_FILE(
1095 0, /* root_dir_fid */
1096 smb_fname, /* fname */
1097 access_mask, /* access_mask */
1098 share_mode, /* share_access */
1099 create_disposition, /* create_disposition*/
1100 create_options, /* create_options */
1101 open_attr, /* file_attributes */
1102 oplock_request, /* oplock_request */
1103 open_size, /* allocation_size */
1105 ea_list, /* ea_list */
1107 &smb_action); /* psbuf */
1109 if (!NT_STATUS_IS_OK(status)) {
1110 if (open_was_deferred(req->mid)) {
1111 /* We have re-scheduled this call. */
1114 reply_openerror(req, status);
1118 size = get_file_size_stat(&smb_fname->st);
1119 fattr = dos_mode(conn, smb_fname);
1120 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1121 inode = smb_fname->st.st_ex_ino;
1123 close_file(req, fsp, ERROR_CLOSE);
1124 reply_doserror(req, ERRDOS,ERRnoaccess);
1128 /* Realloc the size of parameters and data we will return */
1129 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1130 if(*pparams == NULL ) {
1131 reply_nterror(req, NT_STATUS_NO_MEMORY);
1136 SSVAL(params,0,fsp->fnum);
1137 SSVAL(params,2,fattr);
1138 srv_put_dos_date2(params,4, mtime);
1139 SIVAL(params,8, (uint32)size);
1140 SSVAL(params,12,deny_mode);
1141 SSVAL(params,14,0); /* open_type - file or directory. */
1142 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1144 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1145 smb_action |= EXTENDED_OPLOCK_GRANTED;
1148 SSVAL(params,18,smb_action);
1151 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1153 SIVAL(params,20,inode);
1154 SSVAL(params,24,0); /* Padding. */
1156 uint32 ea_size = estimate_ea_size(conn, fsp,
1157 fsp->fsp_name->base_name);
1158 SIVAL(params, 26, ea_size);
1160 SIVAL(params, 26, 0);
1163 /* Send the required number of replies */
1164 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1166 TALLOC_FREE(smb_fname);
1169 /*********************************************************
1170 Routine to check if a given string matches exactly.
1171 as a special case a mask of "." does NOT match. That
1172 is required for correct wildcard semantics
1173 Case can be significant or not.
1174 **********************************************************/
1176 static bool exact_match(bool has_wild,
1177 bool case_sensitive,
1181 if (mask[0] == '.' && mask[1] == 0) {
1189 if (case_sensitive) {
1190 return strcmp(str,mask)==0;
1192 return StrCaseCmp(str,mask) == 0;
1196 /****************************************************************************
1197 Return the filetype for UNIX extensions.
1198 ****************************************************************************/
1200 static uint32 unix_filetype(mode_t mode)
1203 return UNIX_TYPE_FILE;
1204 else if(S_ISDIR(mode))
1205 return UNIX_TYPE_DIR;
1207 else if(S_ISLNK(mode))
1208 return UNIX_TYPE_SYMLINK;
1211 else if(S_ISCHR(mode))
1212 return UNIX_TYPE_CHARDEV;
1215 else if(S_ISBLK(mode))
1216 return UNIX_TYPE_BLKDEV;
1219 else if(S_ISFIFO(mode))
1220 return UNIX_TYPE_FIFO;
1223 else if(S_ISSOCK(mode))
1224 return UNIX_TYPE_SOCKET;
1227 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1228 return UNIX_TYPE_UNKNOWN;
1231 /****************************************************************************
1232 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1233 ****************************************************************************/
1235 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1237 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1238 const SMB_STRUCT_STAT *psbuf,
1240 enum perm_type ptype,
1245 if (perms == SMB_MODE_NO_CHANGE) {
1246 if (!VALID_STAT(*psbuf)) {
1247 return NT_STATUS_INVALID_PARAMETER;
1249 *ret_perms = psbuf->st_ex_mode;
1250 return NT_STATUS_OK;
1254 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1255 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1256 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1257 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1258 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1259 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1260 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1261 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1262 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1264 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1267 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1270 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1275 /* Apply mode mask */
1276 ret &= lp_create_mask(SNUM(conn));
1277 /* Add in force bits */
1278 ret |= lp_force_create_mode(SNUM(conn));
1281 ret &= lp_dir_mask(SNUM(conn));
1282 /* Add in force bits */
1283 ret |= lp_force_dir_mode(SNUM(conn));
1285 case PERM_EXISTING_FILE:
1286 /* Apply mode mask */
1287 ret &= lp_security_mask(SNUM(conn));
1288 /* Add in force bits */
1289 ret |= lp_force_security_mode(SNUM(conn));
1291 case PERM_EXISTING_DIR:
1292 /* Apply mode mask */
1293 ret &= lp_dir_security_mask(SNUM(conn));
1294 /* Add in force bits */
1295 ret |= lp_force_dir_security_mode(SNUM(conn));
1300 return NT_STATUS_OK;
1303 /****************************************************************************
1304 Needed to show the msdfs symlinks as directories. Modifies psbuf
1305 to be a directory if it's a msdfs link.
1306 ****************************************************************************/
1308 static bool check_msdfs_link(connection_struct *conn,
1309 const char *pathname,
1310 SMB_STRUCT_STAT *psbuf)
1312 int saved_errno = errno;
1313 if(lp_host_msdfs() &&
1314 lp_msdfs_root(SNUM(conn)) &&
1315 is_msdfs_link(conn, pathname, psbuf)) {
1317 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1320 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1321 errno = saved_errno;
1324 errno = saved_errno;
1329 /****************************************************************************
1330 Get a level dependent lanman2 dir entry.
1331 ****************************************************************************/
1333 struct smbd_dirptr_lanman2_state {
1334 connection_struct *conn;
1335 uint32_t info_level;
1336 bool check_mangled_names;
1338 bool got_exact_match;
1341 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1347 struct smbd_dirptr_lanman2_state *state =
1348 (struct smbd_dirptr_lanman2_state *)private_data;
1350 char mangled_name[13]; /* mangled 8.3 name. */
1354 /* Mangle fname if it's an illegal name. */
1355 if (mangle_must_mangle(dname, state->conn->params)) {
1356 ok = name_to_8_3(dname, mangled_name,
1357 true, state->conn->params);
1361 fname = mangled_name;
1366 got_match = exact_match(state->has_wild,
1367 state->conn->case_sensitive,
1369 state->got_exact_match = got_match;
1371 got_match = mask_match(fname, mask, get_Protocol(),
1372 state->conn->case_sensitive);
1375 if(!got_match && state->check_mangled_names &&
1376 !mangle_is_8_3(fname, false, state->conn->params)) {
1378 * It turns out that NT matches wildcards against
1379 * both long *and* short names. This may explain some
1380 * of the wildcard wierdness from old DOS clients
1381 * that some people have been seeing.... JRA.
1383 /* Force the mangling into 8.3. */
1384 ok = name_to_8_3(fname, mangled_name,
1385 false, state->conn->params);
1390 got_match = exact_match(state->has_wild,
1391 state->conn->case_sensitive,
1392 mangled_name, mask);
1393 state->got_exact_match = got_match;
1395 got_match = mask_match(mangled_name, mask,
1397 state->conn->case_sensitive);
1405 *_fname = talloc_strdup(ctx, fname);
1406 if (*_fname == NULL) {
1413 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1415 struct smb_filename *smb_fname,
1418 struct smbd_dirptr_lanman2_state *state =
1419 (struct smbd_dirptr_lanman2_state *)private_data;
1420 bool ms_dfs_link = false;
1423 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1424 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1425 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1426 "Couldn't lstat [%s] (%s)\n",
1427 smb_fname_str_dbg(smb_fname),
1431 } else if (!VALID_STAT(smb_fname->st) &&
1432 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1433 /* Needed to show the msdfs symlinks as
1436 ms_dfs_link = check_msdfs_link(state->conn,
1437 smb_fname->base_name,
1440 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1441 "Couldn't stat [%s] (%s)\n",
1442 smb_fname_str_dbg(smb_fname),
1449 mode = dos_mode_msdfs(state->conn, smb_fname);
1451 mode = dos_mode(state->conn, smb_fname);
1458 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1459 connection_struct *conn,
1461 uint32_t info_level,
1462 struct ea_list *name_list,
1463 bool check_mangled_names,
1464 bool requires_resume_key,
1467 const struct smb_filename *smb_fname,
1468 uint64_t space_remaining,
1475 uint64_t *last_entry_off)
1477 char *p, *q, *pdata = *ppdata;
1479 uint64_t file_size = 0;
1480 uint64_t allocation_size = 0;
1482 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1483 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1484 time_t c_date = (time_t)0;
1486 char *last_entry_ptr;
1488 uint32_t nt_extmode; /* Used for NT connections instead of mode */
1492 *out_of_space = false;
1494 ZERO_STRUCT(mdate_ts);
1495 ZERO_STRUCT(adate_ts);
1496 ZERO_STRUCT(create_date_ts);
1497 ZERO_STRUCT(cdate_ts);
1499 if (!(mode & aDIR)) {
1500 file_size = get_file_size_stat(&smb_fname->st);
1502 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1504 mdate_ts = smb_fname->st.st_ex_mtime;
1505 adate_ts = smb_fname->st.st_ex_atime;
1506 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1507 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1509 if (lp_dos_filetime_resolution(SNUM(conn))) {
1510 dos_filetime_timespec(&create_date_ts);
1511 dos_filetime_timespec(&mdate_ts);
1512 dos_filetime_timespec(&adate_ts);
1513 dos_filetime_timespec(&cdate_ts);
1516 create_date = convert_timespec_to_time_t(create_date_ts);
1517 mdate = convert_timespec_to_time_t(mdate_ts);
1518 adate = convert_timespec_to_time_t(adate_ts);
1519 c_date = convert_timespec_to_time_t(cdate_ts);
1521 /* align the record */
1522 off = PTR_DIFF(pdata, base_data);
1523 pad = (off + (align-1)) & ~(align-1);
1526 /* initialize padding to 0 */
1528 memset(pdata, 0, pad);
1530 space_remaining -= pad;
1539 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1541 switch (info_level) {
1542 case SMB_FIND_INFO_STANDARD:
1543 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1544 if(requires_resume_key) {
1548 srv_put_dos_date2(p,0,create_date);
1549 srv_put_dos_date2(p,4,adate);
1550 srv_put_dos_date2(p,8,mdate);
1551 SIVAL(p,12,(uint32)file_size);
1552 SIVAL(p,16,(uint32)allocation_size);
1556 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1557 p += ucs2_align(base_data, p, 0);
1559 len = srvstr_push(base_data, flags2, p,
1560 fname, PTR_DIFF(end_data, p),
1562 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1564 SCVAL(nameptr, -1, len - 2);
1566 SCVAL(nameptr, -1, 0);
1570 SCVAL(nameptr, -1, len - 1);
1572 SCVAL(nameptr, -1, 0);
1578 case SMB_FIND_EA_SIZE:
1579 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1580 if (requires_resume_key) {
1584 srv_put_dos_date2(p,0,create_date);
1585 srv_put_dos_date2(p,4,adate);
1586 srv_put_dos_date2(p,8,mdate);
1587 SIVAL(p,12,(uint32)file_size);
1588 SIVAL(p,16,(uint32)allocation_size);
1591 unsigned int ea_size = estimate_ea_size(conn, NULL,
1592 smb_fname->base_name);
1593 SIVAL(p,22,ea_size); /* Extended attributes */
1597 len = srvstr_push(base_data, flags2,
1598 p, fname, PTR_DIFF(end_data, p),
1599 STR_TERMINATE | STR_NOALIGN);
1600 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1613 SCVAL(nameptr,0,len);
1615 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1618 case SMB_FIND_EA_LIST:
1620 struct ea_list *file_list = NULL;
1623 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1627 if (requires_resume_key) {
1631 srv_put_dos_date2(p,0,create_date);
1632 srv_put_dos_date2(p,4,adate);
1633 srv_put_dos_date2(p,8,mdate);
1634 SIVAL(p,12,(uint32)file_size);
1635 SIVAL(p,16,(uint32)allocation_size);
1637 p += 22; /* p now points to the EA area. */
1639 file_list = get_ea_list_from_file(ctx, conn, NULL,
1640 smb_fname->base_name,
1642 name_list = ea_list_union(name_list, file_list, &ea_len);
1644 /* We need to determine if this entry will fit in the space available. */
1645 /* Max string size is 255 bytes. */
1646 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1647 *out_of_space = true;
1648 DEBUG(9,("smbd_marshall_dir_entry: out of space\n"));
1649 return False; /* Not finished - just out of space */
1652 /* Push the ea_data followed by the name. */
1653 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1655 len = srvstr_push(base_data, flags2,
1656 p + 1, fname, PTR_DIFF(end_data, p+1),
1657 STR_TERMINATE | STR_NOALIGN);
1658 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1671 SCVAL(nameptr,0,len);
1673 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1677 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1678 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1679 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1681 SIVAL(p,0,reskey); p += 4;
1682 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1683 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1684 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1685 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1686 SOFF_T(p,0,file_size); p += 8;
1687 SOFF_T(p,0,allocation_size); p += 8;
1688 SIVAL(p,0,nt_extmode); p += 4;
1689 q = p; p += 4; /* q is placeholder for name length. */
1691 unsigned int ea_size = estimate_ea_size(conn, NULL,
1692 smb_fname->base_name);
1693 SIVAL(p,0,ea_size); /* Extended attributes */
1696 /* Clear the short name buffer. This is
1697 * IMPORTANT as not doing so will trigger
1698 * a Win2k client bug. JRA.
1700 if (!was_8_3 && check_mangled_names) {
1701 char mangled_name[13]; /* mangled 8.3 name. */
1702 if (!name_to_8_3(fname,mangled_name,True,
1704 /* Error - mangle failed ! */
1705 memset(mangled_name,'\0',12);
1707 mangled_name[12] = 0;
1708 len = srvstr_push(base_data, flags2,
1709 p+2, mangled_name, 24,
1710 STR_UPPER|STR_UNICODE);
1712 memset(p + 2 + len,'\0',24 - len);
1719 len = srvstr_push(base_data, flags2, p,
1720 fname, PTR_DIFF(end_data, p),
1721 STR_TERMINATE_ASCII);
1725 len = PTR_DIFF(p, pdata);
1726 pad = (len + (align-1)) & ~(align-1);
1728 * offset to the next entry, the caller
1729 * will overwrite it for the last entry
1730 * that's why we always include the padding
1734 * set padding to zero
1737 memset(p, 0, pad - len);
1744 case SMB_FIND_FILE_DIRECTORY_INFO:
1745 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1747 SIVAL(p,0,reskey); p += 4;
1748 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1749 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1750 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1751 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1752 SOFF_T(p,0,file_size); p += 8;
1753 SOFF_T(p,0,allocation_size); p += 8;
1754 SIVAL(p,0,nt_extmode); p += 4;
1755 len = srvstr_push(base_data, flags2,
1756 p + 4, fname, PTR_DIFF(end_data, p+4),
1757 STR_TERMINATE_ASCII);
1761 len = PTR_DIFF(p, pdata);
1762 pad = (len + (align-1)) & ~(align-1);
1764 * offset to the next entry, the caller
1765 * will overwrite it for the last entry
1766 * that's why we always include the padding
1770 * set padding to zero
1773 memset(p, 0, pad - len);
1780 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1781 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1783 SIVAL(p,0,reskey); p += 4;
1784 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1785 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1786 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1787 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1788 SOFF_T(p,0,file_size); p += 8;
1789 SOFF_T(p,0,allocation_size); p += 8;
1790 SIVAL(p,0,nt_extmode); p += 4;
1791 q = p; p += 4; /* q is placeholder for name length. */
1793 unsigned int ea_size = estimate_ea_size(conn, NULL,
1794 smb_fname->base_name);
1795 SIVAL(p,0,ea_size); /* Extended attributes */
1798 len = srvstr_push(base_data, flags2, p,
1799 fname, PTR_DIFF(end_data, p),
1800 STR_TERMINATE_ASCII);
1804 len = PTR_DIFF(p, pdata);
1805 pad = (len + (align-1)) & ~(align-1);
1807 * offset to the next entry, the caller
1808 * will overwrite it for the last entry
1809 * that's why we always include the padding
1813 * set padding to zero
1816 memset(p, 0, pad - len);
1823 case SMB_FIND_FILE_NAMES_INFO:
1824 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1826 SIVAL(p,0,reskey); p += 4;
1828 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1829 acl on a dir (tridge) */
1830 len = srvstr_push(base_data, flags2, p,
1831 fname, PTR_DIFF(end_data, p),
1832 STR_TERMINATE_ASCII);
1836 len = PTR_DIFF(p, pdata);
1837 pad = (len + (align-1)) & ~(align-1);
1839 * offset to the next entry, the caller
1840 * will overwrite it for the last entry
1841 * that's why we always include the padding
1845 * set padding to zero
1848 memset(p, 0, pad - len);
1855 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1856 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1858 SIVAL(p,0,reskey); p += 4;
1859 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1860 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1861 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1862 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1863 SOFF_T(p,0,file_size); p += 8;
1864 SOFF_T(p,0,allocation_size); p += 8;
1865 SIVAL(p,0,nt_extmode); p += 4;
1866 q = p; p += 4; /* q is placeholder for name length. */
1868 unsigned int ea_size = estimate_ea_size(conn, NULL,
1869 smb_fname->base_name);
1870 SIVAL(p,0,ea_size); /* Extended attributes */
1873 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1874 SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
1875 SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
1876 len = srvstr_push(base_data, flags2, p,
1877 fname, PTR_DIFF(end_data, p),
1878 STR_TERMINATE_ASCII);
1882 len = PTR_DIFF(p, pdata);
1883 pad = (len + (align-1)) & ~(align-1);
1885 * offset to the next entry, the caller
1886 * will overwrite it for the last entry
1887 * that's why we always include the padding
1891 * set padding to zero
1894 memset(p, 0, pad - len);
1901 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1902 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1903 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1905 SIVAL(p,0,reskey); p += 4;
1906 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1907 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1908 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1909 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1910 SOFF_T(p,0,file_size); p += 8;
1911 SOFF_T(p,0,allocation_size); p += 8;
1912 SIVAL(p,0,nt_extmode); p += 4;
1913 q = p; p += 4; /* q is placeholder for name length */
1915 unsigned int ea_size = estimate_ea_size(conn, NULL,
1916 smb_fname->base_name);
1917 SIVAL(p,0,ea_size); /* Extended attributes */
1920 /* Clear the short name buffer. This is
1921 * IMPORTANT as not doing so will trigger
1922 * a Win2k client bug. JRA.
1924 if (!was_8_3 && check_mangled_names) {
1925 char mangled_name[13]; /* mangled 8.3 name. */
1926 if (!name_to_8_3(fname,mangled_name,True,
1928 /* Error - mangle failed ! */
1929 memset(mangled_name,'\0',12);
1931 mangled_name[12] = 0;
1932 len = srvstr_push(base_data, flags2,
1933 p+2, mangled_name, 24,
1934 STR_UPPER|STR_UNICODE);
1937 memset(p + 2 + len,'\0',24 - len);
1944 SSVAL(p,0,0); p += 2; /* Reserved ? */
1945 SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
1946 SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
1947 len = srvstr_push(base_data, flags2, p,
1948 fname, PTR_DIFF(end_data, p),
1949 STR_TERMINATE_ASCII);
1953 len = PTR_DIFF(p, pdata);
1954 pad = (len + (align-1)) & ~(align-1);
1956 * offset to the next entry, the caller
1957 * will overwrite it for the last entry
1958 * that's why we always include the padding
1962 * set padding to zero
1965 memset(p, 0, pad - len);
1972 /* CIFS UNIX Extension. */
1974 case SMB_FIND_FILE_UNIX:
1975 case SMB_FIND_FILE_UNIX_INFO2:
1977 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1979 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1981 if (info_level == SMB_FIND_FILE_UNIX) {
1982 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
1983 p = store_file_unix_basic(conn, p,
1984 NULL, &smb_fname->st);
1985 len = srvstr_push(base_data, flags2, p,
1986 fname, PTR_DIFF(end_data, p),
1989 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1990 p = store_file_unix_basic_info2(conn, p,
1991 NULL, &smb_fname->st);
1994 len = srvstr_push(base_data, flags2, p, fname,
1995 PTR_DIFF(end_data, p), 0);
1996 SIVAL(nameptr, 0, len);
2001 len = PTR_DIFF(p, pdata);
2002 pad = (len + (align-1)) & ~(align-1);
2004 * offset to the next entry, the caller
2005 * will overwrite it for the last entry
2006 * that's why we always include the padding
2010 * set padding to zero
2013 memset(p, 0, pad - len);
2018 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2026 if (PTR_DIFF(p,pdata) > space_remaining) {
2027 *out_of_space = true;
2028 DEBUG(9,("smbd_marshall_dir_entry: out of space\n"));
2029 return false; /* Not finished - just out of space */
2032 /* Setup the last entry pointer, as an offset from base_data */
2033 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2034 /* Advance the data pointer to the next slot */
2040 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2041 connection_struct *conn,
2042 struct dptr_struct *dirptr,
2044 const char *path_mask,
2047 int requires_resume_key,
2055 int space_remaining,
2057 bool *got_exact_match,
2058 int *_last_entry_off,
2059 struct ea_list *name_list)
2062 const char *mask = NULL;
2063 long prev_dirpos = 0;
2066 struct smb_filename *smb_fname = NULL;
2067 struct smbd_dirptr_lanman2_state state;
2069 uint64_t last_entry_off = 0;
2073 state.info_level = info_level;
2074 state.check_mangled_names = lp_manglednames(conn->params);
2075 state.has_wild = dptr_has_wild(dirptr);
2076 state.got_exact_match = false;
2078 *out_of_space = false;
2079 *got_exact_match = false;
2081 p = strrchr_m(path_mask,'/');
2092 ok = smbd_dirptr_get_entry(ctx,
2098 smbd_dirptr_lanman2_match_fn,
2099 smbd_dirptr_lanman2_mode_fn,
2109 *got_exact_match = state.got_exact_match;
2111 ok = smbd_marshall_dir_entry(ctx,
2116 state.check_mangled_names,
2117 requires_resume_key,
2130 TALLOC_FREE(smb_fname);
2131 if (*out_of_space) {
2132 dptr_SeekDir(dirptr, prev_dirpos);
2139 *_last_entry_off = last_entry_off;
2143 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2144 connection_struct *conn,
2145 struct dptr_struct *dirptr,
2147 const char *path_mask,
2150 bool requires_resume_key,
2156 int space_remaining,
2158 bool *got_exact_match,
2159 int *last_entry_off,
2160 struct ea_list *name_list)
2163 const bool do_pad = true;
2165 if (info_level >= 1 && info_level <= 3) {
2166 /* No alignment on earlier info levels. */
2170 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2171 path_mask, dirtype, info_level,
2172 requires_resume_key, dont_descend, ask_sharemode,
2174 ppdata, base_data, end_data,
2176 out_of_space, got_exact_match,
2177 last_entry_off, name_list);
2180 /****************************************************************************
2181 Reply to a TRANS2_FINDFIRST.
2182 ****************************************************************************/
2184 static void call_trans2findfirst(connection_struct *conn,
2185 struct smb_request *req,
2186 char **pparams, int total_params,
2187 char **ppdata, int total_data,
2188 unsigned int max_data_bytes)
2190 /* We must be careful here that we don't return more than the
2191 allowed number of data bytes. If this means returning fewer than
2192 maxentries then so be it. We assume that the redirector has
2193 enough room for the fixed number of parameter bytes it has
2195 struct smb_filename *smb_dname = NULL;
2196 char *params = *pparams;
2197 char *pdata = *ppdata;
2201 uint16 findfirst_flags;
2202 bool close_after_first;
2204 bool requires_resume_key;
2206 char *directory = NULL;
2209 int last_entry_off=0;
2213 bool finished = False;
2214 bool dont_descend = False;
2215 bool out_of_space = False;
2216 int space_remaining;
2217 bool mask_contains_wcard = False;
2218 struct ea_list *ea_list = NULL;
2219 NTSTATUS ntstatus = NT_STATUS_OK;
2220 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2221 TALLOC_CTX *ctx = talloc_tos();
2222 struct dptr_struct *dirptr = NULL;
2223 struct smbd_server_connection *sconn = smbd_server_conn;
2225 if (total_params < 13) {
2226 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2230 dirtype = SVAL(params,0);
2231 maxentries = SVAL(params,2);
2232 findfirst_flags = SVAL(params,4);
2233 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2234 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2235 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2236 info_level = SVAL(params,6);
2238 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2239 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2240 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2241 info_level, max_data_bytes));
2244 /* W2K3 seems to treat zero as 1. */
2248 switch (info_level) {
2249 case SMB_FIND_INFO_STANDARD:
2250 case SMB_FIND_EA_SIZE:
2251 case SMB_FIND_EA_LIST:
2252 case SMB_FIND_FILE_DIRECTORY_INFO:
2253 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2254 case SMB_FIND_FILE_NAMES_INFO:
2255 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2256 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2257 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2259 case SMB_FIND_FILE_UNIX:
2260 case SMB_FIND_FILE_UNIX_INFO2:
2261 /* Always use filesystem for UNIX mtime query. */
2262 ask_sharemode = false;
2263 if (!lp_unix_extensions()) {
2264 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2269 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2273 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2274 params+12, total_params - 12,
2275 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2276 if (!NT_STATUS_IS_OK(ntstatus)) {
2277 reply_nterror(req, ntstatus);
2281 ntstatus = filename_convert(ctx, conn,
2282 req->flags2 & FLAGS2_DFS_PATHNAMES,
2285 UCF_ALWAYS_ALLOW_WCARD_LCOMP),
2286 &mask_contains_wcard,
2288 if (!NT_STATUS_IS_OK(ntstatus)) {
2289 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2290 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2291 ERRSRV, ERRbadpath);
2294 reply_nterror(req, ntstatus);
2298 mask = smb_dname->original_lcomp;
2300 directory = smb_dname->base_name;
2302 p = strrchr_m(directory,'/');
2304 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2305 if((directory[0] == '.') && (directory[1] == '\0')) {
2306 mask = talloc_strdup(ctx,"*");
2308 reply_nterror(req, NT_STATUS_NO_MEMORY);
2311 mask_contains_wcard = True;
2313 directory = talloc_strdup(talloc_tos(), "./");
2315 reply_nterror(req, NT_STATUS_NO_MEMORY);
2322 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2324 if (info_level == SMB_FIND_EA_LIST) {
2327 if (total_data < 4) {
2328 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2332 ea_size = IVAL(pdata,0);
2333 if (ea_size != total_data) {
2334 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2335 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2336 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2340 if (!lp_ea_support(SNUM(conn))) {
2341 reply_doserror(req, ERRDOS, ERReasnotsupported);
2345 /* Pull out the list of names. */
2346 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2348 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2353 *ppdata = (char *)SMB_REALLOC(
2354 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2355 if(*ppdata == NULL ) {
2356 reply_nterror(req, NT_STATUS_NO_MEMORY);
2360 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2362 /* Realloc the params space */
2363 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2364 if (*pparams == NULL) {
2365 reply_nterror(req, NT_STATUS_NO_MEMORY);
2370 /* Save the wildcard match and attribs we are using on this directory -
2371 needed as lanman2 assumes these are being saved between calls */
2373 ntstatus = dptr_create(conn,
2379 mask_contains_wcard,
2383 if (!NT_STATUS_IS_OK(ntstatus)) {
2384 reply_nterror(req, ntstatus);
2388 dptr_num = dptr_dnum(dirptr);
2389 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2391 /* Initialize per TRANS2_FIND_FIRST operation data */
2392 dptr_init_search_op(dirptr);
2394 /* We don't need to check for VOL here as this is returned by
2395 a different TRANS2 call. */
2397 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2398 directory,lp_dontdescend(SNUM(conn))));
2399 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2400 dont_descend = True;
2403 space_remaining = max_data_bytes;
2404 out_of_space = False;
2406 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2407 bool got_exact_match = False;
2409 /* this is a heuristic to avoid seeking the dirptr except when
2410 absolutely necessary. It allows for a filename of about 40 chars */
2411 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2412 out_of_space = True;
2415 finished = !get_lanman2_dir_entry(ctx,
2419 mask,dirtype,info_level,
2420 requires_resume_key,dont_descend,
2423 space_remaining, &out_of_space,
2425 &last_entry_off, ea_list);
2428 if (finished && out_of_space)
2431 if (!finished && !out_of_space)
2435 * As an optimisation if we know we aren't looking
2436 * for a wildcard name (ie. the name matches the wildcard exactly)
2437 * then we can finish on any (first) match.
2438 * This speeds up large directory searches. JRA.
2444 /* Ensure space_remaining never goes -ve. */
2445 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2446 space_remaining = 0;
2447 out_of_space = true;
2449 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2453 /* Check if we can close the dirptr */
2454 if(close_after_first || (finished && close_if_end)) {
2455 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2456 dptr_close(sconn, &dptr_num);
2460 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2461 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2462 * the protocol level is less than NT1. Tested with smbclient. JRA.
2463 * This should fix the OS/2 client bug #2335.
2466 if(numentries == 0) {
2467 dptr_close(sconn, &dptr_num);
2468 if (get_Protocol() < PROTOCOL_NT1) {
2469 reply_doserror(req, ERRDOS, ERRnofiles);
2472 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2473 ERRDOS, ERRbadfile);
2478 /* At this point pdata points to numentries directory entries. */
2480 /* Set up the return parameter block */
2481 SSVAL(params,0,dptr_num);
2482 SSVAL(params,2,numentries);
2483 SSVAL(params,4,finished);
2484 SSVAL(params,6,0); /* Never an EA error */
2485 SSVAL(params,8,last_entry_off);
2487 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2490 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2491 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2493 reply_nterror(req, NT_STATUS_NO_MEMORY);
2497 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2498 smb_fn_name(req->cmd),
2499 mask, directory, dirtype, numentries ) );
2502 * Force a name mangle here to ensure that the
2503 * mask as an 8.3 name is top of the mangled cache.
2504 * The reasons for this are subtle. Don't remove
2505 * this code unless you know what you are doing
2506 * (see PR#13758). JRA.
2509 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2510 char mangled_name[13];
2511 name_to_8_3(mask, mangled_name, True, conn->params);
2514 TALLOC_FREE(smb_dname);
2518 /****************************************************************************
2519 Reply to a TRANS2_FINDNEXT.
2520 ****************************************************************************/
2522 static void call_trans2findnext(connection_struct *conn,
2523 struct smb_request *req,
2524 char **pparams, int total_params,
2525 char **ppdata, int total_data,
2526 unsigned int max_data_bytes)
2528 /* We must be careful here that we don't return more than the
2529 allowed number of data bytes. If this means returning fewer than
2530 maxentries then so be it. We assume that the redirector has
2531 enough room for the fixed number of parameter bytes it has
2533 char *params = *pparams;
2534 char *pdata = *ppdata;
2540 uint16 findnext_flags;
2541 bool close_after_request;
2543 bool requires_resume_key;
2545 bool mask_contains_wcard = False;
2546 char *resume_name = NULL;
2547 const char *mask = NULL;
2548 const char *directory = NULL;
2552 int i, last_entry_off=0;
2553 bool finished = False;
2554 bool dont_descend = False;
2555 bool out_of_space = False;
2556 int space_remaining;
2557 struct ea_list *ea_list = NULL;
2558 NTSTATUS ntstatus = NT_STATUS_OK;
2559 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2560 TALLOC_CTX *ctx = talloc_tos();
2561 struct dptr_struct *dirptr;
2562 struct smbd_server_connection *sconn = smbd_server_conn;
2564 if (total_params < 13) {
2565 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2569 dptr_num = SVAL(params,0);
2570 maxentries = SVAL(params,2);
2571 info_level = SVAL(params,4);
2572 resume_key = IVAL(params,6);
2573 findnext_flags = SVAL(params,10);
2574 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2575 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2576 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2577 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2579 if (!continue_bit) {
2580 /* We only need resume_name if continue_bit is zero. */
2581 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2583 total_params - 12, STR_TERMINATE, &ntstatus,
2584 &mask_contains_wcard);
2585 if (!NT_STATUS_IS_OK(ntstatus)) {
2586 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2587 complain (it thinks we're asking for the directory above the shared
2588 path or an invalid name). Catch this as the resume name is only compared, never used in
2589 a file access. JRA. */
2590 srvstr_pull_talloc(ctx, params, req->flags2,
2591 &resume_name, params+12,
2595 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2596 reply_nterror(req, ntstatus);
2602 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2603 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2604 resume_key = %d resume name = %s continue=%d level = %d\n",
2605 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2606 requires_resume_key, resume_key,
2607 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2610 /* W2K3 seems to treat zero as 1. */
2614 switch (info_level) {
2615 case SMB_FIND_INFO_STANDARD:
2616 case SMB_FIND_EA_SIZE:
2617 case SMB_FIND_EA_LIST:
2618 case SMB_FIND_FILE_DIRECTORY_INFO:
2619 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2620 case SMB_FIND_FILE_NAMES_INFO:
2621 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2622 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2623 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2625 case SMB_FIND_FILE_UNIX:
2626 case SMB_FIND_FILE_UNIX_INFO2:
2627 /* Always use filesystem for UNIX mtime query. */
2628 ask_sharemode = false;
2629 if (!lp_unix_extensions()) {
2630 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2635 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2639 if (info_level == SMB_FIND_EA_LIST) {
2642 if (total_data < 4) {
2643 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2647 ea_size = IVAL(pdata,0);
2648 if (ea_size != total_data) {
2649 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2650 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2651 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2655 if (!lp_ea_support(SNUM(conn))) {
2656 reply_doserror(req, ERRDOS, ERReasnotsupported);
2660 /* Pull out the list of names. */
2661 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2663 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2668 *ppdata = (char *)SMB_REALLOC(
2669 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2670 if(*ppdata == NULL) {
2671 reply_nterror(req, NT_STATUS_NO_MEMORY);
2676 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2678 /* Realloc the params space */
2679 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2680 if(*pparams == NULL ) {
2681 reply_nterror(req, NT_STATUS_NO_MEMORY);
2687 /* Check that the dptr is valid */
2688 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2689 reply_doserror(req, ERRDOS, ERRnofiles);
2693 directory = dptr_path(sconn, dptr_num);
2695 /* Get the wildcard mask from the dptr */
2696 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2697 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2698 reply_doserror(req, ERRDOS, ERRnofiles);
2704 /* Get the attr mask from the dptr */
2705 dirtype = dptr_attr(sconn, dptr_num);
2707 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2708 dptr_num, mask, dirtype,
2710 dptr_TellDir(dirptr)));
2712 /* Initialize per TRANS2_FIND_NEXT operation data */
2713 dptr_init_search_op(dirptr);
2715 /* We don't need to check for VOL here as this is returned by
2716 a different TRANS2 call. */
2718 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2719 directory,lp_dontdescend(SNUM(conn))));
2720 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2721 dont_descend = True;
2724 space_remaining = max_data_bytes;
2725 out_of_space = False;
2728 * Seek to the correct position. We no longer use the resume key but
2729 * depend on the last file name instead.
2732 if(!continue_bit && resume_name && *resume_name) {
2735 long current_pos = 0;
2737 * Remember, name_to_8_3 is called by
2738 * get_lanman2_dir_entry(), so the resume name
2739 * could be mangled. Ensure we check the unmangled name.
2742 if (mangle_is_mangled(resume_name, conn->params)) {
2743 char *new_resume_name = NULL;
2744 mangle_lookup_name_from_8_3(ctx,
2748 if (new_resume_name) {
2749 resume_name = new_resume_name;
2754 * Fix for NT redirector problem triggered by resume key indexes
2755 * changing between directory scans. We now return a resume key of 0
2756 * and instead look for the filename to continue from (also given
2757 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2758 * findfirst/findnext (as is usual) then the directory pointer
2759 * should already be at the correct place.
2762 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
2763 } /* end if resume_name && !continue_bit */
2765 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2766 bool got_exact_match = False;
2768 /* this is a heuristic to avoid seeking the dirptr except when
2769 absolutely necessary. It allows for a filename of about 40 chars */
2770 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2771 out_of_space = True;
2774 finished = !get_lanman2_dir_entry(ctx,
2778 mask,dirtype,info_level,
2779 requires_resume_key,dont_descend,
2782 space_remaining, &out_of_space,
2784 &last_entry_off, ea_list);
2787 if (finished && out_of_space)
2790 if (!finished && !out_of_space)
2794 * As an optimisation if we know we aren't looking
2795 * for a wildcard name (ie. the name matches the wildcard exactly)
2796 * then we can finish on any (first) match.
2797 * This speeds up large directory searches. JRA.
2803 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2806 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2807 smb_fn_name(req->cmd),
2808 mask, directory, dirtype, numentries ) );
2810 /* Check if we can close the dirptr */
2811 if(close_after_request || (finished && close_if_end)) {
2812 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2813 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2816 /* Set up the return parameter block */
2817 SSVAL(params,0,numentries);
2818 SSVAL(params,2,finished);
2819 SSVAL(params,4,0); /* Never an EA error */
2820 SSVAL(params,6,last_entry_off);
2822 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2828 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2830 E_md4hash(lp_servicename(SNUM(conn)),objid);
2834 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2836 SMB_ASSERT(extended_info != NULL);
2838 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2839 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2840 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2841 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2842 #ifdef SAMBA_VERSION_REVISION
2843 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2845 extended_info->samba_subversion = 0;
2846 #ifdef SAMBA_VERSION_RC_RELEASE
2847 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2849 #ifdef SAMBA_VERSION_PRE_RELEASE
2850 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2853 #ifdef SAMBA_VERSION_VENDOR_PATCH
2854 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2856 extended_info->samba_gitcommitdate = 0;
2857 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2858 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2861 memset(extended_info->samba_version_string, 0,
2862 sizeof(extended_info->samba_version_string));
2864 snprintf (extended_info->samba_version_string,
2865 sizeof(extended_info->samba_version_string),
2866 "%s", samba_version_string());
2869 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2870 TALLOC_CTX *mem_ctx,
2871 uint16_t info_level,
2873 unsigned int max_data_bytes,
2877 char *pdata, *end_data;
2878 int data_len = 0, len;
2879 const char *vname = volume_label(SNUM(conn));
2880 int snum = SNUM(conn);
2881 char *fstype = lp_fstype(SNUM(conn));
2882 uint32 additional_flags = 0;
2883 struct smb_filename smb_fname_dot;
2887 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2888 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2889 "info level (0x%x) on IPC$.\n",
2890 (unsigned int)info_level));
2891 return NT_STATUS_ACCESS_DENIED;
2895 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2897 ZERO_STRUCT(smb_fname_dot);
2898 smb_fname_dot.base_name = discard_const_p(char, ".");
2900 if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
2901 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2902 return map_nt_error_from_unix(errno);
2905 st = smb_fname_dot.st;
2907 *ppdata = (char *)SMB_REALLOC(
2908 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2909 if (*ppdata == NULL) {
2910 return NT_STATUS_NO_MEMORY;
2914 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2915 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2917 switch (info_level) {
2918 case SMB_INFO_ALLOCATION:
2920 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2922 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2923 return map_nt_error_from_unix(errno);
2926 block_size = lp_block_size(snum);
2927 if (bsize < block_size) {
2928 uint64_t factor = block_size/bsize;
2933 if (bsize > block_size) {
2934 uint64_t factor = bsize/block_size;
2939 bytes_per_sector = 512;
2940 sectors_per_unit = bsize/bytes_per_sector;
2942 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2943 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2944 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2946 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2947 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2948 SIVAL(pdata,l1_cUnit,dsize);
2949 SIVAL(pdata,l1_cUnitAvail,dfree);
2950 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2954 case SMB_INFO_VOLUME:
2955 /* Return volume name */
2957 * Add volume serial number - hash of a combination of
2958 * the called hostname and the service name.
2960 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2962 * Win2k3 and previous mess this up by sending a name length
2963 * one byte short. I believe only older clients (OS/2 Win9x) use
2964 * this call so try fixing this by adding a terminating null to
2965 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2969 pdata+l2_vol_szVolLabel, vname,
2970 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2971 STR_NOALIGN|STR_TERMINATE);
2972 SCVAL(pdata,l2_vol_cch,len);
2973 data_len = l2_vol_szVolLabel + len;
2974 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
2975 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2979 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2980 case SMB_FS_ATTRIBUTE_INFORMATION:
2982 additional_flags = 0;
2983 #if defined(HAVE_SYS_QUOTAS)
2984 additional_flags |= FILE_VOLUME_QUOTAS;
2987 if(lp_nt_acl_support(SNUM(conn))) {
2988 additional_flags |= FILE_PERSISTENT_ACLS;
2991 /* Capabilities are filled in at connection time through STATVFS call */
2992 additional_flags |= conn->fs_capabilities;
2993 additional_flags |= lp_parm_int(conn->params->service,
2994 "share", "fake_fscaps",
2997 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2998 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2999 additional_flags); /* FS ATTRIBUTES */
3001 SIVAL(pdata,4,255); /* Max filename component length */
3002 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3003 and will think we can't do long filenames */
3004 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3005 PTR_DIFF(end_data, pdata+12),
3008 data_len = 12 + len;
3011 case SMB_QUERY_FS_LABEL_INFO:
3012 case SMB_FS_LABEL_INFORMATION:
3013 len = srvstr_push(pdata, flags2, pdata+4, vname,
3014 PTR_DIFF(end_data, pdata+4), 0);
3019 case SMB_QUERY_FS_VOLUME_INFO:
3020 case SMB_FS_VOLUME_INFORMATION:
3023 * Add volume serial number - hash of a combination of
3024 * the called hostname and the service name.
3026 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3027 (str_checksum(get_local_machine_name())<<16));
3029 /* Max label len is 32 characters. */
3030 len = srvstr_push(pdata, flags2, pdata+18, vname,
3031 PTR_DIFF(end_data, pdata+18),
3033 SIVAL(pdata,12,len);
3036 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3037 (int)strlen(vname),vname, lp_servicename(snum)));
3040 case SMB_QUERY_FS_SIZE_INFO:
3041 case SMB_FS_SIZE_INFORMATION:
3043 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3045 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3046 return map_nt_error_from_unix(errno);
3048 block_size = lp_block_size(snum);
3049 if (bsize < block_size) {
3050 uint64_t factor = block_size/bsize;
3055 if (bsize > block_size) {
3056 uint64_t factor = bsize/block_size;
3061 bytes_per_sector = 512;
3062 sectors_per_unit = bsize/bytes_per_sector;
3063 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3064 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3065 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3066 SBIG_UINT(pdata,0,dsize);
3067 SBIG_UINT(pdata,8,dfree);
3068 SIVAL(pdata,16,sectors_per_unit);
3069 SIVAL(pdata,20,bytes_per_sector);
3073 case SMB_FS_FULL_SIZE_INFORMATION:
3075 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3077 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3078 return map_nt_error_from_unix(errno);
3080 block_size = lp_block_size(snum);
3081 if (bsize < block_size) {
3082 uint64_t factor = block_size/bsize;
3087 if (bsize > block_size) {
3088 uint64_t factor = bsize/block_size;
3093 bytes_per_sector = 512;
3094 sectors_per_unit = bsize/bytes_per_sector;
3095 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3096 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3097 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3098 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3099 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3100 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3101 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3102 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3106 case SMB_QUERY_FS_DEVICE_INFO:
3107 case SMB_FS_DEVICE_INFORMATION:
3109 SIVAL(pdata,0,0); /* dev type */
3110 SIVAL(pdata,4,0); /* characteristics */
3113 #ifdef HAVE_SYS_QUOTAS
3114 case SMB_FS_QUOTA_INFORMATION:
3116 * what we have to send --metze:
3118 * Unknown1: 24 NULL bytes
3119 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3120 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3121 * Quota Flags: 2 byte :
3122 * Unknown3: 6 NULL bytes
3126 * details for Quota Flags:
3128 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3129 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3130 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3131 * 0x0001 Enable Quotas: enable quota for this fs
3135 /* we need to fake up a fsp here,
3136 * because its not send in this call
3139 SMB_NTQUOTA_STRUCT quotas;
3142 ZERO_STRUCT(quotas);
3148 if (conn->server_info->utok.uid != sec_initial_uid()) {
3149 DEBUG(0,("set_user_quota: access_denied "
3150 "service [%s] user [%s]\n",
3151 lp_servicename(SNUM(conn)),
3152 conn->server_info->unix_name));
3153 return NT_STATUS_ACCESS_DENIED;
3156 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3157 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3158 return map_nt_error_from_unix(errno);
3163 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3164 lp_servicename(SNUM(conn))));
3166 /* Unknown1 24 NULL bytes*/
3167 SBIG_UINT(pdata,0,(uint64_t)0);
3168 SBIG_UINT(pdata,8,(uint64_t)0);
3169 SBIG_UINT(pdata,16,(uint64_t)0);
3171 /* Default Soft Quota 8 bytes */
3172 SBIG_UINT(pdata,24,quotas.softlim);
3174 /* Default Hard Quota 8 bytes */
3175 SBIG_UINT(pdata,32,quotas.hardlim);
3177 /* Quota flag 2 bytes */
3178 SSVAL(pdata,40,quotas.qflags);
3180 /* Unknown3 6 NULL bytes */
3186 #endif /* HAVE_SYS_QUOTAS */
3187 case SMB_FS_OBJECTID_INFORMATION:
3189 unsigned char objid[16];
3190 struct smb_extended_info extended_info;
3191 memcpy(pdata,create_volume_objectid(conn, objid),16);
3192 samba_extended_info_version (&extended_info);
3193 SIVAL(pdata,16,extended_info.samba_magic);
3194 SIVAL(pdata,20,extended_info.samba_version);
3195 SIVAL(pdata,24,extended_info.samba_subversion);
3196 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3197 memcpy(pdata+36,extended_info.samba_version_string,28);
3203 * Query the version and capabilities of the CIFS UNIX extensions
3207 case SMB_QUERY_CIFS_UNIX_INFO:
3209 bool large_write = lp_min_receive_file_size() &&
3210 !srv_is_signing_active(smbd_server_conn);
3211 bool large_read = !srv_is_signing_active(smbd_server_conn);
3212 int encrypt_caps = 0;
3214 if (!lp_unix_extensions()) {
3215 return NT_STATUS_INVALID_LEVEL;
3218 switch (conn->encrypt_level) {
3224 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3227 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3228 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3229 large_write = false;
3235 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3236 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3238 /* We have POSIX ACLs, pathname, encryption,
3239 * large read/write, and locking capability. */
3241 SBIG_UINT(pdata,4,((uint64_t)(
3242 CIFS_UNIX_POSIX_ACLS_CAP|
3243 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3244 CIFS_UNIX_FCNTL_LOCKS_CAP|
3245 CIFS_UNIX_EXTATTR_CAP|
3246 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3248 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3250 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3254 case SMB_QUERY_POSIX_FS_INFO:
3257 vfs_statvfs_struct svfs;
3259 if (!lp_unix_extensions()) {
3260 return NT_STATUS_INVALID_LEVEL;
3263 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3267 SIVAL(pdata,0,svfs.OptimalTransferSize);
3268 SIVAL(pdata,4,svfs.BlockSize);
3269 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3270 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3271 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3272 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3273 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3274 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3275 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3277 } else if (rc == EOPNOTSUPP) {
3278 return NT_STATUS_INVALID_LEVEL;
3279 #endif /* EOPNOTSUPP */
3281 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3282 return NT_STATUS_DOS(ERRSRV, ERRerror);
3287 case SMB_QUERY_POSIX_WHOAMI:
3293 if (!lp_unix_extensions()) {
3294 return NT_STATUS_INVALID_LEVEL;
3297 if (max_data_bytes < 40) {
3298 return NT_STATUS_BUFFER_TOO_SMALL;
3301 /* We ARE guest if global_sid_Builtin_Guests is
3302 * in our list of SIDs.
3304 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3305 conn->server_info->ptok)) {
3306 flags |= SMB_WHOAMI_GUEST;
3309 /* We are NOT guest if global_sid_Authenticated_Users
3310 * is in our list of SIDs.
3312 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3313 conn->server_info->ptok)) {
3314 flags &= ~SMB_WHOAMI_GUEST;
3317 /* NOTE: 8 bytes for UID/GID, irrespective of native
3318 * platform size. This matches
3319 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3321 data_len = 4 /* flags */
3328 + 4 /* pad/reserved */
3329 + (conn->server_info->utok.ngroups * 8)
3331 + (conn->server_info->ptok->num_sids *
3335 SIVAL(pdata, 0, flags);
3336 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3338 (uint64_t)conn->server_info->utok.uid);
3339 SBIG_UINT(pdata, 16,
3340 (uint64_t)conn->server_info->utok.gid);
3343 if (data_len >= max_data_bytes) {
3344 /* Potential overflow, skip the GIDs and SIDs. */
3346 SIVAL(pdata, 24, 0); /* num_groups */
3347 SIVAL(pdata, 28, 0); /* num_sids */
3348 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3349 SIVAL(pdata, 36, 0); /* reserved */
3355 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3356 SIVAL(pdata, 28, conn->server_info->num_sids);
3358 /* We walk the SID list twice, but this call is fairly
3359 * infrequent, and I don't expect that it's performance
3360 * sensitive -- jpeach
3362 for (i = 0, sid_bytes = 0;
3363 i < conn->server_info->ptok->num_sids; ++i) {
3364 sid_bytes += ndr_size_dom_sid(
3365 &conn->server_info->ptok->user_sids[i],
3370 /* SID list byte count */
3371 SIVAL(pdata, 32, sid_bytes);
3373 /* 4 bytes pad/reserved - must be zero */
3374 SIVAL(pdata, 36, 0);
3378 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3379 SBIG_UINT(pdata, data_len,
3380 (uint64_t)conn->server_info->utok.groups[i]);
3386 i < conn->server_info->ptok->num_sids; ++i) {
3387 int sid_len = ndr_size_dom_sid(
3388 &conn->server_info->ptok->user_sids[i],
3392 sid_linearize(pdata + data_len, sid_len,
3393 &conn->server_info->ptok->user_sids[i]);
3394 data_len += sid_len;
3400 case SMB_MAC_QUERY_FS_INFO:
3402 * Thursby MAC extension... ONLY on NTFS filesystems
3403 * once we do streams then we don't need this
3405 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3407 SIVAL(pdata,84,0x100); /* Don't support mac... */
3412 return NT_STATUS_INVALID_LEVEL;
3415 *ret_data_len = data_len;
3416 return NT_STATUS_OK;
3419 /****************************************************************************
3420 Reply to a TRANS2_QFSINFO (query filesystem info).
3421 ****************************************************************************/
3423 static void call_trans2qfsinfo(connection_struct *conn,
3424 struct smb_request *req,
3425 char **pparams, int total_params,
3426 char **ppdata, int total_data,
3427 unsigned int max_data_bytes)
3429 char *params = *pparams;
3430 uint16_t info_level;
3434 if (total_params < 2) {
3435 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3439 info_level = SVAL(params,0);
3441 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3442 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3443 DEBUG(0,("call_trans2qfsinfo: encryption required "
3444 "and info level 0x%x sent.\n",
3445 (unsigned int)info_level));
3446 exit_server_cleanly("encryption required "
3452 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3454 status = smbd_do_qfsinfo(conn, req,
3459 if (!NT_STATUS_IS_OK(status)) {
3460 reply_nterror(req, status);
3464 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3467 DEBUG( 4, ( "%s info_level = %d\n",
3468 smb_fn_name(req->cmd), info_level) );
3473 /****************************************************************************
3474 Reply to a TRANS2_SETFSINFO (set filesystem info).
3475 ****************************************************************************/
3477 static void call_trans2setfsinfo(connection_struct *conn,
3478 struct smb_request *req,
3479 char **pparams, int total_params,
3480 char **ppdata, int total_data,
3481 unsigned int max_data_bytes)
3483 char *pdata = *ppdata;
3484 char *params = *pparams;
3487 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3490 if (total_params < 4) {
3491 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3493 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3497 info_level = SVAL(params,2);
3500 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3501 info_level != SMB_SET_CIFS_UNIX_INFO) {
3502 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3503 "info level (0x%x) on IPC$.\n",
3504 (unsigned int)info_level));
3505 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3510 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3511 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3512 DEBUG(0,("call_trans2setfsinfo: encryption required "
3513 "and info level 0x%x sent.\n",
3514 (unsigned int)info_level));
3515 exit_server_cleanly("encryption required "
3521 switch(info_level) {
3522 case SMB_SET_CIFS_UNIX_INFO:
3524 uint16 client_unix_major;
3525 uint16 client_unix_minor;
3526 uint32 client_unix_cap_low;
3527 uint32 client_unix_cap_high;
3529 if (!lp_unix_extensions()) {
3531 NT_STATUS_INVALID_LEVEL);
3535 /* There should be 12 bytes of capabilities set. */
3536 if (total_data < 8) {
3539 NT_STATUS_INVALID_PARAMETER);
3542 client_unix_major = SVAL(pdata,0);
3543 client_unix_minor = SVAL(pdata,2);
3544 client_unix_cap_low = IVAL(pdata,4);
3545 client_unix_cap_high = IVAL(pdata,8);
3546 /* Just print these values for now. */
3547 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3548 cap_low = 0x%x, cap_high = 0x%x\n",
3549 (unsigned int)client_unix_major,
3550 (unsigned int)client_unix_minor,
3551 (unsigned int)client_unix_cap_low,
3552 (unsigned int)client_unix_cap_high ));
3554 /* Here is where we must switch to posix pathname processing... */
3555 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3556 lp_set_posix_pathnames();
3557 mangle_change_to_posix();
3560 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3561 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3562 /* Client that knows how to do posix locks,
3563 * but not posix open/mkdir operations. Set a
3564 * default type for read/write checks. */
3566 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3572 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3575 size_t param_len = 0;
3576 size_t data_len = total_data;
3578 if (!lp_unix_extensions()) {
3581 NT_STATUS_INVALID_LEVEL);
3585 if (lp_smb_encrypt(SNUM(conn)) == false) {
3588 NT_STATUS_NOT_SUPPORTED);
3592 DEBUG( 4,("call_trans2setfsinfo: "
3593 "request transport encryption.\n"));
3595 status = srv_request_encryption_setup(conn,
3596 (unsigned char **)ppdata,
3598 (unsigned char **)pparams,
3601 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3602 !NT_STATUS_IS_OK(status)) {
3603 reply_nterror(req, status);
3607 send_trans2_replies(conn, req,
3614 if (NT_STATUS_IS_OK(status)) {
3615 /* Server-side transport
3616 * encryption is now *on*. */
3617 status = srv_encryption_start(conn);
3618 if (!NT_STATUS_IS_OK(status)) {
3619 exit_server_cleanly(
3620 "Failure in setting "
3621 "up encrypted transport");
3627 case SMB_FS_QUOTA_INFORMATION:
3629 files_struct *fsp = NULL;
3630 SMB_NTQUOTA_STRUCT quotas;
3632 ZERO_STRUCT(quotas);
3635 if ((conn->server_info->utok.uid != sec_initial_uid())
3636 ||!CAN_WRITE(conn)) {
3637 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3638 lp_servicename(SNUM(conn)),
3639 conn->server_info->unix_name));
3640 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3644 /* note: normaly there're 48 bytes,
3645 * but we didn't use the last 6 bytes for now
3648 fsp = file_fsp(req, SVAL(params,0));
3650 if (!check_fsp_ntquota_handle(conn, req,
3652 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3654 req, NT_STATUS_INVALID_HANDLE);
3658 if (total_data < 42) {
3659 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3663 NT_STATUS_INVALID_PARAMETER);
3667 /* unknown_1 24 NULL bytes in pdata*/
3669 /* the soft quotas 8 bytes (uint64_t)*/
3670 quotas.softlim = (uint64_t)IVAL(pdata,24);
3671 #ifdef LARGE_SMB_OFF_T
3672 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3673 #else /* LARGE_SMB_OFF_T */
3674 if ((IVAL(pdata,28) != 0)&&
3675 ((quotas.softlim != 0xFFFFFFFF)||
3676 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3677 /* more than 32 bits? */
3680 NT_STATUS_INVALID_PARAMETER);
3683 #endif /* LARGE_SMB_OFF_T */
3685 /* the hard quotas 8 bytes (uint64_t)*/
3686 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3687 #ifdef LARGE_SMB_OFF_T
3688 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3689 #else /* LARGE_SMB_OFF_T */
3690 if ((IVAL(pdata,36) != 0)&&
3691 ((quotas.hardlim != 0xFFFFFFFF)||
3692 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3693 /* more than 32 bits? */
3696 NT_STATUS_INVALID_PARAMETER);
3699 #endif /* LARGE_SMB_OFF_T */
3701 /* quota_flags 2 bytes **/
3702 quotas.qflags = SVAL(pdata,40);
3704 /* unknown_2 6 NULL bytes follow*/
3706 /* now set the quotas */
3707 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3708 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3709 reply_nterror(req, map_nt_error_from_unix(errno));
3716 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3718 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3724 * sending this reply works fine,
3725 * but I'm not sure it's the same
3726 * like windows do...
3729 reply_outbuf(req, 10, 0);
3732 #if defined(HAVE_POSIX_ACLS)
3733 /****************************************************************************
3734 Utility function to count the number of entries in a POSIX acl.
3735 ****************************************************************************/
3737 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3739 unsigned int ace_count = 0;
3740 int entry_id = SMB_ACL_FIRST_ENTRY;
3741 SMB_ACL_ENTRY_T entry;
3743 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3745 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3746 entry_id = SMB_ACL_NEXT_ENTRY;
3753 /****************************************************************************
3754 Utility function to marshall a POSIX acl into wire format.
3755 ****************************************************************************/
3757 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3759 int entry_id = SMB_ACL_FIRST_ENTRY;
3760 SMB_ACL_ENTRY_T entry;
3762 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3763 SMB_ACL_TAG_T tagtype;
3764 SMB_ACL_PERMSET_T permset;
3765 unsigned char perms = 0;
3766 unsigned int own_grp;
3769 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3770 entry_id = SMB_ACL_NEXT_ENTRY;
3773 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3774 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3778 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3779 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3783 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3784 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3785 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3787 SCVAL(pdata,1,perms);
3790 case SMB_ACL_USER_OBJ:
3791 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3792 own_grp = (unsigned int)pst->st_ex_uid;
3793 SIVAL(pdata,2,own_grp);
3798 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3800 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3803 own_grp = (unsigned int)*puid;
3804 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3805 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3806 SIVAL(pdata,2,own_grp);
3810 case SMB_ACL_GROUP_OBJ:
3811 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3812 own_grp = (unsigned int)pst->st_ex_gid;
3813 SIVAL(pdata,2,own_grp);
3818 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3820 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3823 own_grp = (unsigned int)*pgid;
3824 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3825 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3826 SIVAL(pdata,2,own_grp);
3831 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3832 SIVAL(pdata,2,0xFFFFFFFF);
3833 SIVAL(pdata,6,0xFFFFFFFF);
3836 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3837 SIVAL(pdata,2,0xFFFFFFFF);
3838 SIVAL(pdata,6,0xFFFFFFFF);
3841 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3844 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3851 /****************************************************************************
3852 Store the FILE_UNIX_BASIC info.
3853 ****************************************************************************/
3855 static char *store_file_unix_basic(connection_struct *conn,
3858 const SMB_STRUCT_STAT *psbuf)
3860 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3861 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3863 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3866 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3869 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3870 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3871 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3874 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3878 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3882 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3885 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3889 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3893 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */
3896 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3900 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3907 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3908 * the chflags(2) (or equivalent) flags.
3910 * XXX: this really should be behind the VFS interface. To do this, we would
3911 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3912 * Each VFS module could then implement its own mapping as appropriate for the
3913 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3915 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3919 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3923 { UF_IMMUTABLE, EXT_IMMUTABLE },
3927 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3931 { UF_HIDDEN, EXT_HIDDEN },
3934 /* Do not remove. We need to guarantee that this array has at least one
3935 * entry to build on HP-UX.
3941 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3942 uint32 *smb_fflags, uint32 *smb_fmask)
3946 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3947 *smb_fmask |= info2_flags_map[i].smb_fflag;
3948 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3949 *smb_fflags |= info2_flags_map[i].smb_fflag;
3954 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3955 const uint32 smb_fflags,
3956 const uint32 smb_fmask,
3959 uint32 max_fmask = 0;
3962 *stat_fflags = psbuf->st_ex_flags;
3964 /* For each flags requested in smb_fmask, check the state of the
3965 * corresponding flag in smb_fflags and set or clear the matching
3969 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3970 max_fmask |= info2_flags_map[i].smb_fflag;
3971 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3972 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3973 *stat_fflags |= info2_flags_map[i].stat_fflag;
3975 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3980 /* If smb_fmask is asking to set any bits that are not supported by
3981 * our flag mappings, we should fail.
3983 if ((smb_fmask & max_fmask) != smb_fmask) {
3991 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3992 * of file flags and birth (create) time.
3994 static char *store_file_unix_basic_info2(connection_struct *conn,
3997 const SMB_STRUCT_STAT *psbuf)
3999 uint32 file_flags = 0;
4000 uint32 flags_mask = 0;
4002 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4004 /* Create (birth) time 64 bit */
4005 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4008 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4009 SIVAL(pdata, 0, file_flags); /* flags */
4010 SIVAL(pdata, 4, flags_mask); /* mask */
4016 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4017 const struct stream_struct *streams,
4019 unsigned int max_data_bytes,
4020 unsigned int *data_size)
4023 unsigned int ofs = 0;
4025 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4026 unsigned int next_offset;
4028 smb_ucs2_t *namebuf;
4030 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4031 streams[i].name, &namelen) ||
4034 return NT_STATUS_INVALID_PARAMETER;
4038 * name_buf is now null-terminated, we need to marshall as not
4044 SIVAL(data, ofs+4, namelen);
4045 SOFF_T(data, ofs+8, streams[i].size);
4046 SOFF_T(data, ofs+16, streams[i].alloc_size);
4047 memcpy(data+ofs+24, namebuf, namelen);
4048 TALLOC_FREE(namebuf);
4050 next_offset = ofs + 24 + namelen;
4052 if (i == num_streams-1) {
4053 SIVAL(data, ofs, 0);
4056 unsigned int align = ndr_align_size(next_offset, 8);
4058 memset(data+next_offset, 0, align);
4059 next_offset += align;
4061 SIVAL(data, ofs, next_offset - ofs);
4070 return NT_STATUS_OK;
4073 /****************************************************************************
4074 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4075 ****************************************************************************/
4077 static void call_trans2qpipeinfo(connection_struct *conn,
4078 struct smb_request *req,
4079 unsigned int tran_call,
4080 char **pparams, int total_params,
4081 char **ppdata, int total_data,
4082 unsigned int max_data_bytes)
4084 char *params = *pparams;
4085 char *pdata = *ppdata;
4086 unsigned int data_size = 0;
4087 unsigned int param_size = 2;
4092 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4096 if (total_params < 4) {
4097 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4101 fsp = file_fsp(req, SVAL(params,0));
4102 if (!fsp_is_np(fsp)) {
4103 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4107 info_level = SVAL(params,2);
4109 *pparams = (char *)SMB_REALLOC(*pparams,2);
4110 if (*pparams == NULL) {
4111 reply_nterror(req, NT_STATUS_NO_MEMORY);
4116 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4117 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4118 if (*ppdata == NULL ) {
4119 reply_nterror(req, NT_STATUS_NO_MEMORY);
4124 switch (info_level) {
4125 case SMB_FILE_STANDARD_INFORMATION:
4127 SOFF_T(pdata,0,4096LL);
4134 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4138 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4144 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4145 TALLOC_CTX *mem_ctx,
4146 uint16_t info_level,
4148 struct smb_filename *smb_fname,
4149 bool delete_pending,
4150 struct timespec write_time_ts,
4152 struct ea_list *ea_list,
4153 int lock_data_count,
4156 unsigned int max_data_bytes,
4158 unsigned int *pdata_size)
4160 char *pdata = *ppdata;
4161 char *dstart, *dend;
4162 unsigned int data_size;
4163 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4164 time_t create_time, mtime, atime, c_time;
4165 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4172 uint64_t file_size = 0;
4174 uint64_t allocation_size = 0;
4175 uint64_t file_index = 0;
4176 uint32_t access_mask = 0;
4178 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4179 return NT_STATUS_INVALID_LEVEL;
4182 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4183 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4184 info_level, max_data_bytes));
4187 mode = dos_mode_msdfs(conn, smb_fname);
4189 mode = dos_mode(conn, smb_fname);
4192 mode = FILE_ATTRIBUTE_NORMAL;
4194 nlink = psbuf->st_ex_nlink;
4196 if (nlink && (mode&aDIR)) {
4200 if ((nlink > 0) && delete_pending) {
4204 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4205 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4206 if (*ppdata == NULL) {
4207 return NT_STATUS_NO_MEMORY;
4211 dend = dstart + data_size - 1;
4213 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4214 update_stat_ex_mtime(psbuf, write_time_ts);
4217 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4218 mtime_ts = psbuf->st_ex_mtime;
4219 atime_ts = psbuf->st_ex_atime;
4220 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4222 if (lp_dos_filetime_resolution(SNUM(conn))) {
4223 dos_filetime_timespec(&create_time_ts);
4224 dos_filetime_timespec(&mtime_ts);
4225 dos_filetime_timespec(&atime_ts);
4226 dos_filetime_timespec(&ctime_ts);
4229 create_time = convert_timespec_to_time_t(create_time_ts);
4230 mtime = convert_timespec_to_time_t(mtime_ts);
4231 atime = convert_timespec_to_time_t(atime_ts);
4232 c_time = convert_timespec_to_time_t(ctime_ts);
4234 p = strrchr_m(smb_fname->base_name,'/');
4236 base_name = smb_fname->base_name;
4240 /* NT expects the name to be in an exact form of the *full*
4241 filename. See the trans2 torture test */
4242 if (ISDOT(base_name)) {
4243 dos_fname = talloc_strdup(mem_ctx, "\\");
4245 return NT_STATUS_NO_MEMORY;
4248 dos_fname = talloc_asprintf(mem_ctx,
4250 smb_fname->base_name);
4252 return NT_STATUS_NO_MEMORY;
4254 if (is_ntfs_stream_smb_fname(smb_fname)) {
4255 dos_fname = talloc_asprintf(dos_fname, "%s",
4256 smb_fname->stream_name);
4258 return NT_STATUS_NO_MEMORY;
4262 string_replace(dos_fname, '/', '\\');
4265 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4268 /* Do we have this path open ? */
4270 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4271 fsp1 = file_find_di_first(fileid);
4272 if (fsp1 && fsp1->initial_allocation_size) {
4273 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4277 if (!(mode & aDIR)) {
4278 file_size = get_file_size_stat(psbuf);
4282 pos = fsp->fh->position_information;
4286 access_mask = fsp->access_mask;
4288 /* GENERIC_EXECUTE mapping from Windows */
4289 access_mask = 0x12019F;
4292 /* This should be an index number - looks like
4295 I think this causes us to fail the IFSKIT
4296 BasicFileInformationTest. -tpot */
4297 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
4298 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
4300 switch (info_level) {
4301 case SMB_INFO_STANDARD:
4302 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4304 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4305 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4306 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4307 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4308 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4309 SSVAL(pdata,l1_attrFile,mode);
4312 case SMB_INFO_QUERY_EA_SIZE:
4314 unsigned int ea_size =
4315 estimate_ea_size(conn, fsp,
4316 smb_fname->base_name);
4317 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4319 srv_put_dos_date2(pdata,0,create_time);
4320 srv_put_dos_date2(pdata,4,atime);
4321 srv_put_dos_date2(pdata,8,mtime); /* write time */
4322 SIVAL(pdata,12,(uint32)file_size);
4323 SIVAL(pdata,16,(uint32)allocation_size);
4324 SSVAL(pdata,20,mode);
4325 SIVAL(pdata,22,ea_size);
4329 case SMB_INFO_IS_NAME_VALID:
4330 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4332 /* os/2 needs this ? really ?*/
4333 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4335 /* This is only reached for qpathinfo */
4339 case SMB_INFO_QUERY_EAS_FROM_LIST:
4341 size_t total_ea_len = 0;
4342 struct ea_list *ea_file_list = NULL;
4344 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4347 get_ea_list_from_file(mem_ctx, conn, fsp,
4348 smb_fname->base_name,
4350 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4352 if (!ea_list || (total_ea_len > data_size)) {
4354 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4358 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4362 case SMB_INFO_QUERY_ALL_EAS:
4364 /* We have data_size bytes to put EA's into. */
4365 size_t total_ea_len = 0;
4367 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4369 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4370 smb_fname->base_name,
4372 if (!ea_list || (total_ea_len > data_size)) {
4374 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4378 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4382 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4384 /* This is FileFullEaInformation - 0xF which maps to
4385 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4387 /* We have data_size bytes to put EA's into. */
4388 size_t total_ea_len = 0;
4389 struct ea_list *ea_file_list = NULL;
4391 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4393 /*TODO: add filtering and index handling */
4396 get_ea_list_from_file(mem_ctx, conn, fsp,
4397 smb_fname->base_name,
4399 if (!ea_file_list) {
4400 return NT_STATUS_NO_EAS_ON_FILE;
4403 status = fill_ea_chained_buffer(mem_ctx,
4407 conn, ea_file_list);
4408 if (!NT_STATUS_IS_OK(status)) {
4414 case SMB_FILE_BASIC_INFORMATION:
4415 case SMB_QUERY_FILE_BASIC_INFO:
4417 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4418 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4419 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4421 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4425 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4426 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4427 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4428 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4429 SIVAL(pdata,32,mode);
4431 DEBUG(5,("SMB_QFBI - "));
4432 DEBUG(5,("create: %s ", ctime(&create_time)));
4433 DEBUG(5,("access: %s ", ctime(&atime)));
4434 DEBUG(5,("write: %s ", ctime(&mtime)));
4435 DEBUG(5,("change: %s ", ctime(&c_time)));
4436 DEBUG(5,("mode: %x\n", mode));
4439 case SMB_FILE_STANDARD_INFORMATION:
4440 case SMB_QUERY_FILE_STANDARD_INFO:
4442 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4444 SOFF_T(pdata,0,allocation_size);
4445 SOFF_T(pdata,8,file_size);
4446 SIVAL(pdata,16,nlink);
4447 SCVAL(pdata,20,delete_pending?1:0);
4448 SCVAL(pdata,21,(mode&aDIR)?1:0);
4449 SSVAL(pdata,22,0); /* Padding. */
4452 case SMB_FILE_EA_INFORMATION:
4453 case SMB_QUERY_FILE_EA_INFO:
4455 unsigned int ea_size =
4456 estimate_ea_size(conn, fsp, smb_fname->base_name);
4457 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4459 SIVAL(pdata,0,ea_size);
4463 /* Get the 8.3 name - used if NT SMB was negotiated. */
4464 case SMB_QUERY_FILE_ALT_NAME_INFO:
4465 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4468 char mangled_name[13];
4469 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4470 if (!name_to_8_3(base_name,mangled_name,
4471 True,conn->params)) {
4472 return NT_STATUS_NO_MEMORY;
4474 len = srvstr_push(dstart, flags2,
4475 pdata+4, mangled_name,
4476 PTR_DIFF(dend, pdata+4),
4478 data_size = 4 + len;
4483 case SMB_QUERY_FILE_NAME_INFO:
4487 this must be *exactly* right for ACLs on mapped drives to work
4489 len = srvstr_push(dstart, flags2,
4491 PTR_DIFF(dend, pdata+4),
4493 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4494 data_size = 4 + len;
4499 case SMB_FILE_ALLOCATION_INFORMATION:
4500 case SMB_QUERY_FILE_ALLOCATION_INFO:
4501 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4503 SOFF_T(pdata,0,allocation_size);
4506 case SMB_FILE_END_OF_FILE_INFORMATION:
4507 case SMB_QUERY_FILE_END_OF_FILEINFO:
4508 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4510 SOFF_T(pdata,0,file_size);
4513 case SMB_QUERY_FILE_ALL_INFO:
4514 case SMB_FILE_ALL_INFORMATION:
4517 unsigned int ea_size =
4518 estimate_ea_size(conn, fsp, smb_fname->base_name);
4519 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4520 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4521 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4522 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4523 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4524 SIVAL(pdata,32,mode);
4525 SIVAL(pdata,36,0); /* padding. */
4527 SOFF_T(pdata,0,allocation_size);
4528 SOFF_T(pdata,8,file_size);
4529 SIVAL(pdata,16,nlink);
4530 SCVAL(pdata,20,delete_pending);
4531 SCVAL(pdata,21,(mode&aDIR)?1:0);
4534 SIVAL(pdata,0,ea_size);
4535 pdata += 4; /* EA info */
4536 len = srvstr_push(dstart, flags2,
4538 PTR_DIFF(dend, pdata+4),
4542 data_size = PTR_DIFF(pdata,(*ppdata));
4546 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4549 unsigned int ea_size =
4550 estimate_ea_size(conn, fsp, smb_fname->base_name);
4551 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4552 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4553 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4554 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4555 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4556 SIVAL(pdata, 0x20, mode);
4557 SIVAL(pdata, 0x24, 0); /* padding. */
4558 SBVAL(pdata, 0x28, allocation_size);
4559 SBVAL(pdata, 0x30, file_size);
4560 SIVAL(pdata, 0x38, nlink);
4561 SCVAL(pdata, 0x3C, delete_pending);
4562 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4563 SSVAL(pdata, 0x3E, 0); /* padding */
4564 SBVAL(pdata, 0x40, file_index);
4565 SIVAL(pdata, 0x48, ea_size);
4566 SIVAL(pdata, 0x4C, access_mask);
4567 SBVAL(pdata, 0x50, pos);
4568 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4569 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4573 len = srvstr_push(dstart, flags2,
4575 PTR_DIFF(dend, pdata+4),
4579 data_size = PTR_DIFF(pdata,(*ppdata));
4582 case SMB_FILE_INTERNAL_INFORMATION:
4584 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4585 SBVAL(pdata, 0, file_index);
4589 case SMB_FILE_ACCESS_INFORMATION:
4590 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4591 SIVAL(pdata, 0, access_mask);
4595 case SMB_FILE_NAME_INFORMATION:
4596 /* Pathname with leading '\'. */
4599 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4600 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4601 SIVAL(pdata,0,byte_len);
4602 data_size = 4 + byte_len;
4606 case SMB_FILE_DISPOSITION_INFORMATION:
4607 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4609 SCVAL(pdata,0,delete_pending);
4612 case SMB_FILE_POSITION_INFORMATION:
4613 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4615 SOFF_T(pdata,0,pos);
4618 case SMB_FILE_MODE_INFORMATION:
4619 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4620 SIVAL(pdata,0,mode);
4624 case SMB_FILE_ALIGNMENT_INFORMATION:
4625 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4626 SIVAL(pdata,0,0); /* No alignment needed. */
4631 * NT4 server just returns "invalid query" to this - if we try
4632 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4635 /* The first statement above is false - verified using Thursby
4636 * client against NT4 -- gcolley.
4638 case SMB_QUERY_FILE_STREAM_INFO:
4639 case SMB_FILE_STREAM_INFORMATION: {
4640 unsigned int num_streams;
4641 struct stream_struct *streams;
4643 DEBUG(10,("smbd_do_qfilepathinfo: "
4644 "SMB_FILE_STREAM_INFORMATION\n"));
4646 if (is_ntfs_stream_smb_fname(smb_fname)) {
4647 return NT_STATUS_INVALID_PARAMETER;
4650 status = SMB_VFS_STREAMINFO(
4651 conn, fsp, smb_fname->base_name, talloc_tos(),
4652 &num_streams, &streams);
4654 if (!NT_STATUS_IS_OK(status)) {
4655 DEBUG(10, ("could not get stream info: %s\n",
4656 nt_errstr(status)));
4660 status = marshall_stream_info(num_streams, streams,
4661 pdata, max_data_bytes,
4664 if (!NT_STATUS_IS_OK(status)) {
4665 DEBUG(10, ("marshall_stream_info failed: %s\n",
4666 nt_errstr(status)));
4670 TALLOC_FREE(streams);
4674 case SMB_QUERY_COMPRESSION_INFO:
4675 case SMB_FILE_COMPRESSION_INFORMATION:
4676 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4677 SOFF_T(pdata,0,file_size);
4678 SIVAL(pdata,8,0); /* ??? */
4679 SIVAL(pdata,12,0); /* ??? */
4683 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4684 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4685 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4686 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4687 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4688 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4689 SOFF_T(pdata,32,allocation_size);
4690 SOFF_T(pdata,40,file_size);
4691 SIVAL(pdata,48,mode);
4692 SIVAL(pdata,52,0); /* ??? */
4696 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4697 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4698 SIVAL(pdata,0,mode);
4704 * CIFS UNIX Extensions.
4707 case SMB_QUERY_FILE_UNIX_BASIC:
4709 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4710 data_size = PTR_DIFF(pdata,(*ppdata));
4714 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4716 for (i=0; i<100; i++)
4717 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4723 case SMB_QUERY_FILE_UNIX_INFO2:
4725 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4726 data_size = PTR_DIFF(pdata,(*ppdata));
4730 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4732 for (i=0; i<100; i++)
4733 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4739 case SMB_QUERY_FILE_UNIX_LINK:
4742 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4745 return NT_STATUS_NO_MEMORY;
4748 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4750 if(!S_ISLNK(psbuf->st_ex_mode)) {
4751 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4754 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4756 len = SMB_VFS_READLINK(conn,
4757 smb_fname->base_name,
4760 return map_nt_error_from_unix(errno);
4763 len = srvstr_push(dstart, flags2,
4765 PTR_DIFF(dend, pdata),
4768 data_size = PTR_DIFF(pdata,(*ppdata));
4773 #if defined(HAVE_POSIX_ACLS)
4774 case SMB_QUERY_POSIX_ACL:
4776 SMB_ACL_T file_acl = NULL;
4777 SMB_ACL_T def_acl = NULL;
4778 uint16 num_file_acls = 0;
4779 uint16 num_def_acls = 0;
4781 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4782 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4785 SMB_VFS_SYS_ACL_GET_FILE(conn,
4786 smb_fname->base_name,
4787 SMB_ACL_TYPE_ACCESS);
4790 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4791 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4792 "not implemented on "
4793 "filesystem containing %s\n",
4794 smb_fname->base_name));
4795 return NT_STATUS_NOT_IMPLEMENTED;
4798 if (S_ISDIR(psbuf->st_ex_mode)) {
4799 if (fsp && fsp->is_directory) {
4801 SMB_VFS_SYS_ACL_GET_FILE(
4803 fsp->fsp_name->base_name,
4804 SMB_ACL_TYPE_DEFAULT);
4807 SMB_VFS_SYS_ACL_GET_FILE(
4809 smb_fname->base_name,
4810 SMB_ACL_TYPE_DEFAULT);
4812 def_acl = free_empty_sys_acl(conn, def_acl);
4815 num_file_acls = count_acl_entries(conn, file_acl);
4816 num_def_acls = count_acl_entries(conn, def_acl);
4818 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4819 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4821 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4822 SMB_POSIX_ACL_HEADER_SIZE) ));
4824 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4827 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4829 return NT_STATUS_BUFFER_TOO_SMALL;
4832 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4833 SSVAL(pdata,2,num_file_acls);
4834 SSVAL(pdata,4,num_def_acls);
4835 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4837 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4840 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4842 return NT_STATUS_INTERNAL_ERROR;
4844 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4846 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4849 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4851 return NT_STATUS_INTERNAL_ERROR;
4855 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4858 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4860 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4866 case SMB_QUERY_POSIX_LOCK:
4871 enum brl_type lock_type;
4873 /* We need an open file with a real fd for this. */
4874 if (!fsp || fsp->is_directory || fsp->fh->fd == -1) {
4875 return NT_STATUS_INVALID_LEVEL;
4878 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4879 return NT_STATUS_INVALID_PARAMETER;
4882 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4883 case POSIX_LOCK_TYPE_READ:
4884 lock_type = READ_LOCK;
4886 case POSIX_LOCK_TYPE_WRITE:
4887 lock_type = WRITE_LOCK;
4889 case POSIX_LOCK_TYPE_UNLOCK:
4891 /* There's no point in asking for an unlock... */
4892 return NT_STATUS_INVALID_PARAMETER;
4895 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4896 #if defined(HAVE_LONGLONG)
4897 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4898 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4899 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4900 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4901 #else /* HAVE_LONGLONG */
4902 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4903 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4904 #endif /* HAVE_LONGLONG */
4906 status = query_lock(fsp,
4913 if (ERROR_WAS_LOCK_DENIED(status)) {
4914 /* Here we need to report who has it locked... */
4915 data_size = POSIX_LOCK_DATA_SIZE;
4917 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4918 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4919 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4920 #if defined(HAVE_LONGLONG)
4921 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4922 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4923 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4924 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4925 #else /* HAVE_LONGLONG */
4926 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4927 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4928 #endif /* HAVE_LONGLONG */
4930 } else if (NT_STATUS_IS_OK(status)) {
4931 /* For success we just return a copy of what we sent
4932 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4933 data_size = POSIX_LOCK_DATA_SIZE;
4934 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4935 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4943 return NT_STATUS_INVALID_LEVEL;
4946 *pdata_size = data_size;
4947 return NT_STATUS_OK;
4950 /****************************************************************************
4951 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4952 file name or file id).
4953 ****************************************************************************/
4955 static void call_trans2qfilepathinfo(connection_struct *conn,
4956 struct smb_request *req,
4957 unsigned int tran_call,
4958 char **pparams, int total_params,
4959 char **ppdata, int total_data,
4960 unsigned int max_data_bytes)
4962 char *params = *pparams;
4963 char *pdata = *ppdata;
4965 unsigned int data_size = 0;
4966 unsigned int param_size = 2;
4967 struct smb_filename *smb_fname = NULL;
4968 bool delete_pending = False;
4969 struct timespec write_time_ts;
4970 files_struct *fsp = NULL;
4971 struct file_id fileid;
4972 struct ea_list *ea_list = NULL;
4973 int lock_data_count = 0;
4974 char *lock_data = NULL;
4975 bool ms_dfs_link = false;
4976 NTSTATUS status = NT_STATUS_OK;
4979 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4983 ZERO_STRUCT(write_time_ts);
4985 if (tran_call == TRANSACT2_QFILEINFO) {
4986 if (total_params < 4) {
4987 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4992 call_trans2qpipeinfo(conn, req, tran_call,
4993 pparams, total_params,
4999 fsp = file_fsp(req, SVAL(params,0));
5000 info_level = SVAL(params,2);
5002 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5004 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5005 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5009 /* Initial check for valid fsp ptr. */
5010 if (!check_fsp_open(conn, req, fsp)) {
5014 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5016 if (!NT_STATUS_IS_OK(status)) {
5017 reply_nterror(req, status);
5021 if(fsp->fake_file_handle) {
5023 * This is actually for the QUOTA_FAKE_FILE --metze
5026 /* We know this name is ok, it's already passed the checks. */
5028 } else if(fsp->is_directory || fsp->fh->fd == -1) {
5030 * This is actually a QFILEINFO on a directory
5031 * handle (returned from an NT SMB). NT5.0 seems
5032 * to do this call. JRA.
5035 if (INFO_LEVEL_IS_UNIX(info_level)) {
5036 /* Always do lstat for UNIX calls. */
5037 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5038 DEBUG(3,("call_trans2qfilepathinfo: "
5039 "SMB_VFS_LSTAT of %s failed "
5041 smb_fname_str_dbg(smb_fname),
5044 map_nt_error_from_unix(errno));
5047 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5048 DEBUG(3,("call_trans2qfilepathinfo: "
5049 "SMB_VFS_STAT of %s failed (%s)\n",
5050 smb_fname_str_dbg(smb_fname),
5053 map_nt_error_from_unix(errno));
5057 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5058 get_file_infos(fileid, &delete_pending, &write_time_ts);
5061 * Original code - this is an open file.
5063 if (!check_fsp(conn, req, fsp)) {
5067 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5068 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5069 fsp->fnum, strerror(errno)));
5071 map_nt_error_from_unix(errno));
5074 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5075 get_file_infos(fileid, &delete_pending, &write_time_ts);
5082 if (total_params < 7) {
5083 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5087 info_level = SVAL(params,0);
5089 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5091 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5092 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5096 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
5098 STR_TERMINATE, &status);
5099 if (!NT_STATUS_IS_OK(status)) {
5100 reply_nterror(req, status);
5104 status = filename_convert(req,
5106 req->flags2 & FLAGS2_DFS_PATHNAMES,
5111 if (!NT_STATUS_IS_OK(status)) {
5112 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5113 reply_botherror(req,
5114 NT_STATUS_PATH_NOT_COVERED,
5115 ERRSRV, ERRbadpath);
5118 reply_nterror(req, status);
5122 /* If this is a stream, check if there is a delete_pending. */
5123 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5124 && is_ntfs_stream_smb_fname(smb_fname)) {
5125 struct smb_filename *smb_fname_base = NULL;
5127 /* Create an smb_filename with stream_name == NULL. */
5129 create_synthetic_smb_fname(talloc_tos(),
5130 smb_fname->base_name,
5133 if (!NT_STATUS_IS_OK(status)) {
5134 reply_nterror(req, status);
5138 if (INFO_LEVEL_IS_UNIX(info_level)) {
5139 /* Always do lstat for UNIX calls. */
5140 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5141 DEBUG(3,("call_trans2qfilepathinfo: "
5142 "SMB_VFS_LSTAT of %s failed "
5144 smb_fname_str_dbg(smb_fname_base),
5146 TALLOC_FREE(smb_fname_base);
5148 map_nt_error_from_unix(errno));
5152 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5153 DEBUG(3,("call_trans2qfilepathinfo: "
5154 "fileinfo of %s failed "
5156 smb_fname_str_dbg(smb_fname_base),
5158 TALLOC_FREE(smb_fname_base);
5160 map_nt_error_from_unix(errno));
5165 fileid = vfs_file_id_from_sbuf(conn,
5166 &smb_fname_base->st);
5167 TALLOC_FREE(smb_fname_base);
5168 get_file_infos(fileid, &delete_pending, NULL);
5169 if (delete_pending) {
5170 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5175 if (INFO_LEVEL_IS_UNIX(info_level)) {
5176 /* Always do lstat for UNIX calls. */
5177 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5178 DEBUG(3,("call_trans2qfilepathinfo: "
5179 "SMB_VFS_LSTAT of %s failed (%s)\n",
5180 smb_fname_str_dbg(smb_fname),
5183 map_nt_error_from_unix(errno));
5187 } else if (!VALID_STAT(smb_fname->st) &&
5188 SMB_VFS_STAT(conn, smb_fname) &&
5189 (info_level != SMB_INFO_IS_NAME_VALID)) {
5190 ms_dfs_link = check_msdfs_link(conn,
5191 smb_fname->base_name,
5195 DEBUG(3,("call_trans2qfilepathinfo: "
5196 "SMB_VFS_STAT of %s failed (%s)\n",
5197 smb_fname_str_dbg(smb_fname),
5200 map_nt_error_from_unix(errno));
5205 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5206 get_file_infos(fileid, &delete_pending, &write_time_ts);
5207 if (delete_pending) {
5208 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5213 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5214 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5215 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5217 /* Pull out any data sent here before we realloc. */
5218 switch (info_level) {
5219 case SMB_INFO_QUERY_EAS_FROM_LIST:
5221 /* Pull any EA list from the data portion. */
5224 if (total_data < 4) {
5226 req, NT_STATUS_INVALID_PARAMETER);
5229 ea_size = IVAL(pdata,0);
5231 if (total_data > 0 && ea_size != total_data) {
5232 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5233 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5235 req, NT_STATUS_INVALID_PARAMETER);
5239 if (!lp_ea_support(SNUM(conn))) {
5240 reply_doserror(req, ERRDOS,
5241 ERReasnotsupported);
5245 /* Pull out the list of names. */
5246 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5249 req, NT_STATUS_INVALID_PARAMETER);
5255 case SMB_QUERY_POSIX_LOCK:
5257 if (fsp == NULL || fsp->fh->fd == -1) {
5258 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5262 if (total_data != POSIX_LOCK_DATA_SIZE) {
5264 req, NT_STATUS_INVALID_PARAMETER);
5268 /* Copy the lock range data. */
5269 lock_data = (char *)TALLOC_MEMDUP(
5270 req, pdata, total_data);
5272 reply_nterror(req, NT_STATUS_NO_MEMORY);
5275 lock_data_count = total_data;
5281 *pparams = (char *)SMB_REALLOC(*pparams,2);
5282 if (*pparams == NULL) {
5283 reply_nterror(req, NT_STATUS_NO_MEMORY);
5290 * draft-leach-cifs-v1-spec-02.txt
5291 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5294 * The requested information is placed in the Data portion of the
5295 * transaction response. For the information levels greater than 0x100,
5296 * the transaction response has 1 parameter word which should be
5297 * ignored by the client.
5299 * However Windows only follows this rule for the IS_NAME_VALID call.
5301 switch (info_level) {
5302 case SMB_INFO_IS_NAME_VALID:
5307 if ((info_level & 0xFF00) == 0xFF00) {
5309 * We use levels that start with 0xFF00
5310 * internally to represent SMB2 specific levels
5312 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5316 status = smbd_do_qfilepathinfo(conn, req, info_level,
5318 delete_pending, write_time_ts,
5319 ms_dfs_link, ea_list,
5320 lock_data_count, lock_data,
5321 req->flags2, max_data_bytes,
5322 ppdata, &data_size);
5323 if (!NT_STATUS_IS_OK(status)) {
5324 reply_nterror(req, status);
5328 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5334 /****************************************************************************
5335 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5337 ****************************************************************************/
5339 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5340 connection_struct *conn,
5341 const struct smb_filename *smb_fname_old,
5342 const struct smb_filename *smb_fname_new)
5344 NTSTATUS status = NT_STATUS_OK;
5346 /* source must already exist. */
5347 if (!VALID_STAT(smb_fname_old->st)) {
5348 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5351 /* Disallow if newname already exists. */
5352 if (VALID_STAT(smb_fname_new->st)) {
5353 return NT_STATUS_OBJECT_NAME_COLLISION;
5356 /* No links from a directory. */
5357 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5358 return NT_STATUS_FILE_IS_A_DIRECTORY;
5361 /* Setting a hardlink to/from a stream isn't currently supported. */
5362 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5363 is_ntfs_stream_smb_fname(smb_fname_new)) {
5364 return NT_STATUS_INVALID_PARAMETER;
5367 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5368 smb_fname_old->base_name, smb_fname_new->base_name));
5370 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5371 smb_fname_new->base_name) != 0) {
5372 status = map_nt_error_from_unix(errno);
5373 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5374 nt_errstr(status), smb_fname_old->base_name,
5375 smb_fname_new->base_name));
5380 /****************************************************************************
5381 Deal with setting the time from any of the setfilepathinfo functions.
5382 ****************************************************************************/
5384 NTSTATUS smb_set_file_time(connection_struct *conn,
5386 const struct smb_filename *smb_fname,
5387 struct smb_file_time *ft,
5388 bool setting_write_time)
5390 struct smb_filename smb_fname_base;
5392 FILE_NOTIFY_CHANGE_LAST_ACCESS
5393 |FILE_NOTIFY_CHANGE_LAST_WRITE
5394 |FILE_NOTIFY_CHANGE_CREATION;
5396 if (!VALID_STAT(smb_fname->st)) {
5397 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5400 /* get some defaults (no modifications) if any info is zero or -1. */
5401 if (null_timespec(ft->create_time)) {
5402 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5405 if (null_timespec(ft->atime)) {
5406 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5409 if (null_timespec(ft->mtime)) {
5410 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5413 if (!setting_write_time) {
5414 /* ft->mtime comes from change time, not write time. */
5415 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5418 /* Ensure the resolution is the correct for
5419 * what we can store on this filesystem. */
5421 round_timespec(conn->ts_res, &ft->create_time);
5422 round_timespec(conn->ts_res, &ft->ctime);
5423 round_timespec(conn->ts_res, &ft->atime);
5424 round_timespec(conn->ts_res, &ft->mtime);
5426 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5427 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5428 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5429 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5430 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5431 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5432 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5433 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5435 if (setting_write_time) {
5437 * This was a Windows setfileinfo on an open file.
5438 * NT does this a lot. We also need to
5439 * set the time here, as it can be read by
5440 * FindFirst/FindNext and with the patch for bug #2045
5441 * in smbd/fileio.c it ensures that this timestamp is
5442 * kept sticky even after a write. We save the request
5443 * away and will set it on file close and after a write. JRA.
5446 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5447 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5450 if (fsp->base_fsp) {
5451 set_sticky_write_time_fsp(fsp->base_fsp,
5454 set_sticky_write_time_fsp(fsp, ft->mtime);
5457 set_sticky_write_time_path(
5458 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5463 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5465 /* Always call ntimes on the base, even if a stream was passed in. */
5466 smb_fname_base = *smb_fname;
5467 smb_fname_base.stream_name = NULL;
5469 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5470 return map_nt_error_from_unix(errno);
5473 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5474 smb_fname->base_name);
5475 return NT_STATUS_OK;
5478 /****************************************************************************
5479 Deal with setting the dosmode from any of the setfilepathinfo functions.
5480 ****************************************************************************/
5482 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5483 const struct smb_filename *smb_fname,
5486 struct smb_filename *smb_fname_base = NULL;
5489 if (!VALID_STAT(smb_fname->st)) {
5490 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5493 /* Always operate on the base_name, even if a stream was passed in. */
5494 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5495 NULL, &smb_fname->st,
5497 if (!NT_STATUS_IS_OK(status)) {
5502 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5509 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5511 /* check the mode isn't different, before changing it */
5512 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5513 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5514 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5515 (unsigned int)dosmode));
5517 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5519 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5521 smb_fname_str_dbg(smb_fname_base),
5523 status = map_nt_error_from_unix(errno);
5527 status = NT_STATUS_OK;
5529 TALLOC_FREE(smb_fname_base);
5533 /****************************************************************************
5534 Deal with setting the size from any of the setfilepathinfo functions.
5535 ****************************************************************************/
5537 static NTSTATUS smb_set_file_size(connection_struct *conn,
5538 struct smb_request *req,
5540 const struct smb_filename *smb_fname,
5541 const SMB_STRUCT_STAT *psbuf,
5544 NTSTATUS status = NT_STATUS_OK;
5545 struct smb_filename *smb_fname_tmp = NULL;
5546 files_struct *new_fsp = NULL;
5548 if (!VALID_STAT(*psbuf)) {
5549 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5552 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5554 if (size == get_file_size_stat(psbuf)) {
5555 return NT_STATUS_OK;
5558 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5559 smb_fname_str_dbg(smb_fname), (double)size));
5561 if (fsp && fsp->fh->fd != -1) {
5562 /* Handle based call. */
5563 if (vfs_set_filelen(fsp, size) == -1) {
5564 return map_nt_error_from_unix(errno);
5566 trigger_write_time_update_immediate(fsp);
5567 return NT_STATUS_OK;
5570 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5571 if (!NT_STATUS_IS_OK(status)) {
5575 smb_fname_tmp->st = *psbuf;
5577 status = SMB_VFS_CREATE_FILE(
5580 0, /* root_dir_fid */
5581 smb_fname_tmp, /* fname */
5582 FILE_WRITE_ATTRIBUTES, /* access_mask */
5583 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5585 FILE_OPEN, /* create_disposition*/
5586 0, /* create_options */
5587 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5588 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5589 0, /* allocation_size */
5592 &new_fsp, /* result */
5595 TALLOC_FREE(smb_fname_tmp);
5597 if (!NT_STATUS_IS_OK(status)) {
5598 /* NB. We check for open_was_deferred in the caller. */
5602 if (vfs_set_filelen(new_fsp, size) == -1) {
5603 status = map_nt_error_from_unix(errno);
5604 close_file(req, new_fsp,NORMAL_CLOSE);
5608 trigger_write_time_update_immediate(new_fsp);
5609 close_file(req, new_fsp,NORMAL_CLOSE);
5610 return NT_STATUS_OK;
5613 /****************************************************************************
5614 Deal with SMB_INFO_SET_EA.
5615 ****************************************************************************/
5617 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5621 const struct smb_filename *smb_fname)
5623 struct ea_list *ea_list = NULL;
5624 TALLOC_CTX *ctx = NULL;
5625 NTSTATUS status = NT_STATUS_OK;
5627 if (total_data < 10) {
5629 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5630 length. They seem to have no effect. Bug #3212. JRA */
5632 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5633 /* We're done. We only get EA info in this call. */
5634 return NT_STATUS_OK;
5637 return NT_STATUS_INVALID_PARAMETER;
5640 if (IVAL(pdata,0) > total_data) {
5641 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5642 IVAL(pdata,0), (unsigned int)total_data));
5643 return NT_STATUS_INVALID_PARAMETER;
5647 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5649 return NT_STATUS_INVALID_PARAMETER;
5651 status = set_ea(conn, fsp, smb_fname, ea_list);
5656 /****************************************************************************
5657 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5658 ****************************************************************************/
5660 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5665 struct ea_list *ea_list = NULL;
5669 return NT_STATUS_INVALID_HANDLE;
5672 if (!lp_ea_support(SNUM(conn))) {
5673 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5674 "EA's not supported.\n",
5675 (unsigned int)total_data));
5676 return NT_STATUS_EAS_NOT_SUPPORTED;
5679 if (total_data < 10) {
5680 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5682 (unsigned int)total_data));
5683 return NT_STATUS_INVALID_PARAMETER;
5686 ea_list = read_nttrans_ea_list(talloc_tos(),
5691 return NT_STATUS_INVALID_PARAMETER;
5693 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5695 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5696 smb_fname_str_dbg(fsp->fsp_name),
5697 nt_errstr(status) ));
5703 /****************************************************************************
5704 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5705 ****************************************************************************/
5707 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5711 struct smb_filename *smb_fname)
5713 NTSTATUS status = NT_STATUS_OK;
5714 bool delete_on_close;
5717 if (total_data < 1) {
5718 return NT_STATUS_INVALID_PARAMETER;
5722 return NT_STATUS_INVALID_HANDLE;
5725 delete_on_close = (CVAL(pdata,0) ? True : False);
5726 dosmode = dos_mode(conn, smb_fname);
5728 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5729 "delete_on_close = %u\n",
5730 smb_fname_str_dbg(smb_fname),
5731 (unsigned int)dosmode,
5732 (unsigned int)delete_on_close ));
5734 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5736 if (!NT_STATUS_IS_OK(status)) {
5740 /* The set is across all open files on this dev/inode pair. */
5741 if (!set_delete_on_close(fsp, delete_on_close,
5742 &conn->server_info->utok)) {
5743 return NT_STATUS_ACCESS_DENIED;
5745 return NT_STATUS_OK;
5748 /****************************************************************************
5749 Deal with SMB_FILE_POSITION_INFORMATION.
5750 ****************************************************************************/
5752 static NTSTATUS smb_file_position_information(connection_struct *conn,
5757 uint64_t position_information;
5759 if (total_data < 8) {
5760 return NT_STATUS_INVALID_PARAMETER;
5764 /* Ignore on pathname based set. */
5765 return NT_STATUS_OK;
5768 position_information = (uint64_t)IVAL(pdata,0);
5769 #ifdef LARGE_SMB_OFF_T
5770 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5771 #else /* LARGE_SMB_OFF_T */
5772 if (IVAL(pdata,4) != 0) {
5773 /* more than 32 bits? */
5774 return NT_STATUS_INVALID_PARAMETER;
5776 #endif /* LARGE_SMB_OFF_T */
5778 DEBUG(10,("smb_file_position_information: Set file position "
5779 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5780 (double)position_information));
5781 fsp->fh->position_information = position_information;
5782 return NT_STATUS_OK;
5785 /****************************************************************************
5786 Deal with SMB_FILE_MODE_INFORMATION.
5787 ****************************************************************************/
5789 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5795 if (total_data < 4) {
5796 return NT_STATUS_INVALID_PARAMETER;
5798 mode = IVAL(pdata,0);
5799 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5800 return NT_STATUS_INVALID_PARAMETER;
5802 return NT_STATUS_OK;
5805 /****************************************************************************
5806 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5807 ****************************************************************************/
5809 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5810 struct smb_request *req,
5813 const struct smb_filename *smb_fname)
5815 char *link_target = NULL;
5816 const char *newname = smb_fname->base_name;
5817 NTSTATUS status = NT_STATUS_OK;
5818 TALLOC_CTX *ctx = talloc_tos();
5820 /* Set a symbolic link. */
5821 /* Don't allow this if follow links is false. */
5823 if (total_data == 0) {
5824 return NT_STATUS_INVALID_PARAMETER;
5827 if (!lp_symlinks(SNUM(conn))) {
5828 return NT_STATUS_ACCESS_DENIED;
5831 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5832 total_data, STR_TERMINATE);
5835 return NT_STATUS_INVALID_PARAMETER;
5838 /* !widelinks forces the target path to be within the share. */
5839 /* This means we can interpret the target as a pathname. */
5840 if (!lp_widelinks(SNUM(conn))) {
5841 char *rel_name = NULL;
5842 char *last_dirp = NULL;
5844 if (*link_target == '/') {
5845 /* No absolute paths allowed. */
5846 return NT_STATUS_ACCESS_DENIED;
5848 rel_name = talloc_strdup(ctx,newname);
5850 return NT_STATUS_NO_MEMORY;
5852 last_dirp = strrchr_m(rel_name, '/');
5854 last_dirp[1] = '\0';
5856 rel_name = talloc_strdup(ctx,"./");
5858 return NT_STATUS_NO_MEMORY;
5861 rel_name = talloc_asprintf_append(rel_name,
5865 return NT_STATUS_NO_MEMORY;
5868 status = check_name(conn, rel_name);
5869 if (!NT_STATUS_IS_OK(status)) {
5874 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5875 newname, link_target ));
5877 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5878 return map_nt_error_from_unix(errno);
5881 return NT_STATUS_OK;
5884 /****************************************************************************
5885 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5886 ****************************************************************************/
5888 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5889 struct smb_request *req,
5890 const char *pdata, int total_data,
5891 const struct smb_filename *smb_fname_new)
5893 char *oldname = NULL;
5894 struct smb_filename *smb_fname_old = NULL;
5895 TALLOC_CTX *ctx = talloc_tos();
5896 NTSTATUS status = NT_STATUS_OK;
5898 /* Set a hard link. */
5899 if (total_data == 0) {
5900 return NT_STATUS_INVALID_PARAMETER;
5903 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5904 total_data, STR_TERMINATE, &status);
5905 if (!NT_STATUS_IS_OK(status)) {
5909 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5910 smb_fname_str_dbg(smb_fname_new), oldname));
5912 status = filename_convert(ctx,
5914 req->flags2 & FLAGS2_DFS_PATHNAMES,
5919 if (!NT_STATUS_IS_OK(status)) {
5923 return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
5926 /****************************************************************************
5927 Deal with SMB_FILE_RENAME_INFORMATION.
5928 ****************************************************************************/
5930 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5931 struct smb_request *req,
5935 struct smb_filename *smb_fname_src)
5940 char *newname = NULL;
5941 struct smb_filename *smb_fname_dst = NULL;
5942 bool dest_has_wcard = False;
5943 NTSTATUS status = NT_STATUS_OK;
5945 TALLOC_CTX *ctx = talloc_tos();
5947 if (total_data < 13) {
5948 return NT_STATUS_INVALID_PARAMETER;
5951 overwrite = (CVAL(pdata,0) ? True : False);
5952 root_fid = IVAL(pdata,4);
5953 len = IVAL(pdata,8);
5955 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5956 return NT_STATUS_INVALID_PARAMETER;
5959 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5962 if (!NT_STATUS_IS_OK(status)) {
5966 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5969 status = resolve_dfspath_wcard(ctx, conn,
5970 req->flags2 & FLAGS2_DFS_PATHNAMES,
5974 if (!NT_STATUS_IS_OK(status)) {
5978 /* Check the new name has no '/' characters. */
5979 if (strchr_m(newname, '/')) {
5980 return NT_STATUS_NOT_SUPPORTED;
5983 if (fsp && fsp->base_fsp) {
5984 /* newname must be a stream name. */
5985 if (newname[0] != ':') {
5986 return NT_STATUS_NOT_SUPPORTED;
5989 /* Create an smb_fname to call rename_internals_fsp() with. */
5990 status = create_synthetic_smb_fname(talloc_tos(),
5991 fsp->base_fsp->fsp_name->base_name, newname, NULL,
5993 if (!NT_STATUS_IS_OK(status)) {
5998 * Set the original last component, since
5999 * rename_internals_fsp() requires it.
6001 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6003 if (smb_fname_dst->original_lcomp == NULL) {
6004 status = NT_STATUS_NO_MEMORY;
6010 * Build up an smb_fname_dst based on the filename passed in.
6011 * We basically just strip off the last component, and put on
6012 * the newname instead.
6014 char *base_name = NULL;
6016 /* newname must *not* be a stream name. */
6017 if (newname[0] == ':') {
6018 return NT_STATUS_NOT_SUPPORTED;
6022 * Strip off the last component (filename) of the path passed
6025 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6027 return NT_STATUS_NO_MEMORY;
6029 p = strrchr_m(base_name, '/');
6033 base_name = talloc_strdup(ctx, "./");
6035 return NT_STATUS_NO_MEMORY;
6038 /* Append the new name. */
6039 base_name = talloc_asprintf_append(base_name,
6043 return NT_STATUS_NO_MEMORY;
6046 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6049 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6052 /* If an error we expect this to be
6053 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6055 if (!NT_STATUS_IS_OK(status)) {
6056 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6060 /* Create an smb_fname to call rename_internals_fsp() */
6061 status = create_synthetic_smb_fname(ctx,
6065 if (!NT_STATUS_IS_OK(status)) {
6072 DEBUG(10,("smb_file_rename_information: "
6073 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6074 fsp->fnum, fsp_str_dbg(fsp),
6075 smb_fname_str_dbg(smb_fname_dst)));
6076 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6079 DEBUG(10,("smb_file_rename_information: "
6080 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6081 smb_fname_str_dbg(smb_fname_src),
6082 smb_fname_str_dbg(smb_fname_dst)));
6083 status = rename_internals(ctx, conn, req, smb_fname_src,
6084 smb_fname_dst, 0, overwrite, false,
6086 FILE_WRITE_ATTRIBUTES);
6089 TALLOC_FREE(smb_fname_dst);
6093 /****************************************************************************
6094 Deal with SMB_SET_POSIX_ACL.
6095 ****************************************************************************/
6097 #if defined(HAVE_POSIX_ACLS)
6098 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6102 const struct smb_filename *smb_fname)
6104 uint16 posix_acl_version;
6105 uint16 num_file_acls;
6106 uint16 num_def_acls;
6107 bool valid_file_acls = True;
6108 bool valid_def_acls = True;
6110 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6111 return NT_STATUS_INVALID_PARAMETER;
6113 posix_acl_version = SVAL(pdata,0);
6114 num_file_acls = SVAL(pdata,2);
6115 num_def_acls = SVAL(pdata,4);
6117 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6118 valid_file_acls = False;
6122 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6123 valid_def_acls = False;
6127 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6128 return NT_STATUS_INVALID_PARAMETER;
6131 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6132 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6133 return NT_STATUS_INVALID_PARAMETER;
6136 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6137 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6138 (unsigned int)num_file_acls,
6139 (unsigned int)num_def_acls));
6141 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6142 smb_fname->base_name, num_file_acls,
6143 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6144 return map_nt_error_from_unix(errno);
6147 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6148 smb_fname->base_name, &smb_fname->st, num_def_acls,
6149 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6150 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6151 return map_nt_error_from_unix(errno);
6153 return NT_STATUS_OK;
6157 /****************************************************************************
6158 Deal with SMB_SET_POSIX_LOCK.
6159 ****************************************************************************/
6161 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6162 struct smb_request *req,
6170 bool blocking_lock = False;
6171 enum brl_type lock_type;
6173 NTSTATUS status = NT_STATUS_OK;
6175 if (fsp == NULL || fsp->fh->fd == -1) {
6176 return NT_STATUS_INVALID_HANDLE;
6179 if (total_data != POSIX_LOCK_DATA_SIZE) {
6180 return NT_STATUS_INVALID_PARAMETER;
6183 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6184 case POSIX_LOCK_TYPE_READ:
6185 lock_type = READ_LOCK;
6187 case POSIX_LOCK_TYPE_WRITE:
6188 /* Return the right POSIX-mappable error code for files opened read-only. */
6189 if (!fsp->can_write) {
6190 return NT_STATUS_INVALID_HANDLE;
6192 lock_type = WRITE_LOCK;
6194 case POSIX_LOCK_TYPE_UNLOCK:
6195 lock_type = UNLOCK_LOCK;
6198 return NT_STATUS_INVALID_PARAMETER;
6201 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6202 blocking_lock = False;
6203 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6204 blocking_lock = True;
6206 return NT_STATUS_INVALID_PARAMETER;
6209 if (!lp_blocking_locks(SNUM(conn))) {
6210 blocking_lock = False;
6213 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6214 #if defined(HAVE_LONGLONG)
6215 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6216 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6217 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6218 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6219 #else /* HAVE_LONGLONG */
6220 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6221 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6222 #endif /* HAVE_LONGLONG */
6224 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6225 "lock_pid = %u, count = %.0f, offset = %.0f\n",
6227 (unsigned int)lock_type,
6228 (unsigned int)lock_pid,
6232 if (lock_type == UNLOCK_LOCK) {
6233 status = do_unlock(smbd_messaging_context(),
6240 uint32 block_smbpid;
6242 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
6254 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6256 * A blocking lock was requested. Package up
6257 * this smb into a queued request and push it
6258 * onto the blocking lock queue.
6260 if(push_blocking_lock_request(br_lck,
6263 -1, /* infinite timeout. */
6271 TALLOC_FREE(br_lck);
6275 TALLOC_FREE(br_lck);
6281 /****************************************************************************
6282 Deal with SMB_SET_FILE_BASIC_INFO.
6283 ****************************************************************************/
6285 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6289 const struct smb_filename *smb_fname)
6291 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6292 struct smb_file_time ft;
6294 NTSTATUS status = NT_STATUS_OK;
6298 if (total_data < 36) {
6299 return NT_STATUS_INVALID_PARAMETER;
6302 /* Set the attributes */
6303 dosmode = IVAL(pdata,32);
6304 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6305 if (!NT_STATUS_IS_OK(status)) {
6310 ft.create_time = interpret_long_date(pdata);
6313 ft.atime = interpret_long_date(pdata+8);
6316 ft.mtime = interpret_long_date(pdata+16);
6319 ft.ctime = interpret_long_date(pdata+24);
6321 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6322 smb_fname_str_dbg(smb_fname)));
6324 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6328 /****************************************************************************
6329 Deal with SMB_INFO_STANDARD.
6330 ****************************************************************************/
6332 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6336 const struct smb_filename *smb_fname)
6338 struct smb_file_time ft;
6342 if (total_data < 12) {
6343 return NT_STATUS_INVALID_PARAMETER;
6347 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6349 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6351 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6353 DEBUG(10,("smb_set_info_standard: file %s\n",
6354 smb_fname_str_dbg(smb_fname)));
6356 return smb_set_file_time(conn,
6363 /****************************************************************************
6364 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6365 ****************************************************************************/
6367 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6368 struct smb_request *req,
6372 struct smb_filename *smb_fname)
6374 uint64_t allocation_size = 0;
6375 NTSTATUS status = NT_STATUS_OK;
6376 files_struct *new_fsp = NULL;
6378 if (!VALID_STAT(smb_fname->st)) {
6379 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6382 if (total_data < 8) {
6383 return NT_STATUS_INVALID_PARAMETER;
6386 allocation_size = (uint64_t)IVAL(pdata,0);
6387 #ifdef LARGE_SMB_OFF_T
6388 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6389 #else /* LARGE_SMB_OFF_T */
6390 if (IVAL(pdata,4) != 0) {
6391 /* more than 32 bits? */
6392 return NT_STATUS_INVALID_PARAMETER;
6394 #endif /* LARGE_SMB_OFF_T */
6396 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6397 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6398 (double)allocation_size));
6400 if (allocation_size) {
6401 allocation_size = smb_roundup(conn, allocation_size);
6404 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6405 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6406 (double)allocation_size));
6408 if (fsp && fsp->fh->fd != -1) {
6409 /* Open file handle. */
6410 /* Only change if needed. */
6411 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6412 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6413 return map_nt_error_from_unix(errno);
6416 /* But always update the time. */
6418 * This is equivalent to a write. Ensure it's seen immediately
6419 * if there are no pending writes.
6421 trigger_write_time_update_immediate(fsp);
6422 return NT_STATUS_OK;
6425 /* Pathname or stat or directory file. */
6426 status = SMB_VFS_CREATE_FILE(
6429 0, /* root_dir_fid */
6430 smb_fname, /* fname */
6431 FILE_WRITE_DATA, /* access_mask */
6432 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6434 FILE_OPEN, /* create_disposition*/
6435 0, /* create_options */
6436 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6437 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6438 0, /* allocation_size */
6441 &new_fsp, /* result */
6444 if (!NT_STATUS_IS_OK(status)) {
6445 /* NB. We check for open_was_deferred in the caller. */
6449 /* Only change if needed. */
6450 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6451 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6452 status = map_nt_error_from_unix(errno);
6453 close_file(req, new_fsp, NORMAL_CLOSE);
6458 /* Changing the allocation size should set the last mod time. */
6460 * This is equivalent to a write. Ensure it's seen immediately
6461 * if there are no pending writes.
6463 trigger_write_time_update_immediate(new_fsp);
6465 close_file(req, new_fsp, NORMAL_CLOSE);
6466 return NT_STATUS_OK;
6469 /****************************************************************************
6470 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6471 ****************************************************************************/
6473 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6474 struct smb_request *req,
6478 const struct smb_filename *smb_fname)
6482 if (total_data < 8) {
6483 return NT_STATUS_INVALID_PARAMETER;
6486 size = IVAL(pdata,0);
6487 #ifdef LARGE_SMB_OFF_T
6488 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6489 #else /* LARGE_SMB_OFF_T */
6490 if (IVAL(pdata,4) != 0) {
6491 /* more than 32 bits? */
6492 return NT_STATUS_INVALID_PARAMETER;
6494 #endif /* LARGE_SMB_OFF_T */
6495 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6496 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6499 return smb_set_file_size(conn, req,
6506 /****************************************************************************
6507 Allow a UNIX info mknod.
6508 ****************************************************************************/
6510 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6513 const struct smb_filename *smb_fname)
6515 uint32 file_type = IVAL(pdata,56);
6516 #if defined(HAVE_MAKEDEV)
6517 uint32 dev_major = IVAL(pdata,60);
6518 uint32 dev_minor = IVAL(pdata,68);
6520 SMB_DEV_T dev = (SMB_DEV_T)0;
6521 uint32 raw_unixmode = IVAL(pdata,84);
6525 if (total_data < 100) {
6526 return NT_STATUS_INVALID_PARAMETER;
6529 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6530 PERM_NEW_FILE, &unixmode);
6531 if (!NT_STATUS_IS_OK(status)) {
6535 #if defined(HAVE_MAKEDEV)
6536 dev = makedev(dev_major, dev_minor);
6539 switch (file_type) {
6540 #if defined(S_IFIFO)
6541 case UNIX_TYPE_FIFO:
6542 unixmode |= S_IFIFO;
6545 #if defined(S_IFSOCK)
6546 case UNIX_TYPE_SOCKET:
6547 unixmode |= S_IFSOCK;
6550 #if defined(S_IFCHR)
6551 case UNIX_TYPE_CHARDEV:
6552 unixmode |= S_IFCHR;
6555 #if defined(S_IFBLK)
6556 case UNIX_TYPE_BLKDEV:
6557 unixmode |= S_IFBLK;
6561 return NT_STATUS_INVALID_PARAMETER;
6564 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6565 "%.0f mode 0%o for file %s\n", (double)dev,
6566 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6568 /* Ok - do the mknod. */
6569 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6570 return map_nt_error_from_unix(errno);
6573 /* If any of the other "set" calls fail we
6574 * don't want to end up with a half-constructed mknod.
6577 if (lp_inherit_perms(SNUM(conn))) {
6579 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6581 return NT_STATUS_NO_MEMORY;
6583 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6585 TALLOC_FREE(parent);
6588 return NT_STATUS_OK;
6591 /****************************************************************************
6592 Deal with SMB_SET_FILE_UNIX_BASIC.
6593 ****************************************************************************/
6595 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6596 struct smb_request *req,
6600 const struct smb_filename *smb_fname)
6602 struct smb_file_time ft;
6603 uint32 raw_unixmode;
6606 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6607 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6608 NTSTATUS status = NT_STATUS_OK;
6609 bool delete_on_fail = False;
6610 enum perm_type ptype;
6611 files_struct *all_fsps = NULL;
6612 bool modify_mtime = true;
6614 SMB_STRUCT_STAT sbuf;
6618 if (total_data < 100) {
6619 return NT_STATUS_INVALID_PARAMETER;
6622 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6623 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6624 size=IVAL(pdata,0); /* first 8 Bytes are size */
6625 #ifdef LARGE_SMB_OFF_T
6626 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6627 #else /* LARGE_SMB_OFF_T */
6628 if (IVAL(pdata,4) != 0) {
6629 /* more than 32 bits? */
6630 return NT_STATUS_INVALID_PARAMETER;
6632 #endif /* LARGE_SMB_OFF_T */
6635 ft.atime = interpret_long_date(pdata+24); /* access_time */
6636 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6637 set_owner = (uid_t)IVAL(pdata,40);
6638 set_grp = (gid_t)IVAL(pdata,48);
6639 raw_unixmode = IVAL(pdata,84);
6641 if (VALID_STAT(smb_fname->st)) {
6642 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6643 ptype = PERM_EXISTING_DIR;
6645 ptype = PERM_EXISTING_FILE;
6648 ptype = PERM_NEW_FILE;
6651 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6653 if (!NT_STATUS_IS_OK(status)) {
6657 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6658 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6659 smb_fname_str_dbg(smb_fname), (double)size,
6660 (unsigned int)set_owner, (unsigned int)set_grp,
6661 (int)raw_unixmode));
6663 sbuf = smb_fname->st;
6665 if (!VALID_STAT(sbuf)) {
6666 struct smb_filename *smb_fname_tmp = NULL;
6668 * The only valid use of this is to create character and block
6669 * devices, and named pipes. This is deprecated (IMHO) and
6670 * a new info level should be used for mknod. JRA.
6673 status = smb_unix_mknod(conn,
6677 if (!NT_STATUS_IS_OK(status)) {
6681 status = copy_smb_filename(talloc_tos(), smb_fname,
6683 if (!NT_STATUS_IS_OK(status)) {
6687 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6688 status = map_nt_error_from_unix(errno);
6689 TALLOC_FREE(smb_fname_tmp);
6690 SMB_VFS_UNLINK(conn, smb_fname);
6694 sbuf = smb_fname_tmp->st;
6695 TALLOC_FREE(smb_fname_tmp);
6697 /* Ensure we don't try and change anything else. */
6698 raw_unixmode = SMB_MODE_NO_CHANGE;
6699 size = get_file_size_stat(&sbuf);
6700 ft.atime = sbuf.st_ex_atime;
6701 ft.mtime = sbuf.st_ex_mtime;
6703 * We continue here as we might want to change the
6706 delete_on_fail = True;
6710 /* Horrible backwards compatibility hack as an old server bug
6711 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6715 size = get_file_size_stat(&sbuf);
6720 * Deal with the UNIX specific mode set.
6723 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6724 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6725 "setting mode 0%o for file %s\n",
6726 (unsigned int)unixmode,
6727 smb_fname_str_dbg(smb_fname)));
6728 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6729 return map_nt_error_from_unix(errno);
6734 * Deal with the UNIX specific uid set.
6737 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6738 (sbuf.st_ex_uid != set_owner)) {
6741 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6742 "changing owner %u for path %s\n",
6743 (unsigned int)set_owner,
6744 smb_fname_str_dbg(smb_fname)));
6746 if (S_ISLNK(sbuf.st_ex_mode)) {
6747 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6748 set_owner, (gid_t)-1);
6750 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6751 set_owner, (gid_t)-1);
6755 status = map_nt_error_from_unix(errno);
6756 if (delete_on_fail) {
6757 SMB_VFS_UNLINK(conn, smb_fname);
6764 * Deal with the UNIX specific gid set.
6767 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6768 (sbuf.st_ex_gid != set_grp)) {
6769 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6770 "changing group %u for file %s\n",
6771 (unsigned int)set_owner,
6772 smb_fname_str_dbg(smb_fname)));
6773 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6775 status = map_nt_error_from_unix(errno);
6776 if (delete_on_fail) {
6777 SMB_VFS_UNLINK(conn, smb_fname);
6783 /* Deal with any size changes. */
6785 status = smb_set_file_size(conn, req,
6790 if (!NT_STATUS_IS_OK(status)) {
6794 /* Deal with any time changes. */
6795 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6796 /* No change, don't cancel anything. */
6800 id = vfs_file_id_from_sbuf(conn, &sbuf);
6801 for(all_fsps = file_find_di_first(id); all_fsps;
6802 all_fsps = file_find_di_next(all_fsps)) {
6804 * We're setting the time explicitly for UNIX.
6805 * Cancel any pending changes over all handles.
6807 all_fsps->update_write_time_on_close = false;
6808 TALLOC_FREE(all_fsps->update_write_time_event);
6812 * Override the "setting_write_time"
6813 * parameter here as it almost does what
6814 * we need. Just remember if we modified
6815 * mtime and send the notify ourselves.
6817 if (null_timespec(ft.mtime)) {
6818 modify_mtime = false;
6821 status = smb_set_file_time(conn,
6827 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6828 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6833 /****************************************************************************
6834 Deal with SMB_SET_FILE_UNIX_INFO2.
6835 ****************************************************************************/
6837 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6838 struct smb_request *req,
6842 const struct smb_filename *smb_fname)
6848 if (total_data < 116) {
6849 return NT_STATUS_INVALID_PARAMETER;
6852 /* Start by setting all the fields that are common between UNIX_BASIC
6855 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6857 if (!NT_STATUS_IS_OK(status)) {
6861 smb_fflags = IVAL(pdata, 108);
6862 smb_fmask = IVAL(pdata, 112);
6864 /* NB: We should only attempt to alter the file flags if the client
6865 * sends a non-zero mask.
6867 if (smb_fmask != 0) {
6868 int stat_fflags = 0;
6870 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6871 smb_fmask, &stat_fflags)) {
6872 /* Client asked to alter a flag we don't understand. */
6873 return NT_STATUS_INVALID_PARAMETER;
6876 if (fsp && fsp->fh->fd != -1) {
6877 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6878 return NT_STATUS_NOT_SUPPORTED;
6880 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
6881 stat_fflags) != 0) {
6882 return map_nt_error_from_unix(errno);
6887 /* XXX: need to add support for changing the create_time here. You
6888 * can do this for paths on Darwin with setattrlist(2). The right way
6889 * to hook this up is probably by extending the VFS utimes interface.
6892 return NT_STATUS_OK;
6895 /****************************************************************************
6896 Create a directory with POSIX semantics.
6897 ****************************************************************************/
6899 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6900 struct smb_request *req,
6903 struct smb_filename *smb_fname,
6904 int *pdata_return_size)
6906 NTSTATUS status = NT_STATUS_OK;
6907 uint32 raw_unixmode = 0;
6908 uint32 mod_unixmode = 0;
6909 mode_t unixmode = (mode_t)0;
6910 files_struct *fsp = NULL;
6911 uint16 info_level_return = 0;
6913 char *pdata = *ppdata;
6915 if (total_data < 18) {
6916 return NT_STATUS_INVALID_PARAMETER;
6919 raw_unixmode = IVAL(pdata,8);
6920 /* Next 4 bytes are not yet defined. */
6922 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6923 PERM_NEW_DIR, &unixmode);
6924 if (!NT_STATUS_IS_OK(status)) {
6928 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6930 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6931 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
6933 status = SMB_VFS_CREATE_FILE(
6936 0, /* root_dir_fid */
6937 smb_fname, /* fname */
6938 FILE_READ_ATTRIBUTES, /* access_mask */
6939 FILE_SHARE_NONE, /* share_access */
6940 FILE_CREATE, /* create_disposition*/
6941 FILE_DIRECTORY_FILE, /* create_options */
6942 mod_unixmode, /* file_attributes */
6943 0, /* oplock_request */
6944 0, /* allocation_size */
6950 if (NT_STATUS_IS_OK(status)) {
6951 close_file(req, fsp, NORMAL_CLOSE);
6954 info_level_return = SVAL(pdata,16);
6956 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6957 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6958 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6959 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6961 *pdata_return_size = 12;
6964 /* Realloc the data size */
6965 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6966 if (*ppdata == NULL) {
6967 *pdata_return_size = 0;
6968 return NT_STATUS_NO_MEMORY;
6972 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6973 SSVAL(pdata,2,0); /* No fnum. */
6974 SIVAL(pdata,4,info); /* Was directory created. */
6976 switch (info_level_return) {
6977 case SMB_QUERY_FILE_UNIX_BASIC:
6978 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6979 SSVAL(pdata,10,0); /* Padding. */
6980 store_file_unix_basic(conn, pdata + 12, fsp,
6983 case SMB_QUERY_FILE_UNIX_INFO2:
6984 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6985 SSVAL(pdata,10,0); /* Padding. */
6986 store_file_unix_basic_info2(conn, pdata + 12, fsp,
6990 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6991 SSVAL(pdata,10,0); /* Padding. */
6998 /****************************************************************************
6999 Open/Create a file with POSIX semantics.
7000 ****************************************************************************/
7002 static NTSTATUS smb_posix_open(connection_struct *conn,
7003 struct smb_request *req,
7006 struct smb_filename *smb_fname,
7007 int *pdata_return_size)
7009 bool extended_oplock_granted = False;
7010 char *pdata = *ppdata;
7012 uint32 wire_open_mode = 0;
7013 uint32 raw_unixmode = 0;
7014 uint32 mod_unixmode = 0;
7015 uint32 create_disp = 0;
7016 uint32 access_mask = 0;
7017 uint32 create_options = 0;
7018 NTSTATUS status = NT_STATUS_OK;
7019 mode_t unixmode = (mode_t)0;
7020 files_struct *fsp = NULL;
7021 int oplock_request = 0;
7023 uint16 info_level_return = 0;
7025 if (total_data < 18) {
7026 return NT_STATUS_INVALID_PARAMETER;
7029 flags = IVAL(pdata,0);
7030 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7031 if (oplock_request) {
7032 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7035 wire_open_mode = IVAL(pdata,4);
7037 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7038 return smb_posix_mkdir(conn, req,
7045 switch (wire_open_mode & SMB_ACCMODE) {
7047 access_mask = FILE_READ_DATA;
7050 access_mask = FILE_WRITE_DATA;
7053 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
7056 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7057 (unsigned int)wire_open_mode ));
7058 return NT_STATUS_INVALID_PARAMETER;
7061 wire_open_mode &= ~SMB_ACCMODE;
7063 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
7064 create_disp = FILE_CREATE;
7065 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
7066 create_disp = FILE_OVERWRITE_IF;
7067 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
7068 create_disp = FILE_OPEN_IF;
7069 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
7070 create_disp = FILE_OPEN;
7072 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7073 (unsigned int)wire_open_mode ));
7074 return NT_STATUS_INVALID_PARAMETER;
7077 raw_unixmode = IVAL(pdata,8);
7078 /* Next 4 bytes are not yet defined. */
7080 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7081 (VALID_STAT(smb_fname->st) ?
7082 PERM_EXISTING_FILE : PERM_NEW_FILE),
7085 if (!NT_STATUS_IS_OK(status)) {
7089 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7091 if (wire_open_mode & SMB_O_SYNC) {
7092 create_options |= FILE_WRITE_THROUGH;
7094 if (wire_open_mode & SMB_O_APPEND) {
7095 access_mask |= FILE_APPEND_DATA;
7097 if (wire_open_mode & SMB_O_DIRECT) {
7098 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7101 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7102 smb_fname_str_dbg(smb_fname),
7103 (unsigned int)wire_open_mode,
7104 (unsigned int)unixmode ));
7106 status = SMB_VFS_CREATE_FILE(
7109 0, /* root_dir_fid */
7110 smb_fname, /* fname */
7111 access_mask, /* access_mask */
7112 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7114 create_disp, /* create_disposition*/
7115 FILE_NON_DIRECTORY_FILE, /* create_options */
7116 mod_unixmode, /* file_attributes */
7117 oplock_request, /* oplock_request */
7118 0, /* allocation_size */
7124 if (!NT_STATUS_IS_OK(status)) {
7128 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7129 extended_oplock_granted = True;
7132 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7133 extended_oplock_granted = True;
7136 info_level_return = SVAL(pdata,16);
7138 /* Allocate the correct return size. */
7140 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7141 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7142 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7143 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7145 *pdata_return_size = 12;
7148 /* Realloc the data size */
7149 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7150 if (*ppdata == NULL) {
7151 close_file(req, fsp, ERROR_CLOSE);
7152 *pdata_return_size = 0;
7153 return NT_STATUS_NO_MEMORY;
7157 if (extended_oplock_granted) {
7158 if (flags & REQUEST_BATCH_OPLOCK) {
7159 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7161 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7163 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7164 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7166 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7169 SSVAL(pdata,2,fsp->fnum);
7170 SIVAL(pdata,4,info); /* Was file created etc. */
7172 switch (info_level_return) {
7173 case SMB_QUERY_FILE_UNIX_BASIC:
7174 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7175 SSVAL(pdata,10,0); /* padding. */
7176 store_file_unix_basic(conn, pdata + 12, fsp,
7179 case SMB_QUERY_FILE_UNIX_INFO2:
7180 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7181 SSVAL(pdata,10,0); /* padding. */
7182 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7186 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7187 SSVAL(pdata,10,0); /* padding. */
7190 return NT_STATUS_OK;
7193 /****************************************************************************
7194 Delete a file with POSIX semantics.
7195 ****************************************************************************/
7197 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7198 struct smb_request *req,
7201 struct smb_filename *smb_fname)
7203 NTSTATUS status = NT_STATUS_OK;
7204 files_struct *fsp = NULL;
7208 int create_options = 0;
7210 struct share_mode_lock *lck = NULL;
7212 if (total_data < 2) {
7213 return NT_STATUS_INVALID_PARAMETER;
7216 flags = SVAL(pdata,0);
7218 if (!VALID_STAT(smb_fname->st)) {
7219 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7222 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7223 !VALID_STAT_OF_DIR(smb_fname->st)) {
7224 return NT_STATUS_NOT_A_DIRECTORY;
7227 DEBUG(10,("smb_posix_unlink: %s %s\n",
7228 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7229 smb_fname_str_dbg(smb_fname)));
7231 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7232 create_options |= FILE_DIRECTORY_FILE;
7235 status = SMB_VFS_CREATE_FILE(
7238 0, /* root_dir_fid */
7239 smb_fname, /* fname */
7240 DELETE_ACCESS, /* access_mask */
7241 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7243 FILE_OPEN, /* create_disposition*/
7244 create_options, /* create_options */
7245 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7246 0, /* oplock_request */
7247 0, /* allocation_size */
7253 if (!NT_STATUS_IS_OK(status)) {
7258 * Don't lie to client. If we can't really delete due to
7259 * non-POSIX opens return SHARING_VIOLATION.
7262 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7265 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7266 "lock for file %s\n", fsp_str_dbg(fsp)));
7267 close_file(req, fsp, NORMAL_CLOSE);
7268 return NT_STATUS_INVALID_PARAMETER;
7272 * See if others still have the file open. If this is the case, then
7273 * don't delete. If all opens are POSIX delete we can set the delete
7274 * on close disposition.
7276 for (i=0; i<lck->num_share_modes; i++) {
7277 struct share_mode_entry *e = &lck->share_modes[i];
7278 if (is_valid_share_mode_entry(e)) {
7279 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7282 /* Fail with sharing violation. */
7283 close_file(req, fsp, NORMAL_CLOSE);
7285 return NT_STATUS_SHARING_VIOLATION;
7290 * Set the delete on close.
7292 status = smb_set_file_disposition_info(conn,
7298 if (!NT_STATUS_IS_OK(status)) {
7299 close_file(req, fsp, NORMAL_CLOSE);
7304 return close_file(req, fsp, NORMAL_CLOSE);
7307 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7308 struct smb_request *req,
7309 TALLOC_CTX *mem_ctx,
7310 uint16_t info_level,
7312 struct smb_filename *smb_fname,
7313 char **ppdata, int total_data,
7316 char *pdata = *ppdata;
7317 NTSTATUS status = NT_STATUS_OK;
7318 int data_return_size = 0;
7322 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7323 return NT_STATUS_INVALID_LEVEL;
7326 if (!CAN_WRITE(conn)) {
7327 /* Allow POSIX opens. The open path will deny
7328 * any non-readonly opens. */
7329 if (info_level != SMB_POSIX_PATH_OPEN) {
7330 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7334 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7335 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7336 fsp ? fsp->fnum : -1, info_level, total_data));
7338 switch (info_level) {
7340 case SMB_INFO_STANDARD:
7342 status = smb_set_info_standard(conn,
7350 case SMB_INFO_SET_EA:
7352 status = smb_info_set_ea(conn,
7360 case SMB_SET_FILE_BASIC_INFO:
7361 case SMB_FILE_BASIC_INFORMATION:
7363 status = smb_set_file_basic_info(conn,
7371 case SMB_FILE_ALLOCATION_INFORMATION:
7372 case SMB_SET_FILE_ALLOCATION_INFO:
7374 status = smb_set_file_allocation_info(conn, req,
7382 case SMB_FILE_END_OF_FILE_INFORMATION:
7383 case SMB_SET_FILE_END_OF_FILE_INFO:
7385 status = smb_set_file_end_of_file_info(conn, req,
7393 case SMB_FILE_DISPOSITION_INFORMATION:
7394 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7397 /* JRA - We used to just ignore this on a path ?
7398 * Shouldn't this be invalid level on a pathname
7401 if (tran_call != TRANSACT2_SETFILEINFO) {
7402 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7405 status = smb_set_file_disposition_info(conn,
7413 case SMB_FILE_POSITION_INFORMATION:
7415 status = smb_file_position_information(conn,
7422 case SMB_FILE_FULL_EA_INFORMATION:
7424 status = smb_set_file_full_ea_info(conn,
7431 /* From tridge Samba4 :
7432 * MODE_INFORMATION in setfileinfo (I have no
7433 * idea what "mode information" on a file is - it takes a value of 0,
7434 * 2, 4 or 6. What could it be?).
7437 case SMB_FILE_MODE_INFORMATION:
7439 status = smb_file_mode_information(conn,
7446 * CIFS UNIX extensions.
7449 case SMB_SET_FILE_UNIX_BASIC:
7451 status = smb_set_file_unix_basic(conn, req,
7459 case SMB_SET_FILE_UNIX_INFO2:
7461 status = smb_set_file_unix_info2(conn, req,
7469 case SMB_SET_FILE_UNIX_LINK:
7472 /* We must have a pathname for this. */
7473 return NT_STATUS_INVALID_LEVEL;
7475 status = smb_set_file_unix_link(conn, req, pdata,
7476 total_data, smb_fname);
7480 case SMB_SET_FILE_UNIX_HLINK:
7483 /* We must have a pathname for this. */
7484 return NT_STATUS_INVALID_LEVEL;
7486 status = smb_set_file_unix_hlink(conn, req,
7492 case SMB_FILE_RENAME_INFORMATION:
7494 status = smb_file_rename_information(conn, req,
7500 #if defined(HAVE_POSIX_ACLS)
7501 case SMB_SET_POSIX_ACL:
7503 status = smb_set_posix_acl(conn,
7512 case SMB_SET_POSIX_LOCK:
7515 return NT_STATUS_INVALID_LEVEL;
7517 status = smb_set_posix_lock(conn, req,
7518 pdata, total_data, fsp);
7522 case SMB_POSIX_PATH_OPEN:
7525 /* We must have a pathname for this. */
7526 return NT_STATUS_INVALID_LEVEL;
7529 status = smb_posix_open(conn, req,
7537 case SMB_POSIX_PATH_UNLINK:
7540 /* We must have a pathname for this. */
7541 return NT_STATUS_INVALID_LEVEL;
7544 status = smb_posix_unlink(conn, req,
7552 return NT_STATUS_INVALID_LEVEL;
7555 if (!NT_STATUS_IS_OK(status)) {
7559 *ret_data_size = data_return_size;
7560 return NT_STATUS_OK;
7563 /****************************************************************************
7564 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7565 ****************************************************************************/
7567 static void call_trans2setfilepathinfo(connection_struct *conn,
7568 struct smb_request *req,
7569 unsigned int tran_call,
7570 char **pparams, int total_params,
7571 char **ppdata, int total_data,
7572 unsigned int max_data_bytes)
7574 char *params = *pparams;
7575 char *pdata = *ppdata;
7577 struct smb_filename *smb_fname = NULL;
7578 files_struct *fsp = NULL;
7579 NTSTATUS status = NT_STATUS_OK;
7580 int data_return_size = 0;
7583 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7587 if (tran_call == TRANSACT2_SETFILEINFO) {
7588 if (total_params < 4) {
7589 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7593 fsp = file_fsp(req, SVAL(params,0));
7594 /* Basic check for non-null fsp. */
7595 if (!check_fsp_open(conn, req, fsp)) {
7598 info_level = SVAL(params,2);
7600 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7602 if (!NT_STATUS_IS_OK(status)) {
7603 reply_nterror(req, status);
7607 if(fsp->is_directory || fsp->fh->fd == -1) {
7609 * This is actually a SETFILEINFO on a directory
7610 * handle (returned from an NT SMB). NT5.0 seems
7611 * to do this call. JRA.
7613 if (INFO_LEVEL_IS_UNIX(info_level)) {
7614 /* Always do lstat for UNIX calls. */
7615 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7616 DEBUG(3,("call_trans2setfilepathinfo: "
7617 "SMB_VFS_LSTAT of %s failed "
7619 smb_fname_str_dbg(smb_fname),
7621 reply_nterror(req, map_nt_error_from_unix(errno));
7625 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7626 DEBUG(3,("call_trans2setfilepathinfo: "
7627 "fileinfo of %s failed (%s)\n",
7628 smb_fname_str_dbg(smb_fname),
7630 reply_nterror(req, map_nt_error_from_unix(errno));
7634 } else if (fsp->print_file) {
7636 * Doing a DELETE_ON_CLOSE should cancel a print job.
7638 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7639 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
7641 DEBUG(3,("call_trans2setfilepathinfo: "
7642 "Cancelling print job (%s)\n",
7646 send_trans2_replies(conn, req, params, 2,
7651 reply_doserror(req, ERRDOS, ERRbadpath);
7656 * Original code - this is an open file.
7658 if (!check_fsp(conn, req, fsp)) {
7662 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7663 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7664 "of fnum %d failed (%s)\n", fsp->fnum,
7666 reply_nterror(req, map_nt_error_from_unix(errno));
7674 if (total_params < 7) {
7675 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7679 info_level = SVAL(params,0);
7680 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
7681 total_params - 6, STR_TERMINATE,
7683 if (!NT_STATUS_IS_OK(status)) {
7684 reply_nterror(req, status);
7688 status = filename_convert(req, conn,
7689 req->flags2 & FLAGS2_DFS_PATHNAMES,
7694 if (!NT_STATUS_IS_OK(status)) {
7695 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7696 reply_botherror(req,
7697 NT_STATUS_PATH_NOT_COVERED,
7698 ERRSRV, ERRbadpath);
7701 reply_nterror(req, status);
7705 if (INFO_LEVEL_IS_UNIX(info_level)) {
7707 * For CIFS UNIX extensions the target name may not exist.
7710 /* Always do lstat for UNIX calls. */
7711 SMB_VFS_LSTAT(conn, smb_fname);
7713 } else if (!VALID_STAT(smb_fname->st) &&
7714 SMB_VFS_STAT(conn, smb_fname)) {
7715 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7717 smb_fname_str_dbg(smb_fname),
7719 reply_nterror(req, map_nt_error_from_unix(errno));
7724 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7725 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
7726 fsp ? fsp->fnum : -1, info_level,total_data));
7728 /* Realloc the parameter size */
7729 *pparams = (char *)SMB_REALLOC(*pparams,2);
7730 if (*pparams == NULL) {
7731 reply_nterror(req, NT_STATUS_NO_MEMORY);
7738 status = smbd_do_setfilepathinfo(conn, req, req,
7744 if (!NT_STATUS_IS_OK(status)) {
7745 if (open_was_deferred(req->mid)) {
7746 /* We have re-scheduled this call. */
7749 if (blocking_lock_was_deferred(req->mid)) {
7750 /* We have re-scheduled this call. */
7753 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7754 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7755 ERRSRV, ERRbadpath);
7758 if (info_level == SMB_POSIX_PATH_OPEN) {
7759 reply_openerror(req, status);
7763 reply_nterror(req, status);
7767 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7773 /****************************************************************************
7774 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7775 ****************************************************************************/
7777 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7778 char **pparams, int total_params,
7779 char **ppdata, int total_data,
7780 unsigned int max_data_bytes)
7782 struct smb_filename *smb_dname = NULL;
7783 char *params = *pparams;
7784 char *pdata = *ppdata;
7785 char *directory = NULL;
7786 NTSTATUS status = NT_STATUS_OK;
7787 struct ea_list *ea_list = NULL;
7788 TALLOC_CTX *ctx = talloc_tos();
7790 if (!CAN_WRITE(conn)) {
7791 reply_doserror(req, ERRSRV, ERRaccess);
7795 if (total_params < 5) {
7796 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7800 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7801 total_params - 4, STR_TERMINATE,
7803 if (!NT_STATUS_IS_OK(status)) {
7804 reply_nterror(req, status);
7808 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7810 status = filename_convert(ctx,
7812 req->flags2 & FLAGS2_DFS_PATHNAMES,
7818 if (!NT_STATUS_IS_OK(status)) {
7819 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7820 reply_botherror(req,
7821 NT_STATUS_PATH_NOT_COVERED,
7822 ERRSRV, ERRbadpath);
7825 reply_nterror(req, status);
7829 /* Any data in this call is an EA list. */
7830 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7831 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7836 * OS/2 workplace shell seems to send SET_EA requests of "null"
7837 * length (4 bytes containing IVAL 4).
7838 * They seem to have no effect. Bug #3212. JRA.
7841 if (total_data != 4) {
7842 if (total_data < 10) {
7843 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7847 if (IVAL(pdata,0) > total_data) {
7848 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7849 IVAL(pdata,0), (unsigned int)total_data));
7850 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7854 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7857 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7861 /* If total_data == 4 Windows doesn't care what values
7862 * are placed in that field, it just ignores them.
7863 * The System i QNTC IBM SMB client puts bad values here,
7864 * so ignore them. */
7866 status = create_directory(conn, req, smb_dname);
7868 if (!NT_STATUS_IS_OK(status)) {
7869 reply_nterror(req, status);
7873 /* Try and set any given EA. */
7875 status = set_ea(conn, NULL, smb_dname, ea_list);
7876 if (!NT_STATUS_IS_OK(status)) {
7877 reply_nterror(req, status);
7882 /* Realloc the parameter and data sizes */
7883 *pparams = (char *)SMB_REALLOC(*pparams,2);
7884 if(*pparams == NULL) {
7885 reply_nterror(req, NT_STATUS_NO_MEMORY);
7892 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7895 TALLOC_FREE(smb_dname);
7899 /****************************************************************************
7900 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7901 We don't actually do this - we just send a null response.
7902 ****************************************************************************/
7904 static void call_trans2findnotifyfirst(connection_struct *conn,
7905 struct smb_request *req,
7906 char **pparams, int total_params,
7907 char **ppdata, int total_data,
7908 unsigned int max_data_bytes)
7910 char *params = *pparams;
7913 if (total_params < 6) {
7914 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7918 info_level = SVAL(params,4);
7919 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7921 switch (info_level) {
7926 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7930 /* Realloc the parameter and data sizes */
7931 *pparams = (char *)SMB_REALLOC(*pparams,6);
7932 if (*pparams == NULL) {
7933 reply_nterror(req, NT_STATUS_NO_MEMORY);
7938 SSVAL(params,0,fnf_handle);
7939 SSVAL(params,2,0); /* No changes */
7940 SSVAL(params,4,0); /* No EA errors */
7947 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7952 /****************************************************************************
7953 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7954 changes). Currently this does nothing.
7955 ****************************************************************************/
7957 static void call_trans2findnotifynext(connection_struct *conn,
7958 struct smb_request *req,
7959 char **pparams, int total_params,
7960 char **ppdata, int total_data,
7961 unsigned int max_data_bytes)
7963 char *params = *pparams;
7965 DEBUG(3,("call_trans2findnotifynext\n"));
7967 /* Realloc the parameter and data sizes */
7968 *pparams = (char *)SMB_REALLOC(*pparams,4);
7969 if (*pparams == NULL) {
7970 reply_nterror(req, NT_STATUS_NO_MEMORY);
7975 SSVAL(params,0,0); /* No changes */
7976 SSVAL(params,2,0); /* No EA errors */
7978 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7983 /****************************************************************************
7984 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7985 ****************************************************************************/
7987 static void call_trans2getdfsreferral(connection_struct *conn,
7988 struct smb_request *req,
7989 char **pparams, int total_params,
7990 char **ppdata, int total_data,
7991 unsigned int max_data_bytes)
7993 char *params = *pparams;
7994 char *pathname = NULL;
7996 int max_referral_level;
7997 NTSTATUS status = NT_STATUS_OK;
7998 TALLOC_CTX *ctx = talloc_tos();
8000 DEBUG(10,("call_trans2getdfsreferral\n"));
8002 if (total_params < 3) {
8003 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8007 max_referral_level = SVAL(params,0);
8009 if(!lp_host_msdfs()) {
8010 reply_doserror(req, ERRDOS, ERRbadfunc);
8014 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
8015 total_params - 2, STR_TERMINATE);
8017 reply_nterror(req, NT_STATUS_NOT_FOUND);
8020 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8021 ppdata,&status)) < 0) {
8022 reply_nterror(req, status);
8026 SSVAL(req->inbuf, smb_flg2,
8027 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8028 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8033 #define LMCAT_SPL 0x53
8034 #define LMFUNC_GETJOBID 0x60
8036 /****************************************************************************
8037 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8038 ****************************************************************************/
8040 static void call_trans2ioctl(connection_struct *conn,
8041 struct smb_request *req,
8042 char **pparams, int total_params,
8043 char **ppdata, int total_data,
8044 unsigned int max_data_bytes)
8046 char *pdata = *ppdata;
8047 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8049 /* check for an invalid fid before proceeding */
8052 reply_doserror(req, ERRDOS, ERRbadfid);
8056 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8057 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8058 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8059 if (*ppdata == NULL) {
8060 reply_nterror(req, NT_STATUS_NO_MEMORY);
8065 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8066 CAN ACCEPT THIS IN UNICODE. JRA. */
8068 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
8069 srvstr_push(pdata, req->flags2, pdata + 2,
8070 global_myname(), 15,
8071 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8072 srvstr_push(pdata, req->flags2, pdata+18,
8073 lp_servicename(SNUM(conn)), 13,
8074 STR_ASCII|STR_TERMINATE); /* Service name */
8075 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8080 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8081 reply_doserror(req, ERRSRV, ERRerror);
8084 /****************************************************************************
8085 Reply to a SMBfindclose (stop trans2 directory search).
8086 ****************************************************************************/
8088 void reply_findclose(struct smb_request *req)
8091 struct smbd_server_connection *sconn = smbd_server_conn;
8093 START_PROFILE(SMBfindclose);
8096 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8097 END_PROFILE(SMBfindclose);
8101 dptr_num = SVALS(req->vwv+0, 0);
8103 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8105 dptr_close(sconn, &dptr_num);
8107 reply_outbuf(req, 0, 0);
8109 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8111 END_PROFILE(SMBfindclose);
8115 /****************************************************************************
8116 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8117 ****************************************************************************/
8119 void reply_findnclose(struct smb_request *req)
8123 START_PROFILE(SMBfindnclose);
8126 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8127 END_PROFILE(SMBfindnclose);
8131 dptr_num = SVAL(req->vwv+0, 0);
8133 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8135 /* We never give out valid handles for a
8136 findnotifyfirst - so any dptr_num is ok here.
8139 reply_outbuf(req, 0, 0);
8141 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8143 END_PROFILE(SMBfindnclose);
8147 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8148 struct trans_state *state)
8150 if (get_Protocol() >= PROTOCOL_NT1) {
8151 req->flags2 |= 0x40; /* IS_LONG_NAME */
8152 SSVAL(req->inbuf,smb_flg2,req->flags2);
8155 if (conn->encrypt_level == Required && !req->encrypted) {
8156 if (state->call != TRANSACT2_QFSINFO &&
8157 state->call != TRANSACT2_SETFSINFO) {
8158 DEBUG(0,("handle_trans2: encryption required "
8160 (unsigned int)state->call));
8161 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8166 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8168 /* Now we must call the relevant TRANS2 function */
8169 switch(state->call) {
8170 case TRANSACT2_OPEN:
8172 START_PROFILE(Trans2_open);
8173 call_trans2open(conn, req,
8174 &state->param, state->total_param,
8175 &state->data, state->total_data,
8176 state->max_data_return);
8177 END_PROFILE(Trans2_open);
8181 case TRANSACT2_FINDFIRST:
8183 START_PROFILE(Trans2_findfirst);
8184 call_trans2findfirst(conn, req,
8185 &state->param, state->total_param,
8186 &state->data, state->total_data,
8187 state->max_data_return);
8188 END_PROFILE(Trans2_findfirst);
8192 case TRANSACT2_FINDNEXT:
8194 START_PROFILE(Trans2_findnext);
8195 call_trans2findnext(conn, req,
8196 &state->param, state->total_param,
8197 &state->data, state->total_data,
8198 state->max_data_return);
8199 END_PROFILE(Trans2_findnext);
8203 case TRANSACT2_QFSINFO:
8205 START_PROFILE(Trans2_qfsinfo);
8206 call_trans2qfsinfo(conn, req,
8207 &state->param, state->total_param,
8208 &state->data, state->total_data,
8209 state->max_data_return);
8210 END_PROFILE(Trans2_qfsinfo);
8214 case TRANSACT2_SETFSINFO:
8216 START_PROFILE(Trans2_setfsinfo);
8217 call_trans2setfsinfo(conn, req,
8218 &state->param, state->total_param,
8219 &state->data, state->total_data,
8220 state->max_data_return);
8221 END_PROFILE(Trans2_setfsinfo);
8225 case TRANSACT2_QPATHINFO:
8226 case TRANSACT2_QFILEINFO:
8228 START_PROFILE(Trans2_qpathinfo);
8229 call_trans2qfilepathinfo(conn, req, state->call,
8230 &state->param, state->total_param,
8231 &state->data, state->total_data,
8232 state->max_data_return);
8233 END_PROFILE(Trans2_qpathinfo);
8237 case TRANSACT2_SETPATHINFO:
8238 case TRANSACT2_SETFILEINFO:
8240 START_PROFILE(Trans2_setpathinfo);
8241 call_trans2setfilepathinfo(conn, req, state->call,
8242 &state->param, state->total_param,
8243 &state->data, state->total_data,
8244 state->max_data_return);
8245 END_PROFILE(Trans2_setpathinfo);
8249 case TRANSACT2_FINDNOTIFYFIRST:
8251 START_PROFILE(Trans2_findnotifyfirst);
8252 call_trans2findnotifyfirst(conn, req,
8253 &state->param, state->total_param,
8254 &state->data, state->total_data,
8255 state->max_data_return);
8256 END_PROFILE(Trans2_findnotifyfirst);
8260 case TRANSACT2_FINDNOTIFYNEXT:
8262 START_PROFILE(Trans2_findnotifynext);
8263 call_trans2findnotifynext(conn, req,
8264 &state->param, state->total_param,
8265 &state->data, state->total_data,
8266 state->max_data_return);
8267 END_PROFILE(Trans2_findnotifynext);
8271 case TRANSACT2_MKDIR:
8273 START_PROFILE(Trans2_mkdir);
8274 call_trans2mkdir(conn, req,
8275 &state->param, state->total_param,
8276 &state->data, state->total_data,
8277 state->max_data_return);
8278 END_PROFILE(Trans2_mkdir);
8282 case TRANSACT2_GET_DFS_REFERRAL:
8284 START_PROFILE(Trans2_get_dfs_referral);
8285 call_trans2getdfsreferral(conn, req,
8286 &state->param, state->total_param,
8287 &state->data, state->total_data,
8288 state->max_data_return);
8289 END_PROFILE(Trans2_get_dfs_referral);
8293 case TRANSACT2_IOCTL:
8295 START_PROFILE(Trans2_ioctl);
8296 call_trans2ioctl(conn, req,
8297 &state->param, state->total_param,
8298 &state->data, state->total_data,
8299 state->max_data_return);
8300 END_PROFILE(Trans2_ioctl);
8305 /* Error in request */
8306 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8307 reply_doserror(req, ERRSRV,ERRerror);
8311 /****************************************************************************
8312 Reply to a SMBtrans2.
8313 ****************************************************************************/
8315 void reply_trans2(struct smb_request *req)
8317 connection_struct *conn = req->conn;
8322 unsigned int tran_call;
8323 struct trans_state *state;
8326 START_PROFILE(SMBtrans2);
8328 if (req->wct < 14) {
8329 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8330 END_PROFILE(SMBtrans2);
8334 dsoff = SVAL(req->vwv+12, 0);
8335 dscnt = SVAL(req->vwv+11, 0);
8336 psoff = SVAL(req->vwv+10, 0);
8337 pscnt = SVAL(req->vwv+9, 0);
8338 tran_call = SVAL(req->vwv+14, 0);
8340 result = allow_new_trans(conn->pending_trans, req->mid);
8341 if (!NT_STATUS_IS_OK(result)) {
8342 DEBUG(2, ("Got invalid trans2 request: %s\n",
8343 nt_errstr(result)));
8344 reply_nterror(req, result);
8345 END_PROFILE(SMBtrans2);
8350 switch (tran_call) {
8351 /* List the allowed trans2 calls on IPC$ */
8352 case TRANSACT2_OPEN:
8353 case TRANSACT2_GET_DFS_REFERRAL:
8354 case TRANSACT2_QFILEINFO:
8355 case TRANSACT2_QFSINFO:
8356 case TRANSACT2_SETFSINFO:
8359 reply_doserror(req, ERRSRV, ERRaccess);
8360 END_PROFILE(SMBtrans2);
8365 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8366 DEBUG(0, ("talloc failed\n"));
8367 reply_nterror(req, NT_STATUS_NO_MEMORY);
8368 END_PROFILE(SMBtrans2);
8372 state->cmd = SMBtrans2;
8374 state->mid = req->mid;
8375 state->vuid = req->vuid;
8376 state->setup_count = SVAL(req->vwv+13, 0);
8377 state->setup = NULL;
8378 state->total_param = SVAL(req->vwv+0, 0);
8379 state->param = NULL;
8380 state->total_data = SVAL(req->vwv+1, 0);
8382 state->max_param_return = SVAL(req->vwv+2, 0);
8383 state->max_data_return = SVAL(req->vwv+3, 0);
8384 state->max_setup_return = SVAL(req->vwv+4, 0);
8385 state->close_on_completion = BITSETW(req->vwv+5, 0);
8386 state->one_way = BITSETW(req->vwv+5, 1);
8388 state->call = tran_call;
8390 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8391 is so as a sanity check */
8392 if (state->setup_count != 1) {
8394 * Need to have rc=0 for ioctl to get job id for OS/2.
8395 * Network printing will fail if function is not successful.
8396 * Similar function in reply.c will be used if protocol
8397 * is LANMAN1.0 instead of LM1.2X002.
8398 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8399 * outbuf doesn't have to be set(only job id is used).
8401 if ( (state->setup_count == 4)
8402 && (tran_call == TRANSACT2_IOCTL)
8403 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8404 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8405 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8407 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8408 DEBUG(2,("Transaction is %d\n",tran_call));
8410 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8411 END_PROFILE(SMBtrans2);
8416 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8419 if (state->total_data) {
8421 if (trans_oob(state->total_data, 0, dscnt)
8422 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8426 /* Can't use talloc here, the core routines do realloc on the
8427 * params and data. */
8428 state->data = (char *)SMB_MALLOC(state->total_data);
8429 if (state->data == NULL) {
8430 DEBUG(0,("reply_trans2: data malloc fail for %u "
8431 "bytes !\n", (unsigned int)state->total_data));
8433 reply_nterror(req, NT_STATUS_NO_MEMORY);
8434 END_PROFILE(SMBtrans2);
8438 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8441 if (state->total_param) {
8443 if (trans_oob(state->total_param, 0, pscnt)
8444 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8448 /* Can't use talloc here, the core routines do realloc on the
8449 * params and data. */
8450 state->param = (char *)SMB_MALLOC(state->total_param);
8451 if (state->param == NULL) {
8452 DEBUG(0,("reply_trans: param malloc fail for %u "
8453 "bytes !\n", (unsigned int)state->total_param));
8454 SAFE_FREE(state->data);
8456 reply_nterror(req, NT_STATUS_NO_MEMORY);
8457 END_PROFILE(SMBtrans2);
8461 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8464 state->received_data = dscnt;
8465 state->received_param = pscnt;
8467 if ((state->received_param == state->total_param) &&
8468 (state->received_data == state->total_data)) {
8470 handle_trans2(conn, req, state);
8472 SAFE_FREE(state->data);
8473 SAFE_FREE(state->param);
8475 END_PROFILE(SMBtrans2);
8479 DLIST_ADD(conn->pending_trans, state);
8481 /* We need to send an interim response then receive the rest
8482 of the parameter/data bytes */
8483 reply_outbuf(req, 0, 0);
8484 show_msg((char *)req->outbuf);
8485 END_PROFILE(SMBtrans2);
8490 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8491 SAFE_FREE(state->data);
8492 SAFE_FREE(state->param);
8494 END_PROFILE(SMBtrans2);
8495 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8499 /****************************************************************************
8500 Reply to a SMBtranss2
8501 ****************************************************************************/
8503 void reply_transs2(struct smb_request *req)
8505 connection_struct *conn = req->conn;
8506 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8507 struct trans_state *state;
8509 START_PROFILE(SMBtranss2);
8511 show_msg((char *)req->inbuf);
8514 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8515 END_PROFILE(SMBtranss2);
8519 for (state = conn->pending_trans; state != NULL;
8520 state = state->next) {
8521 if (state->mid == req->mid) {
8526 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8527 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8528 END_PROFILE(SMBtranss2);
8532 /* Revise state->total_param and state->total_data in case they have
8533 changed downwards */
8535 if (SVAL(req->vwv+0, 0) < state->total_param)
8536 state->total_param = SVAL(req->vwv+0, 0);
8537 if (SVAL(req->vwv+1, 0) < state->total_data)
8538 state->total_data = SVAL(req->vwv+1, 0);
8540 pcnt = SVAL(req->vwv+2, 0);
8541 poff = SVAL(req->vwv+3, 0);
8542 pdisp = SVAL(req->vwv+4, 0);
8544 dcnt = SVAL(req->vwv+5, 0);
8545 doff = SVAL(req->vwv+6, 0);
8546 ddisp = SVAL(req->vwv+7, 0);
8548 state->received_param += pcnt;
8549 state->received_data += dcnt;
8551 if ((state->received_data > state->total_data) ||
8552 (state->received_param > state->total_param))
8556 if (trans_oob(state->total_param, pdisp, pcnt)
8557 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8560 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8564 if (trans_oob(state->total_data, ddisp, dcnt)
8565 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8568 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8571 if ((state->received_param < state->total_param) ||
8572 (state->received_data < state->total_data)) {
8573 END_PROFILE(SMBtranss2);
8577 handle_trans2(conn, req, state);
8579 DLIST_REMOVE(conn->pending_trans, state);
8580 SAFE_FREE(state->data);
8581 SAFE_FREE(state->param);
8584 END_PROFILE(SMBtranss2);
8589 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8590 DLIST_REMOVE(conn->pending_trans, state);
8591 SAFE_FREE(state->data);
8592 SAFE_FREE(state->param);
8594 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8595 END_PROFILE(SMBtranss2);