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,
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_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
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_nterror(req, NT_STATUS_ACCESS_DENIED);
1062 /* Any data in this call is an EA list. */
1063 if (total_data && (total_data != 4)) {
1064 if (total_data < 10) {
1065 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1069 if (IVAL(pdata,0) > total_data) {
1070 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1071 IVAL(pdata,0), (unsigned int)total_data));
1072 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1076 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1079 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1083 if (!lp_ea_support(SNUM(conn))) {
1084 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1089 status = SMB_VFS_CREATE_FILE(
1092 0, /* root_dir_fid */
1093 smb_fname, /* fname */
1094 access_mask, /* access_mask */
1095 share_mode, /* share_access */
1096 create_disposition, /* create_disposition*/
1097 create_options, /* create_options */
1098 open_attr, /* file_attributes */
1099 oplock_request, /* oplock_request */
1100 open_size, /* allocation_size */
1102 ea_list, /* ea_list */
1104 &smb_action); /* psbuf */
1106 if (!NT_STATUS_IS_OK(status)) {
1107 if (open_was_deferred(req->mid)) {
1108 /* We have re-scheduled this call. */
1111 reply_openerror(req, status);
1115 size = get_file_size_stat(&smb_fname->st);
1116 fattr = dos_mode(conn, smb_fname);
1117 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1118 inode = smb_fname->st.st_ex_ino;
1120 close_file(req, fsp, ERROR_CLOSE);
1121 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1125 /* Realloc the size of parameters and data we will return */
1126 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1127 if(*pparams == NULL ) {
1128 reply_nterror(req, NT_STATUS_NO_MEMORY);
1133 SSVAL(params,0,fsp->fnum);
1134 SSVAL(params,2,fattr);
1135 srv_put_dos_date2(params,4, mtime);
1136 SIVAL(params,8, (uint32)size);
1137 SSVAL(params,12,deny_mode);
1138 SSVAL(params,14,0); /* open_type - file or directory. */
1139 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1141 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1142 smb_action |= EXTENDED_OPLOCK_GRANTED;
1145 SSVAL(params,18,smb_action);
1148 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1150 SIVAL(params,20,inode);
1151 SSVAL(params,24,0); /* Padding. */
1153 uint32 ea_size = estimate_ea_size(conn, fsp,
1154 fsp->fsp_name->base_name);
1155 SIVAL(params, 26, ea_size);
1157 SIVAL(params, 26, 0);
1160 /* Send the required number of replies */
1161 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1163 TALLOC_FREE(smb_fname);
1166 /*********************************************************
1167 Routine to check if a given string matches exactly.
1168 as a special case a mask of "." does NOT match. That
1169 is required for correct wildcard semantics
1170 Case can be significant or not.
1171 **********************************************************/
1173 static bool exact_match(bool has_wild,
1174 bool case_sensitive,
1178 if (mask[0] == '.' && mask[1] == 0) {
1186 if (case_sensitive) {
1187 return strcmp(str,mask)==0;
1189 return StrCaseCmp(str,mask) == 0;
1193 /****************************************************************************
1194 Return the filetype for UNIX extensions.
1195 ****************************************************************************/
1197 static uint32 unix_filetype(mode_t mode)
1200 return UNIX_TYPE_FILE;
1201 else if(S_ISDIR(mode))
1202 return UNIX_TYPE_DIR;
1204 else if(S_ISLNK(mode))
1205 return UNIX_TYPE_SYMLINK;
1208 else if(S_ISCHR(mode))
1209 return UNIX_TYPE_CHARDEV;
1212 else if(S_ISBLK(mode))
1213 return UNIX_TYPE_BLKDEV;
1216 else if(S_ISFIFO(mode))
1217 return UNIX_TYPE_FIFO;
1220 else if(S_ISSOCK(mode))
1221 return UNIX_TYPE_SOCKET;
1224 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1225 return UNIX_TYPE_UNKNOWN;
1228 /****************************************************************************
1229 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1230 ****************************************************************************/
1232 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1234 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1235 const SMB_STRUCT_STAT *psbuf,
1237 enum perm_type ptype,
1242 if (perms == SMB_MODE_NO_CHANGE) {
1243 if (!VALID_STAT(*psbuf)) {
1244 return NT_STATUS_INVALID_PARAMETER;
1246 *ret_perms = psbuf->st_ex_mode;
1247 return NT_STATUS_OK;
1251 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1252 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1253 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1254 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1255 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1256 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1257 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1258 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1259 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1261 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1264 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1267 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1272 /* Apply mode mask */
1273 ret &= lp_create_mask(SNUM(conn));
1274 /* Add in force bits */
1275 ret |= lp_force_create_mode(SNUM(conn));
1278 ret &= lp_dir_mask(SNUM(conn));
1279 /* Add in force bits */
1280 ret |= lp_force_dir_mode(SNUM(conn));
1282 case PERM_EXISTING_FILE:
1283 /* Apply mode mask */
1284 ret &= lp_security_mask(SNUM(conn));
1285 /* Add in force bits */
1286 ret |= lp_force_security_mode(SNUM(conn));
1288 case PERM_EXISTING_DIR:
1289 /* Apply mode mask */
1290 ret &= lp_dir_security_mask(SNUM(conn));
1291 /* Add in force bits */
1292 ret |= lp_force_dir_security_mode(SNUM(conn));
1297 return NT_STATUS_OK;
1300 /****************************************************************************
1301 Needed to show the msdfs symlinks as directories. Modifies psbuf
1302 to be a directory if it's a msdfs link.
1303 ****************************************************************************/
1305 static bool check_msdfs_link(connection_struct *conn,
1306 const char *pathname,
1307 SMB_STRUCT_STAT *psbuf)
1309 int saved_errno = errno;
1310 if(lp_host_msdfs() &&
1311 lp_msdfs_root(SNUM(conn)) &&
1312 is_msdfs_link(conn, pathname, psbuf)) {
1314 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1317 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1318 errno = saved_errno;
1321 errno = saved_errno;
1326 /****************************************************************************
1327 Get a level dependent lanman2 dir entry.
1328 ****************************************************************************/
1330 struct smbd_dirptr_lanman2_state {
1331 connection_struct *conn;
1332 uint32_t info_level;
1333 bool check_mangled_names;
1335 bool got_exact_match;
1338 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1344 struct smbd_dirptr_lanman2_state *state =
1345 (struct smbd_dirptr_lanman2_state *)private_data;
1347 char mangled_name[13]; /* mangled 8.3 name. */
1351 /* Mangle fname if it's an illegal name. */
1352 if (mangle_must_mangle(dname, state->conn->params)) {
1353 ok = name_to_8_3(dname, mangled_name,
1354 true, state->conn->params);
1358 fname = mangled_name;
1363 got_match = exact_match(state->has_wild,
1364 state->conn->case_sensitive,
1366 state->got_exact_match = got_match;
1368 got_match = mask_match(fname, mask,
1369 state->conn->case_sensitive);
1372 if(!got_match && state->check_mangled_names &&
1373 !mangle_is_8_3(fname, false, state->conn->params)) {
1375 * It turns out that NT matches wildcards against
1376 * both long *and* short names. This may explain some
1377 * of the wildcard wierdness from old DOS clients
1378 * that some people have been seeing.... JRA.
1380 /* Force the mangling into 8.3. */
1381 ok = name_to_8_3(fname, mangled_name,
1382 false, state->conn->params);
1387 got_match = exact_match(state->has_wild,
1388 state->conn->case_sensitive,
1389 mangled_name, mask);
1390 state->got_exact_match = got_match;
1392 got_match = mask_match(mangled_name, mask,
1393 state->conn->case_sensitive);
1401 *_fname = talloc_strdup(ctx, fname);
1402 if (*_fname == NULL) {
1409 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1411 struct smb_filename *smb_fname,
1414 struct smbd_dirptr_lanman2_state *state =
1415 (struct smbd_dirptr_lanman2_state *)private_data;
1416 bool ms_dfs_link = false;
1419 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1420 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1421 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1422 "Couldn't lstat [%s] (%s)\n",
1423 smb_fname_str_dbg(smb_fname),
1427 } else if (!VALID_STAT(smb_fname->st) &&
1428 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1429 /* Needed to show the msdfs symlinks as
1432 ms_dfs_link = check_msdfs_link(state->conn,
1433 smb_fname->base_name,
1436 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1437 "Couldn't stat [%s] (%s)\n",
1438 smb_fname_str_dbg(smb_fname),
1445 mode = dos_mode_msdfs(state->conn, smb_fname);
1447 mode = dos_mode(state->conn, smb_fname);
1454 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1455 connection_struct *conn,
1457 uint32_t info_level,
1458 struct ea_list *name_list,
1459 bool check_mangled_names,
1460 bool requires_resume_key,
1463 const struct smb_filename *smb_fname,
1464 uint64_t space_remaining,
1471 uint64_t *last_entry_off)
1473 char *p, *q, *pdata = *ppdata;
1475 uint64_t file_size = 0;
1476 uint64_t allocation_size = 0;
1478 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1479 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1480 time_t c_date = (time_t)0;
1482 char *last_entry_ptr;
1487 *out_of_space = false;
1489 ZERO_STRUCT(mdate_ts);
1490 ZERO_STRUCT(adate_ts);
1491 ZERO_STRUCT(create_date_ts);
1492 ZERO_STRUCT(cdate_ts);
1494 if (!(mode & aDIR)) {
1495 file_size = get_file_size_stat(&smb_fname->st);
1497 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1499 mdate_ts = smb_fname->st.st_ex_mtime;
1500 adate_ts = smb_fname->st.st_ex_atime;
1501 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1502 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1504 if (lp_dos_filetime_resolution(SNUM(conn))) {
1505 dos_filetime_timespec(&create_date_ts);
1506 dos_filetime_timespec(&mdate_ts);
1507 dos_filetime_timespec(&adate_ts);
1508 dos_filetime_timespec(&cdate_ts);
1511 create_date = convert_timespec_to_time_t(create_date_ts);
1512 mdate = convert_timespec_to_time_t(mdate_ts);
1513 adate = convert_timespec_to_time_t(adate_ts);
1514 c_date = convert_timespec_to_time_t(cdate_ts);
1516 /* align the record */
1517 off = PTR_DIFF(pdata, base_data);
1518 pad = (off + (align-1)) & ~(align-1);
1521 /* initialize padding to 0 */
1523 memset(pdata, 0, pad);
1525 space_remaining -= pad;
1534 switch (info_level) {
1535 case SMB_FIND_INFO_STANDARD:
1536 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1537 if(requires_resume_key) {
1541 srv_put_dos_date2(p,0,create_date);
1542 srv_put_dos_date2(p,4,adate);
1543 srv_put_dos_date2(p,8,mdate);
1544 SIVAL(p,12,(uint32)file_size);
1545 SIVAL(p,16,(uint32)allocation_size);
1549 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1550 p += ucs2_align(base_data, p, 0);
1552 len = srvstr_push(base_data, flags2, p,
1553 fname, PTR_DIFF(end_data, p),
1555 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1557 SCVAL(nameptr, -1, len - 2);
1559 SCVAL(nameptr, -1, 0);
1563 SCVAL(nameptr, -1, len - 1);
1565 SCVAL(nameptr, -1, 0);
1571 case SMB_FIND_EA_SIZE:
1572 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1573 if (requires_resume_key) {
1577 srv_put_dos_date2(p,0,create_date);
1578 srv_put_dos_date2(p,4,adate);
1579 srv_put_dos_date2(p,8,mdate);
1580 SIVAL(p,12,(uint32)file_size);
1581 SIVAL(p,16,(uint32)allocation_size);
1584 unsigned int ea_size = estimate_ea_size(conn, NULL,
1585 smb_fname->base_name);
1586 SIVAL(p,22,ea_size); /* Extended attributes */
1590 len = srvstr_push(base_data, flags2,
1591 p, fname, PTR_DIFF(end_data, p),
1592 STR_TERMINATE | STR_NOALIGN);
1593 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1606 SCVAL(nameptr,0,len);
1608 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1611 case SMB_FIND_EA_LIST:
1613 struct ea_list *file_list = NULL;
1616 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1620 if (requires_resume_key) {
1624 srv_put_dos_date2(p,0,create_date);
1625 srv_put_dos_date2(p,4,adate);
1626 srv_put_dos_date2(p,8,mdate);
1627 SIVAL(p,12,(uint32)file_size);
1628 SIVAL(p,16,(uint32)allocation_size);
1630 p += 22; /* p now points to the EA area. */
1632 file_list = get_ea_list_from_file(ctx, conn, NULL,
1633 smb_fname->base_name,
1635 name_list = ea_list_union(name_list, file_list, &ea_len);
1637 /* We need to determine if this entry will fit in the space available. */
1638 /* Max string size is 255 bytes. */
1639 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1640 *out_of_space = true;
1641 DEBUG(9,("smbd_marshall_dir_entry: out of space\n"));
1642 return False; /* Not finished - just out of space */
1645 /* Push the ea_data followed by the name. */
1646 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1648 len = srvstr_push(base_data, flags2,
1649 p + 1, fname, PTR_DIFF(end_data, p+1),
1650 STR_TERMINATE | STR_NOALIGN);
1651 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1664 SCVAL(nameptr,0,len);
1666 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1670 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1671 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1672 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1674 SIVAL(p,0,reskey); p += 4;
1675 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1676 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1677 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1678 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1679 SOFF_T(p,0,file_size); p += 8;
1680 SOFF_T(p,0,allocation_size); p += 8;
1681 SIVAL(p,0,mode); p += 4;
1682 q = p; p += 4; /* q is placeholder for name length. */
1684 unsigned int ea_size = estimate_ea_size(conn, NULL,
1685 smb_fname->base_name);
1686 SIVAL(p,0,ea_size); /* Extended attributes */
1689 /* Clear the short name buffer. This is
1690 * IMPORTANT as not doing so will trigger
1691 * a Win2k client bug. JRA.
1693 if (!was_8_3 && check_mangled_names) {
1694 char mangled_name[13]; /* mangled 8.3 name. */
1695 if (!name_to_8_3(fname,mangled_name,True,
1697 /* Error - mangle failed ! */
1698 memset(mangled_name,'\0',12);
1700 mangled_name[12] = 0;
1701 len = srvstr_push(base_data, flags2,
1702 p+2, mangled_name, 24,
1703 STR_UPPER|STR_UNICODE);
1705 memset(p + 2 + len,'\0',24 - len);
1712 len = srvstr_push(base_data, flags2, p,
1713 fname, PTR_DIFF(end_data, p),
1714 STR_TERMINATE_ASCII);
1718 len = PTR_DIFF(p, pdata);
1719 pad = (len + (align-1)) & ~(align-1);
1721 * offset to the next entry, the caller
1722 * will overwrite it for the last entry
1723 * that's why we always include the padding
1727 * set padding to zero
1730 memset(p, 0, pad - len);
1737 case SMB_FIND_FILE_DIRECTORY_INFO:
1738 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1740 SIVAL(p,0,reskey); p += 4;
1741 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1742 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1743 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1744 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1745 SOFF_T(p,0,file_size); p += 8;
1746 SOFF_T(p,0,allocation_size); p += 8;
1747 SIVAL(p,0,mode); p += 4;
1748 len = srvstr_push(base_data, flags2,
1749 p + 4, fname, PTR_DIFF(end_data, p+4),
1750 STR_TERMINATE_ASCII);
1754 len = PTR_DIFF(p, pdata);
1755 pad = (len + (align-1)) & ~(align-1);
1757 * offset to the next entry, the caller
1758 * will overwrite it for the last entry
1759 * that's why we always include the padding
1763 * set padding to zero
1766 memset(p, 0, pad - len);
1773 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1774 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1776 SIVAL(p,0,reskey); p += 4;
1777 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1778 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1779 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1780 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1781 SOFF_T(p,0,file_size); p += 8;
1782 SOFF_T(p,0,allocation_size); p += 8;
1783 SIVAL(p,0,mode); p += 4;
1784 q = p; p += 4; /* q is placeholder for name length. */
1786 unsigned int ea_size = estimate_ea_size(conn, NULL,
1787 smb_fname->base_name);
1788 SIVAL(p,0,ea_size); /* Extended attributes */
1791 len = srvstr_push(base_data, flags2, p,
1792 fname, PTR_DIFF(end_data, p),
1793 STR_TERMINATE_ASCII);
1797 len = PTR_DIFF(p, pdata);
1798 pad = (len + (align-1)) & ~(align-1);
1800 * offset to the next entry, the caller
1801 * will overwrite it for the last entry
1802 * that's why we always include the padding
1806 * set padding to zero
1809 memset(p, 0, pad - len);
1816 case SMB_FIND_FILE_NAMES_INFO:
1817 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1819 SIVAL(p,0,reskey); p += 4;
1821 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1822 acl on a dir (tridge) */
1823 len = srvstr_push(base_data, flags2, p,
1824 fname, PTR_DIFF(end_data, p),
1825 STR_TERMINATE_ASCII);
1829 len = PTR_DIFF(p, pdata);
1830 pad = (len + (align-1)) & ~(align-1);
1832 * offset to the next entry, the caller
1833 * will overwrite it for the last entry
1834 * that's why we always include the padding
1838 * set padding to zero
1841 memset(p, 0, pad - len);
1848 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1849 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1851 SIVAL(p,0,reskey); p += 4;
1852 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1853 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1854 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1855 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1856 SOFF_T(p,0,file_size); p += 8;
1857 SOFF_T(p,0,allocation_size); p += 8;
1858 SIVAL(p,0,mode); p += 4;
1859 q = p; p += 4; /* q is placeholder for name length. */
1861 unsigned int ea_size = estimate_ea_size(conn, NULL,
1862 smb_fname->base_name);
1863 SIVAL(p,0,ea_size); /* Extended attributes */
1866 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1867 SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
1868 SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
1869 len = srvstr_push(base_data, flags2, p,
1870 fname, PTR_DIFF(end_data, p),
1871 STR_TERMINATE_ASCII);
1875 len = PTR_DIFF(p, pdata);
1876 pad = (len + (align-1)) & ~(align-1);
1878 * offset to the next entry, the caller
1879 * will overwrite it for the last entry
1880 * that's why we always include the padding
1884 * set padding to zero
1887 memset(p, 0, pad - len);
1894 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1895 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1896 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1898 SIVAL(p,0,reskey); p += 4;
1899 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1900 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1901 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1902 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1903 SOFF_T(p,0,file_size); p += 8;
1904 SOFF_T(p,0,allocation_size); p += 8;
1905 SIVAL(p,0,mode); p += 4;
1906 q = p; p += 4; /* q is placeholder for name length */
1908 unsigned int ea_size = estimate_ea_size(conn, NULL,
1909 smb_fname->base_name);
1910 SIVAL(p,0,ea_size); /* Extended attributes */
1913 /* Clear the short name buffer. This is
1914 * IMPORTANT as not doing so will trigger
1915 * a Win2k client bug. JRA.
1917 if (!was_8_3 && check_mangled_names) {
1918 char mangled_name[13]; /* mangled 8.3 name. */
1919 if (!name_to_8_3(fname,mangled_name,True,
1921 /* Error - mangle failed ! */
1922 memset(mangled_name,'\0',12);
1924 mangled_name[12] = 0;
1925 len = srvstr_push(base_data, flags2,
1926 p+2, mangled_name, 24,
1927 STR_UPPER|STR_UNICODE);
1930 memset(p + 2 + len,'\0',24 - len);
1937 SSVAL(p,0,0); p += 2; /* Reserved ? */
1938 SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
1939 SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
1940 len = srvstr_push(base_data, flags2, p,
1941 fname, PTR_DIFF(end_data, p),
1942 STR_TERMINATE_ASCII);
1946 len = PTR_DIFF(p, pdata);
1947 pad = (len + (align-1)) & ~(align-1);
1949 * offset to the next entry, the caller
1950 * will overwrite it for the last entry
1951 * that's why we always include the padding
1955 * set padding to zero
1958 memset(p, 0, pad - len);
1965 /* CIFS UNIX Extension. */
1967 case SMB_FIND_FILE_UNIX:
1968 case SMB_FIND_FILE_UNIX_INFO2:
1970 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1972 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1974 if (info_level == SMB_FIND_FILE_UNIX) {
1975 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
1976 p = store_file_unix_basic(conn, p,
1977 NULL, &smb_fname->st);
1978 len = srvstr_push(base_data, flags2, p,
1979 fname, PTR_DIFF(end_data, p),
1982 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1983 p = store_file_unix_basic_info2(conn, p,
1984 NULL, &smb_fname->st);
1987 len = srvstr_push(base_data, flags2, p, fname,
1988 PTR_DIFF(end_data, p), 0);
1989 SIVAL(nameptr, 0, len);
1994 len = PTR_DIFF(p, pdata);
1995 pad = (len + (align-1)) & ~(align-1);
1997 * offset to the next entry, the caller
1998 * will overwrite it for the last entry
1999 * that's why we always include the padding
2003 * set padding to zero
2006 memset(p, 0, pad - len);
2011 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2019 if (PTR_DIFF(p,pdata) > space_remaining) {
2020 *out_of_space = true;
2021 DEBUG(9,("smbd_marshall_dir_entry: out of space\n"));
2022 return false; /* Not finished - just out of space */
2025 /* Setup the last entry pointer, as an offset from base_data */
2026 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2027 /* Advance the data pointer to the next slot */
2033 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2034 connection_struct *conn,
2035 struct dptr_struct *dirptr,
2037 const char *path_mask,
2040 int requires_resume_key,
2048 int space_remaining,
2050 bool *got_exact_match,
2051 int *_last_entry_off,
2052 struct ea_list *name_list)
2055 const char *mask = NULL;
2056 long prev_dirpos = 0;
2059 struct smb_filename *smb_fname = NULL;
2060 struct smbd_dirptr_lanman2_state state;
2062 uint64_t last_entry_off = 0;
2066 state.info_level = info_level;
2067 state.check_mangled_names = lp_manglednames(conn->params);
2068 state.has_wild = dptr_has_wild(dirptr);
2069 state.got_exact_match = false;
2071 *out_of_space = false;
2072 *got_exact_match = false;
2074 p = strrchr_m(path_mask,'/');
2085 ok = smbd_dirptr_get_entry(ctx,
2091 smbd_dirptr_lanman2_match_fn,
2092 smbd_dirptr_lanman2_mode_fn,
2102 *got_exact_match = state.got_exact_match;
2104 ok = smbd_marshall_dir_entry(ctx,
2109 state.check_mangled_names,
2110 requires_resume_key,
2123 TALLOC_FREE(smb_fname);
2124 if (*out_of_space) {
2125 dptr_SeekDir(dirptr, prev_dirpos);
2132 *_last_entry_off = last_entry_off;
2136 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2137 connection_struct *conn,
2138 struct dptr_struct *dirptr,
2140 const char *path_mask,
2143 bool requires_resume_key,
2149 int space_remaining,
2151 bool *got_exact_match,
2152 int *last_entry_off,
2153 struct ea_list *name_list)
2156 const bool do_pad = true;
2158 if (info_level >= 1 && info_level <= 3) {
2159 /* No alignment on earlier info levels. */
2163 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2164 path_mask, dirtype, info_level,
2165 requires_resume_key, dont_descend, ask_sharemode,
2167 ppdata, base_data, end_data,
2169 out_of_space, got_exact_match,
2170 last_entry_off, name_list);
2173 /****************************************************************************
2174 Reply to a TRANS2_FINDFIRST.
2175 ****************************************************************************/
2177 static void call_trans2findfirst(connection_struct *conn,
2178 struct smb_request *req,
2179 char **pparams, int total_params,
2180 char **ppdata, int total_data,
2181 unsigned int max_data_bytes)
2183 /* We must be careful here that we don't return more than the
2184 allowed number of data bytes. If this means returning fewer than
2185 maxentries then so be it. We assume that the redirector has
2186 enough room for the fixed number of parameter bytes it has
2188 struct smb_filename *smb_dname = NULL;
2189 char *params = *pparams;
2190 char *pdata = *ppdata;
2194 uint16 findfirst_flags;
2195 bool close_after_first;
2197 bool requires_resume_key;
2199 char *directory = NULL;
2202 int last_entry_off=0;
2206 bool finished = False;
2207 bool dont_descend = False;
2208 bool out_of_space = False;
2209 int space_remaining;
2210 bool mask_contains_wcard = False;
2211 struct ea_list *ea_list = NULL;
2212 NTSTATUS ntstatus = NT_STATUS_OK;
2213 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2214 TALLOC_CTX *ctx = talloc_tos();
2215 struct dptr_struct *dirptr = NULL;
2216 struct smbd_server_connection *sconn = smbd_server_conn;
2218 if (total_params < 13) {
2219 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2223 dirtype = SVAL(params,0);
2224 maxentries = SVAL(params,2);
2225 findfirst_flags = SVAL(params,4);
2226 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2227 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2228 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2229 info_level = SVAL(params,6);
2231 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2232 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2233 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2234 info_level, max_data_bytes));
2237 /* W2K3 seems to treat zero as 1. */
2241 switch (info_level) {
2242 case SMB_FIND_INFO_STANDARD:
2243 case SMB_FIND_EA_SIZE:
2244 case SMB_FIND_EA_LIST:
2245 case SMB_FIND_FILE_DIRECTORY_INFO:
2246 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2247 case SMB_FIND_FILE_NAMES_INFO:
2248 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2249 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2250 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2252 case SMB_FIND_FILE_UNIX:
2253 case SMB_FIND_FILE_UNIX_INFO2:
2254 /* Always use filesystem for UNIX mtime query. */
2255 ask_sharemode = false;
2256 if (!lp_unix_extensions()) {
2257 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2262 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2266 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2267 params+12, total_params - 12,
2268 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2269 if (!NT_STATUS_IS_OK(ntstatus)) {
2270 reply_nterror(req, ntstatus);
2274 ntstatus = filename_convert(ctx, conn,
2275 req->flags2 & FLAGS2_DFS_PATHNAMES,
2278 UCF_ALWAYS_ALLOW_WCARD_LCOMP),
2279 &mask_contains_wcard,
2281 if (!NT_STATUS_IS_OK(ntstatus)) {
2282 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2283 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2284 ERRSRV, ERRbadpath);
2287 reply_nterror(req, ntstatus);
2291 mask = smb_dname->original_lcomp;
2293 directory = smb_dname->base_name;
2295 p = strrchr_m(directory,'/');
2297 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2298 if((directory[0] == '.') && (directory[1] == '\0')) {
2299 mask = talloc_strdup(ctx,"*");
2301 reply_nterror(req, NT_STATUS_NO_MEMORY);
2304 mask_contains_wcard = True;
2306 directory = talloc_strdup(talloc_tos(), "./");
2308 reply_nterror(req, NT_STATUS_NO_MEMORY);
2315 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2317 if (info_level == SMB_FIND_EA_LIST) {
2320 if (total_data < 4) {
2321 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2325 ea_size = IVAL(pdata,0);
2326 if (ea_size != total_data) {
2327 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2328 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2329 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2333 if (!lp_ea_support(SNUM(conn))) {
2334 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2338 /* Pull out the list of names. */
2339 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2341 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2346 *ppdata = (char *)SMB_REALLOC(
2347 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2348 if(*ppdata == NULL ) {
2349 reply_nterror(req, NT_STATUS_NO_MEMORY);
2353 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2355 /* Realloc the params space */
2356 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2357 if (*pparams == NULL) {
2358 reply_nterror(req, NT_STATUS_NO_MEMORY);
2363 /* Save the wildcard match and attribs we are using on this directory -
2364 needed as lanman2 assumes these are being saved between calls */
2366 ntstatus = dptr_create(conn,
2372 mask_contains_wcard,
2376 if (!NT_STATUS_IS_OK(ntstatus)) {
2377 reply_nterror(req, ntstatus);
2381 dptr_num = dptr_dnum(dirptr);
2382 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2384 /* Initialize per TRANS2_FIND_FIRST operation data */
2385 dptr_init_search_op(dirptr);
2387 /* We don't need to check for VOL here as this is returned by
2388 a different TRANS2 call. */
2390 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2391 directory,lp_dontdescend(SNUM(conn))));
2392 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2393 dont_descend = True;
2396 space_remaining = max_data_bytes;
2397 out_of_space = False;
2399 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2400 bool got_exact_match = False;
2402 /* this is a heuristic to avoid seeking the dirptr except when
2403 absolutely necessary. It allows for a filename of about 40 chars */
2404 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2405 out_of_space = True;
2408 finished = !get_lanman2_dir_entry(ctx,
2412 mask,dirtype,info_level,
2413 requires_resume_key,dont_descend,
2416 space_remaining, &out_of_space,
2418 &last_entry_off, ea_list);
2421 if (finished && out_of_space)
2424 if (!finished && !out_of_space)
2428 * As an optimisation if we know we aren't looking
2429 * for a wildcard name (ie. the name matches the wildcard exactly)
2430 * then we can finish on any (first) match.
2431 * This speeds up large directory searches. JRA.
2437 /* Ensure space_remaining never goes -ve. */
2438 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2439 space_remaining = 0;
2440 out_of_space = true;
2442 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2446 /* Check if we can close the dirptr */
2447 if(close_after_first || (finished && close_if_end)) {
2448 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2449 dptr_close(sconn, &dptr_num);
2453 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2454 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2455 * the protocol level is less than NT1. Tested with smbclient. JRA.
2456 * This should fix the OS/2 client bug #2335.
2459 if(numentries == 0) {
2460 dptr_close(sconn, &dptr_num);
2461 if (get_Protocol() < PROTOCOL_NT1) {
2462 reply_force_doserror(req, ERRDOS, ERRnofiles);
2465 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2466 ERRDOS, ERRbadfile);
2471 /* At this point pdata points to numentries directory entries. */
2473 /* Set up the return parameter block */
2474 SSVAL(params,0,dptr_num);
2475 SSVAL(params,2,numentries);
2476 SSVAL(params,4,finished);
2477 SSVAL(params,6,0); /* Never an EA error */
2478 SSVAL(params,8,last_entry_off);
2480 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2483 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2484 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2486 reply_nterror(req, NT_STATUS_NO_MEMORY);
2490 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2491 smb_fn_name(req->cmd),
2492 mask, directory, dirtype, numentries ) );
2495 * Force a name mangle here to ensure that the
2496 * mask as an 8.3 name is top of the mangled cache.
2497 * The reasons for this are subtle. Don't remove
2498 * this code unless you know what you are doing
2499 * (see PR#13758). JRA.
2502 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2503 char mangled_name[13];
2504 name_to_8_3(mask, mangled_name, True, conn->params);
2507 TALLOC_FREE(smb_dname);
2511 /****************************************************************************
2512 Reply to a TRANS2_FINDNEXT.
2513 ****************************************************************************/
2515 static void call_trans2findnext(connection_struct *conn,
2516 struct smb_request *req,
2517 char **pparams, int total_params,
2518 char **ppdata, int total_data,
2519 unsigned int max_data_bytes)
2521 /* We must be careful here that we don't return more than the
2522 allowed number of data bytes. If this means returning fewer than
2523 maxentries then so be it. We assume that the redirector has
2524 enough room for the fixed number of parameter bytes it has
2526 char *params = *pparams;
2527 char *pdata = *ppdata;
2533 uint16 findnext_flags;
2534 bool close_after_request;
2536 bool requires_resume_key;
2538 bool mask_contains_wcard = False;
2539 char *resume_name = NULL;
2540 const char *mask = NULL;
2541 const char *directory = NULL;
2545 int i, last_entry_off=0;
2546 bool finished = False;
2547 bool dont_descend = False;
2548 bool out_of_space = False;
2549 int space_remaining;
2550 struct ea_list *ea_list = NULL;
2551 NTSTATUS ntstatus = NT_STATUS_OK;
2552 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2553 TALLOC_CTX *ctx = talloc_tos();
2554 struct dptr_struct *dirptr;
2555 struct smbd_server_connection *sconn = smbd_server_conn;
2557 if (total_params < 13) {
2558 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2562 dptr_num = SVAL(params,0);
2563 maxentries = SVAL(params,2);
2564 info_level = SVAL(params,4);
2565 resume_key = IVAL(params,6);
2566 findnext_flags = SVAL(params,10);
2567 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2568 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2569 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2570 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2572 if (!continue_bit) {
2573 /* We only need resume_name if continue_bit is zero. */
2574 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2576 total_params - 12, STR_TERMINATE, &ntstatus,
2577 &mask_contains_wcard);
2578 if (!NT_STATUS_IS_OK(ntstatus)) {
2579 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2580 complain (it thinks we're asking for the directory above the shared
2581 path or an invalid name). Catch this as the resume name is only compared, never used in
2582 a file access. JRA. */
2583 srvstr_pull_talloc(ctx, params, req->flags2,
2584 &resume_name, params+12,
2588 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2589 reply_nterror(req, ntstatus);
2595 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2596 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2597 resume_key = %d resume name = %s continue=%d level = %d\n",
2598 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2599 requires_resume_key, resume_key,
2600 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2603 /* W2K3 seems to treat zero as 1. */
2607 switch (info_level) {
2608 case SMB_FIND_INFO_STANDARD:
2609 case SMB_FIND_EA_SIZE:
2610 case SMB_FIND_EA_LIST:
2611 case SMB_FIND_FILE_DIRECTORY_INFO:
2612 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2613 case SMB_FIND_FILE_NAMES_INFO:
2614 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2615 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2616 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2618 case SMB_FIND_FILE_UNIX:
2619 case SMB_FIND_FILE_UNIX_INFO2:
2620 /* Always use filesystem for UNIX mtime query. */
2621 ask_sharemode = false;
2622 if (!lp_unix_extensions()) {
2623 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2628 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2632 if (info_level == SMB_FIND_EA_LIST) {
2635 if (total_data < 4) {
2636 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2640 ea_size = IVAL(pdata,0);
2641 if (ea_size != total_data) {
2642 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2643 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2644 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2648 if (!lp_ea_support(SNUM(conn))) {
2649 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2653 /* Pull out the list of names. */
2654 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2656 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2661 *ppdata = (char *)SMB_REALLOC(
2662 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2663 if(*ppdata == NULL) {
2664 reply_nterror(req, NT_STATUS_NO_MEMORY);
2669 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2671 /* Realloc the params space */
2672 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2673 if(*pparams == NULL ) {
2674 reply_nterror(req, NT_STATUS_NO_MEMORY);
2680 /* Check that the dptr is valid */
2681 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2682 reply_nterror(req, STATUS_NO_MORE_FILES);
2686 directory = dptr_path(sconn, dptr_num);
2688 /* Get the wildcard mask from the dptr */
2689 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2690 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2691 reply_nterror(req, STATUS_NO_MORE_FILES);
2697 /* Get the attr mask from the dptr */
2698 dirtype = dptr_attr(sconn, dptr_num);
2700 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2701 dptr_num, mask, dirtype,
2703 dptr_TellDir(dirptr)));
2705 /* Initialize per TRANS2_FIND_NEXT operation data */
2706 dptr_init_search_op(dirptr);
2708 /* We don't need to check for VOL here as this is returned by
2709 a different TRANS2 call. */
2711 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2712 directory,lp_dontdescend(SNUM(conn))));
2713 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2714 dont_descend = True;
2717 space_remaining = max_data_bytes;
2718 out_of_space = False;
2721 * Seek to the correct position. We no longer use the resume key but
2722 * depend on the last file name instead.
2725 if(!continue_bit && resume_name && *resume_name) {
2728 long current_pos = 0;
2730 * Remember, name_to_8_3 is called by
2731 * get_lanman2_dir_entry(), so the resume name
2732 * could be mangled. Ensure we check the unmangled name.
2735 if (mangle_is_mangled(resume_name, conn->params)) {
2736 char *new_resume_name = NULL;
2737 mangle_lookup_name_from_8_3(ctx,
2741 if (new_resume_name) {
2742 resume_name = new_resume_name;
2747 * Fix for NT redirector problem triggered by resume key indexes
2748 * changing between directory scans. We now return a resume key of 0
2749 * and instead look for the filename to continue from (also given
2750 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2751 * findfirst/findnext (as is usual) then the directory pointer
2752 * should already be at the correct place.
2755 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
2756 } /* end if resume_name && !continue_bit */
2758 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2759 bool got_exact_match = False;
2761 /* this is a heuristic to avoid seeking the dirptr except when
2762 absolutely necessary. It allows for a filename of about 40 chars */
2763 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2764 out_of_space = True;
2767 finished = !get_lanman2_dir_entry(ctx,
2771 mask,dirtype,info_level,
2772 requires_resume_key,dont_descend,
2775 space_remaining, &out_of_space,
2777 &last_entry_off, ea_list);
2780 if (finished && out_of_space)
2783 if (!finished && !out_of_space)
2787 * As an optimisation if we know we aren't looking
2788 * for a wildcard name (ie. the name matches the wildcard exactly)
2789 * then we can finish on any (first) match.
2790 * This speeds up large directory searches. JRA.
2796 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2799 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2800 smb_fn_name(req->cmd),
2801 mask, directory, dirtype, numentries ) );
2803 /* Check if we can close the dirptr */
2804 if(close_after_request || (finished && close_if_end)) {
2805 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2806 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2809 /* Set up the return parameter block */
2810 SSVAL(params,0,numentries);
2811 SSVAL(params,2,finished);
2812 SSVAL(params,4,0); /* Never an EA error */
2813 SSVAL(params,6,last_entry_off);
2815 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2821 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2823 E_md4hash(lp_servicename(SNUM(conn)),objid);
2827 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2829 SMB_ASSERT(extended_info != NULL);
2831 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2832 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2833 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2834 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2835 #ifdef SAMBA_VERSION_REVISION
2836 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2838 extended_info->samba_subversion = 0;
2839 #ifdef SAMBA_VERSION_RC_RELEASE
2840 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2842 #ifdef SAMBA_VERSION_PRE_RELEASE
2843 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2846 #ifdef SAMBA_VERSION_VENDOR_PATCH
2847 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2849 extended_info->samba_gitcommitdate = 0;
2850 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2851 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2854 memset(extended_info->samba_version_string, 0,
2855 sizeof(extended_info->samba_version_string));
2857 snprintf (extended_info->samba_version_string,
2858 sizeof(extended_info->samba_version_string),
2859 "%s", samba_version_string());
2862 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2863 TALLOC_CTX *mem_ctx,
2864 uint16_t info_level,
2866 unsigned int max_data_bytes,
2870 char *pdata, *end_data;
2871 int data_len = 0, len;
2872 const char *vname = volume_label(SNUM(conn));
2873 int snum = SNUM(conn);
2874 char *fstype = lp_fstype(SNUM(conn));
2875 uint32 additional_flags = 0;
2876 struct smb_filename smb_fname_dot;
2880 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2881 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2882 "info level (0x%x) on IPC$.\n",
2883 (unsigned int)info_level));
2884 return NT_STATUS_ACCESS_DENIED;
2888 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2890 ZERO_STRUCT(smb_fname_dot);
2891 smb_fname_dot.base_name = discard_const_p(char, ".");
2893 if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
2894 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2895 return map_nt_error_from_unix(errno);
2898 st = smb_fname_dot.st;
2900 *ppdata = (char *)SMB_REALLOC(
2901 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2902 if (*ppdata == NULL) {
2903 return NT_STATUS_NO_MEMORY;
2907 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2908 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2910 switch (info_level) {
2911 case SMB_INFO_ALLOCATION:
2913 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2915 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2916 return map_nt_error_from_unix(errno);
2919 block_size = lp_block_size(snum);
2920 if (bsize < block_size) {
2921 uint64_t factor = block_size/bsize;
2926 if (bsize > block_size) {
2927 uint64_t factor = bsize/block_size;
2932 bytes_per_sector = 512;
2933 sectors_per_unit = bsize/bytes_per_sector;
2935 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2936 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2937 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2939 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2940 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2941 SIVAL(pdata,l1_cUnit,dsize);
2942 SIVAL(pdata,l1_cUnitAvail,dfree);
2943 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2947 case SMB_INFO_VOLUME:
2948 /* Return volume name */
2950 * Add volume serial number - hash of a combination of
2951 * the called hostname and the service name.
2953 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2955 * Win2k3 and previous mess this up by sending a name length
2956 * one byte short. I believe only older clients (OS/2 Win9x) use
2957 * this call so try fixing this by adding a terminating null to
2958 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2962 pdata+l2_vol_szVolLabel, vname,
2963 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2964 STR_NOALIGN|STR_TERMINATE);
2965 SCVAL(pdata,l2_vol_cch,len);
2966 data_len = l2_vol_szVolLabel + len;
2967 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
2968 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2972 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2973 case SMB_FS_ATTRIBUTE_INFORMATION:
2975 additional_flags = 0;
2976 #if defined(HAVE_SYS_QUOTAS)
2977 additional_flags |= FILE_VOLUME_QUOTAS;
2980 if(lp_nt_acl_support(SNUM(conn))) {
2981 additional_flags |= FILE_PERSISTENT_ACLS;
2984 /* Capabilities are filled in at connection time through STATVFS call */
2985 additional_flags |= conn->fs_capabilities;
2986 additional_flags |= lp_parm_int(conn->params->service,
2987 "share", "fake_fscaps",
2990 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2991 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2992 additional_flags); /* FS ATTRIBUTES */
2994 SIVAL(pdata,4,255); /* Max filename component length */
2995 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2996 and will think we can't do long filenames */
2997 len = srvstr_push(pdata, flags2, pdata+12, fstype,
2998 PTR_DIFF(end_data, pdata+12),
3001 data_len = 12 + len;
3004 case SMB_QUERY_FS_LABEL_INFO:
3005 case SMB_FS_LABEL_INFORMATION:
3006 len = srvstr_push(pdata, flags2, pdata+4, vname,
3007 PTR_DIFF(end_data, pdata+4), 0);
3012 case SMB_QUERY_FS_VOLUME_INFO:
3013 case SMB_FS_VOLUME_INFORMATION:
3016 * Add volume serial number - hash of a combination of
3017 * the called hostname and the service name.
3019 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3020 (str_checksum(get_local_machine_name())<<16));
3022 /* Max label len is 32 characters. */
3023 len = srvstr_push(pdata, flags2, pdata+18, vname,
3024 PTR_DIFF(end_data, pdata+18),
3026 SIVAL(pdata,12,len);
3029 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3030 (int)strlen(vname),vname, lp_servicename(snum)));
3033 case SMB_QUERY_FS_SIZE_INFO:
3034 case SMB_FS_SIZE_INFORMATION:
3036 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3038 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3039 return map_nt_error_from_unix(errno);
3041 block_size = lp_block_size(snum);
3042 if (bsize < block_size) {
3043 uint64_t factor = block_size/bsize;
3048 if (bsize > block_size) {
3049 uint64_t factor = bsize/block_size;
3054 bytes_per_sector = 512;
3055 sectors_per_unit = bsize/bytes_per_sector;
3056 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3057 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3058 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3059 SBIG_UINT(pdata,0,dsize);
3060 SBIG_UINT(pdata,8,dfree);
3061 SIVAL(pdata,16,sectors_per_unit);
3062 SIVAL(pdata,20,bytes_per_sector);
3066 case SMB_FS_FULL_SIZE_INFORMATION:
3068 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3070 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3071 return map_nt_error_from_unix(errno);
3073 block_size = lp_block_size(snum);
3074 if (bsize < block_size) {
3075 uint64_t factor = block_size/bsize;
3080 if (bsize > block_size) {
3081 uint64_t factor = bsize/block_size;
3086 bytes_per_sector = 512;
3087 sectors_per_unit = bsize/bytes_per_sector;
3088 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3089 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3090 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3091 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3092 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3093 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3094 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3095 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3099 case SMB_QUERY_FS_DEVICE_INFO:
3100 case SMB_FS_DEVICE_INFORMATION:
3102 SIVAL(pdata,0,0); /* dev type */
3103 SIVAL(pdata,4,0); /* characteristics */
3106 #ifdef HAVE_SYS_QUOTAS
3107 case SMB_FS_QUOTA_INFORMATION:
3109 * what we have to send --metze:
3111 * Unknown1: 24 NULL bytes
3112 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3113 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3114 * Quota Flags: 2 byte :
3115 * Unknown3: 6 NULL bytes
3119 * details for Quota Flags:
3121 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3122 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3123 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3124 * 0x0001 Enable Quotas: enable quota for this fs
3128 /* we need to fake up a fsp here,
3129 * because its not send in this call
3132 SMB_NTQUOTA_STRUCT quotas;
3135 ZERO_STRUCT(quotas);
3141 if (conn->server_info->utok.uid != sec_initial_uid()) {
3142 DEBUG(0,("set_user_quota: access_denied "
3143 "service [%s] user [%s]\n",
3144 lp_servicename(SNUM(conn)),
3145 conn->server_info->unix_name));
3146 return NT_STATUS_ACCESS_DENIED;
3149 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3150 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3151 return map_nt_error_from_unix(errno);
3156 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3157 lp_servicename(SNUM(conn))));
3159 /* Unknown1 24 NULL bytes*/
3160 SBIG_UINT(pdata,0,(uint64_t)0);
3161 SBIG_UINT(pdata,8,(uint64_t)0);
3162 SBIG_UINT(pdata,16,(uint64_t)0);
3164 /* Default Soft Quota 8 bytes */
3165 SBIG_UINT(pdata,24,quotas.softlim);
3167 /* Default Hard Quota 8 bytes */
3168 SBIG_UINT(pdata,32,quotas.hardlim);
3170 /* Quota flag 2 bytes */
3171 SSVAL(pdata,40,quotas.qflags);
3173 /* Unknown3 6 NULL bytes */
3179 #endif /* HAVE_SYS_QUOTAS */
3180 case SMB_FS_OBJECTID_INFORMATION:
3182 unsigned char objid[16];
3183 struct smb_extended_info extended_info;
3184 memcpy(pdata,create_volume_objectid(conn, objid),16);
3185 samba_extended_info_version (&extended_info);
3186 SIVAL(pdata,16,extended_info.samba_magic);
3187 SIVAL(pdata,20,extended_info.samba_version);
3188 SIVAL(pdata,24,extended_info.samba_subversion);
3189 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3190 memcpy(pdata+36,extended_info.samba_version_string,28);
3196 * Query the version and capabilities of the CIFS UNIX extensions
3200 case SMB_QUERY_CIFS_UNIX_INFO:
3202 bool large_write = lp_min_receive_file_size() &&
3203 !srv_is_signing_active(smbd_server_conn);
3204 bool large_read = !srv_is_signing_active(smbd_server_conn);
3205 int encrypt_caps = 0;
3207 if (!lp_unix_extensions()) {
3208 return NT_STATUS_INVALID_LEVEL;
3211 switch (conn->encrypt_level) {
3217 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3220 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3221 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3222 large_write = false;
3228 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3229 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3231 /* We have POSIX ACLs, pathname, encryption,
3232 * large read/write, and locking capability. */
3234 SBIG_UINT(pdata,4,((uint64_t)(
3235 CIFS_UNIX_POSIX_ACLS_CAP|
3236 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3237 CIFS_UNIX_FCNTL_LOCKS_CAP|
3238 CIFS_UNIX_EXTATTR_CAP|
3239 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3241 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3243 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3247 case SMB_QUERY_POSIX_FS_INFO:
3250 vfs_statvfs_struct svfs;
3252 if (!lp_unix_extensions()) {
3253 return NT_STATUS_INVALID_LEVEL;
3256 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3260 SIVAL(pdata,0,svfs.OptimalTransferSize);
3261 SIVAL(pdata,4,svfs.BlockSize);
3262 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3263 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3264 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3265 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3266 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3267 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3268 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3270 } else if (rc == EOPNOTSUPP) {
3271 return NT_STATUS_INVALID_LEVEL;
3272 #endif /* EOPNOTSUPP */
3274 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3275 return NT_STATUS_DOS(ERRSRV, ERRerror);
3280 case SMB_QUERY_POSIX_WHOAMI:
3286 if (!lp_unix_extensions()) {
3287 return NT_STATUS_INVALID_LEVEL;
3290 if (max_data_bytes < 40) {
3291 return NT_STATUS_BUFFER_TOO_SMALL;
3294 /* We ARE guest if global_sid_Builtin_Guests is
3295 * in our list of SIDs.
3297 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3298 conn->server_info->ptok)) {
3299 flags |= SMB_WHOAMI_GUEST;
3302 /* We are NOT guest if global_sid_Authenticated_Users
3303 * is in our list of SIDs.
3305 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3306 conn->server_info->ptok)) {
3307 flags &= ~SMB_WHOAMI_GUEST;
3310 /* NOTE: 8 bytes for UID/GID, irrespective of native
3311 * platform size. This matches
3312 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3314 data_len = 4 /* flags */
3321 + 4 /* pad/reserved */
3322 + (conn->server_info->utok.ngroups * 8)
3324 + (conn->server_info->ptok->num_sids *
3328 SIVAL(pdata, 0, flags);
3329 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3331 (uint64_t)conn->server_info->utok.uid);
3332 SBIG_UINT(pdata, 16,
3333 (uint64_t)conn->server_info->utok.gid);
3336 if (data_len >= max_data_bytes) {
3337 /* Potential overflow, skip the GIDs and SIDs. */
3339 SIVAL(pdata, 24, 0); /* num_groups */
3340 SIVAL(pdata, 28, 0); /* num_sids */
3341 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3342 SIVAL(pdata, 36, 0); /* reserved */
3348 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3349 SIVAL(pdata, 28, conn->server_info->num_sids);
3351 /* We walk the SID list twice, but this call is fairly
3352 * infrequent, and I don't expect that it's performance
3353 * sensitive -- jpeach
3355 for (i = 0, sid_bytes = 0;
3356 i < conn->server_info->ptok->num_sids; ++i) {
3357 sid_bytes += ndr_size_dom_sid(
3358 &conn->server_info->ptok->user_sids[i],
3363 /* SID list byte count */
3364 SIVAL(pdata, 32, sid_bytes);
3366 /* 4 bytes pad/reserved - must be zero */
3367 SIVAL(pdata, 36, 0);
3371 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3372 SBIG_UINT(pdata, data_len,
3373 (uint64_t)conn->server_info->utok.groups[i]);
3379 i < conn->server_info->ptok->num_sids; ++i) {
3380 int sid_len = ndr_size_dom_sid(
3381 &conn->server_info->ptok->user_sids[i],
3385 sid_linearize(pdata + data_len, sid_len,
3386 &conn->server_info->ptok->user_sids[i]);
3387 data_len += sid_len;
3393 case SMB_MAC_QUERY_FS_INFO:
3395 * Thursby MAC extension... ONLY on NTFS filesystems
3396 * once we do streams then we don't need this
3398 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3400 SIVAL(pdata,84,0x100); /* Don't support mac... */
3405 return NT_STATUS_INVALID_LEVEL;
3408 *ret_data_len = data_len;
3409 return NT_STATUS_OK;
3412 /****************************************************************************
3413 Reply to a TRANS2_QFSINFO (query filesystem info).
3414 ****************************************************************************/
3416 static void call_trans2qfsinfo(connection_struct *conn,
3417 struct smb_request *req,
3418 char **pparams, int total_params,
3419 char **ppdata, int total_data,
3420 unsigned int max_data_bytes)
3422 char *params = *pparams;
3423 uint16_t info_level;
3427 if (total_params < 2) {
3428 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3432 info_level = SVAL(params,0);
3434 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3435 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3436 DEBUG(0,("call_trans2qfsinfo: encryption required "
3437 "and info level 0x%x sent.\n",
3438 (unsigned int)info_level));
3439 exit_server_cleanly("encryption required "
3445 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3447 status = smbd_do_qfsinfo(conn, req,
3452 if (!NT_STATUS_IS_OK(status)) {
3453 reply_nterror(req, status);
3457 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3460 DEBUG( 4, ( "%s info_level = %d\n",
3461 smb_fn_name(req->cmd), info_level) );
3466 /****************************************************************************
3467 Reply to a TRANS2_SETFSINFO (set filesystem info).
3468 ****************************************************************************/
3470 static void call_trans2setfsinfo(connection_struct *conn,
3471 struct smb_request *req,
3472 char **pparams, int total_params,
3473 char **ppdata, int total_data,
3474 unsigned int max_data_bytes)
3476 char *pdata = *ppdata;
3477 char *params = *pparams;
3480 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3483 if (total_params < 4) {
3484 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3486 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3490 info_level = SVAL(params,2);
3493 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3494 info_level != SMB_SET_CIFS_UNIX_INFO) {
3495 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3496 "info level (0x%x) on IPC$.\n",
3497 (unsigned int)info_level));
3498 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3503 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3504 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3505 DEBUG(0,("call_trans2setfsinfo: encryption required "
3506 "and info level 0x%x sent.\n",
3507 (unsigned int)info_level));
3508 exit_server_cleanly("encryption required "
3514 switch(info_level) {
3515 case SMB_SET_CIFS_UNIX_INFO:
3517 uint16 client_unix_major;
3518 uint16 client_unix_minor;
3519 uint32 client_unix_cap_low;
3520 uint32 client_unix_cap_high;
3522 if (!lp_unix_extensions()) {
3524 NT_STATUS_INVALID_LEVEL);
3528 /* There should be 12 bytes of capabilities set. */
3529 if (total_data < 8) {
3532 NT_STATUS_INVALID_PARAMETER);
3535 client_unix_major = SVAL(pdata,0);
3536 client_unix_minor = SVAL(pdata,2);
3537 client_unix_cap_low = IVAL(pdata,4);
3538 client_unix_cap_high = IVAL(pdata,8);
3539 /* Just print these values for now. */
3540 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3541 cap_low = 0x%x, cap_high = 0x%x\n",
3542 (unsigned int)client_unix_major,
3543 (unsigned int)client_unix_minor,
3544 (unsigned int)client_unix_cap_low,
3545 (unsigned int)client_unix_cap_high ));
3547 /* Here is where we must switch to posix pathname processing... */
3548 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3549 lp_set_posix_pathnames();
3550 mangle_change_to_posix();
3553 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3554 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3555 /* Client that knows how to do posix locks,
3556 * but not posix open/mkdir operations. Set a
3557 * default type for read/write checks. */
3559 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3565 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3568 size_t param_len = 0;
3569 size_t data_len = total_data;
3571 if (!lp_unix_extensions()) {
3574 NT_STATUS_INVALID_LEVEL);
3578 if (lp_smb_encrypt(SNUM(conn)) == false) {
3581 NT_STATUS_NOT_SUPPORTED);
3585 DEBUG( 4,("call_trans2setfsinfo: "
3586 "request transport encryption.\n"));
3588 status = srv_request_encryption_setup(conn,
3589 (unsigned char **)ppdata,
3591 (unsigned char **)pparams,
3594 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3595 !NT_STATUS_IS_OK(status)) {
3596 reply_nterror(req, status);
3600 send_trans2_replies(conn, req,
3607 if (NT_STATUS_IS_OK(status)) {
3608 /* Server-side transport
3609 * encryption is now *on*. */
3610 status = srv_encryption_start(conn);
3611 if (!NT_STATUS_IS_OK(status)) {
3612 exit_server_cleanly(
3613 "Failure in setting "
3614 "up encrypted transport");
3620 case SMB_FS_QUOTA_INFORMATION:
3622 files_struct *fsp = NULL;
3623 SMB_NTQUOTA_STRUCT quotas;
3625 ZERO_STRUCT(quotas);
3628 if ((conn->server_info->utok.uid != sec_initial_uid())
3629 ||!CAN_WRITE(conn)) {
3630 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3631 lp_servicename(SNUM(conn)),
3632 conn->server_info->unix_name));
3633 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3637 /* note: normaly there're 48 bytes,
3638 * but we didn't use the last 6 bytes for now
3641 fsp = file_fsp(req, SVAL(params,0));
3643 if (!check_fsp_ntquota_handle(conn, req,
3645 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3647 req, NT_STATUS_INVALID_HANDLE);
3651 if (total_data < 42) {
3652 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3656 NT_STATUS_INVALID_PARAMETER);
3660 /* unknown_1 24 NULL bytes in pdata*/
3662 /* the soft quotas 8 bytes (uint64_t)*/
3663 quotas.softlim = (uint64_t)IVAL(pdata,24);
3664 #ifdef LARGE_SMB_OFF_T
3665 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3666 #else /* LARGE_SMB_OFF_T */
3667 if ((IVAL(pdata,28) != 0)&&
3668 ((quotas.softlim != 0xFFFFFFFF)||
3669 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3670 /* more than 32 bits? */
3673 NT_STATUS_INVALID_PARAMETER);
3676 #endif /* LARGE_SMB_OFF_T */
3678 /* the hard quotas 8 bytes (uint64_t)*/
3679 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3680 #ifdef LARGE_SMB_OFF_T
3681 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3682 #else /* LARGE_SMB_OFF_T */
3683 if ((IVAL(pdata,36) != 0)&&
3684 ((quotas.hardlim != 0xFFFFFFFF)||
3685 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3686 /* more than 32 bits? */
3689 NT_STATUS_INVALID_PARAMETER);
3692 #endif /* LARGE_SMB_OFF_T */
3694 /* quota_flags 2 bytes **/
3695 quotas.qflags = SVAL(pdata,40);
3697 /* unknown_2 6 NULL bytes follow*/
3699 /* now set the quotas */
3700 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3701 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3702 reply_nterror(req, map_nt_error_from_unix(errno));
3709 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3711 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3717 * sending this reply works fine,
3718 * but I'm not sure it's the same
3719 * like windows do...
3722 reply_outbuf(req, 10, 0);
3725 #if defined(HAVE_POSIX_ACLS)
3726 /****************************************************************************
3727 Utility function to count the number of entries in a POSIX acl.
3728 ****************************************************************************/
3730 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3732 unsigned int ace_count = 0;
3733 int entry_id = SMB_ACL_FIRST_ENTRY;
3734 SMB_ACL_ENTRY_T entry;
3736 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3738 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3739 entry_id = SMB_ACL_NEXT_ENTRY;
3746 /****************************************************************************
3747 Utility function to marshall a POSIX acl into wire format.
3748 ****************************************************************************/
3750 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3752 int entry_id = SMB_ACL_FIRST_ENTRY;
3753 SMB_ACL_ENTRY_T entry;
3755 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3756 SMB_ACL_TAG_T tagtype;
3757 SMB_ACL_PERMSET_T permset;
3758 unsigned char perms = 0;
3759 unsigned int own_grp;
3762 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3763 entry_id = SMB_ACL_NEXT_ENTRY;
3766 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3767 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3771 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3772 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3776 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3777 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3778 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3780 SCVAL(pdata,1,perms);
3783 case SMB_ACL_USER_OBJ:
3784 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3785 own_grp = (unsigned int)pst->st_ex_uid;
3786 SIVAL(pdata,2,own_grp);
3791 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3793 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3796 own_grp = (unsigned int)*puid;
3797 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3798 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3799 SIVAL(pdata,2,own_grp);
3803 case SMB_ACL_GROUP_OBJ:
3804 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3805 own_grp = (unsigned int)pst->st_ex_gid;
3806 SIVAL(pdata,2,own_grp);
3811 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3813 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3816 own_grp = (unsigned int)*pgid;
3817 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3818 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3819 SIVAL(pdata,2,own_grp);
3824 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3825 SIVAL(pdata,2,0xFFFFFFFF);
3826 SIVAL(pdata,6,0xFFFFFFFF);
3829 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3830 SIVAL(pdata,2,0xFFFFFFFF);
3831 SIVAL(pdata,6,0xFFFFFFFF);
3834 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3837 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3844 /****************************************************************************
3845 Store the FILE_UNIX_BASIC info.
3846 ****************************************************************************/
3848 static char *store_file_unix_basic(connection_struct *conn,
3851 const SMB_STRUCT_STAT *psbuf)
3853 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3854 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3856 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3859 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3862 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3863 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3864 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3867 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3871 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3875 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3878 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3882 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3886 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */
3889 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3893 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3900 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3901 * the chflags(2) (or equivalent) flags.
3903 * XXX: this really should be behind the VFS interface. To do this, we would
3904 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3905 * Each VFS module could then implement its own mapping as appropriate for the
3906 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3908 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3912 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3916 { UF_IMMUTABLE, EXT_IMMUTABLE },
3920 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3924 { UF_HIDDEN, EXT_HIDDEN },
3927 /* Do not remove. We need to guarantee that this array has at least one
3928 * entry to build on HP-UX.
3934 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3935 uint32 *smb_fflags, uint32 *smb_fmask)
3939 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3940 *smb_fmask |= info2_flags_map[i].smb_fflag;
3941 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3942 *smb_fflags |= info2_flags_map[i].smb_fflag;
3947 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3948 const uint32 smb_fflags,
3949 const uint32 smb_fmask,
3952 uint32 max_fmask = 0;
3955 *stat_fflags = psbuf->st_ex_flags;
3957 /* For each flags requested in smb_fmask, check the state of the
3958 * corresponding flag in smb_fflags and set or clear the matching
3962 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3963 max_fmask |= info2_flags_map[i].smb_fflag;
3964 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3965 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3966 *stat_fflags |= info2_flags_map[i].stat_fflag;
3968 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3973 /* If smb_fmask is asking to set any bits that are not supported by
3974 * our flag mappings, we should fail.
3976 if ((smb_fmask & max_fmask) != smb_fmask) {
3984 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3985 * of file flags and birth (create) time.
3987 static char *store_file_unix_basic_info2(connection_struct *conn,
3990 const SMB_STRUCT_STAT *psbuf)
3992 uint32 file_flags = 0;
3993 uint32 flags_mask = 0;
3995 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3997 /* Create (birth) time 64 bit */
3998 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4001 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4002 SIVAL(pdata, 0, file_flags); /* flags */
4003 SIVAL(pdata, 4, flags_mask); /* mask */
4009 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4010 const struct stream_struct *streams,
4012 unsigned int max_data_bytes,
4013 unsigned int *data_size)
4016 unsigned int ofs = 0;
4018 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4019 unsigned int next_offset;
4021 smb_ucs2_t *namebuf;
4023 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4024 streams[i].name, &namelen) ||
4027 return NT_STATUS_INVALID_PARAMETER;
4031 * name_buf is now null-terminated, we need to marshall as not
4037 SIVAL(data, ofs+4, namelen);
4038 SOFF_T(data, ofs+8, streams[i].size);
4039 SOFF_T(data, ofs+16, streams[i].alloc_size);
4040 memcpy(data+ofs+24, namebuf, namelen);
4041 TALLOC_FREE(namebuf);
4043 next_offset = ofs + 24 + namelen;
4045 if (i == num_streams-1) {
4046 SIVAL(data, ofs, 0);
4049 unsigned int align = ndr_align_size(next_offset, 8);
4051 memset(data+next_offset, 0, align);
4052 next_offset += align;
4054 SIVAL(data, ofs, next_offset - ofs);
4063 return NT_STATUS_OK;
4066 /****************************************************************************
4067 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4068 ****************************************************************************/
4070 static void call_trans2qpipeinfo(connection_struct *conn,
4071 struct smb_request *req,
4072 unsigned int tran_call,
4073 char **pparams, int total_params,
4074 char **ppdata, int total_data,
4075 unsigned int max_data_bytes)
4077 char *params = *pparams;
4078 char *pdata = *ppdata;
4079 unsigned int data_size = 0;
4080 unsigned int param_size = 2;
4085 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4089 if (total_params < 4) {
4090 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4094 fsp = file_fsp(req, SVAL(params,0));
4095 if (!fsp_is_np(fsp)) {
4096 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4100 info_level = SVAL(params,2);
4102 *pparams = (char *)SMB_REALLOC(*pparams,2);
4103 if (*pparams == NULL) {
4104 reply_nterror(req, NT_STATUS_NO_MEMORY);
4109 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4110 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4111 if (*ppdata == NULL ) {
4112 reply_nterror(req, NT_STATUS_NO_MEMORY);
4117 switch (info_level) {
4118 case SMB_FILE_STANDARD_INFORMATION:
4120 SOFF_T(pdata,0,4096LL);
4127 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4131 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4137 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4138 TALLOC_CTX *mem_ctx,
4139 uint16_t info_level,
4141 struct smb_filename *smb_fname,
4142 bool delete_pending,
4143 struct timespec write_time_ts,
4145 struct ea_list *ea_list,
4146 int lock_data_count,
4149 unsigned int max_data_bytes,
4151 unsigned int *pdata_size)
4153 char *pdata = *ppdata;
4154 char *dstart, *dend;
4155 unsigned int data_size;
4156 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4157 time_t create_time, mtime, atime, c_time;
4158 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4165 uint64_t file_size = 0;
4167 uint64_t allocation_size = 0;
4168 uint64_t file_index = 0;
4169 uint32_t access_mask = 0;
4171 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4172 return NT_STATUS_INVALID_LEVEL;
4175 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4176 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4177 info_level, max_data_bytes));
4180 mode = dos_mode_msdfs(conn, smb_fname);
4182 mode = dos_mode(conn, smb_fname);
4185 nlink = psbuf->st_ex_nlink;
4187 if (nlink && (mode&aDIR)) {
4191 if ((nlink > 0) && delete_pending) {
4195 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4196 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4197 if (*ppdata == NULL) {
4198 return NT_STATUS_NO_MEMORY;
4202 dend = dstart + data_size - 1;
4204 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4205 update_stat_ex_mtime(psbuf, write_time_ts);
4208 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4209 mtime_ts = psbuf->st_ex_mtime;
4210 atime_ts = psbuf->st_ex_atime;
4211 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4213 if (lp_dos_filetime_resolution(SNUM(conn))) {
4214 dos_filetime_timespec(&create_time_ts);
4215 dos_filetime_timespec(&mtime_ts);
4216 dos_filetime_timespec(&atime_ts);
4217 dos_filetime_timespec(&ctime_ts);
4220 create_time = convert_timespec_to_time_t(create_time_ts);
4221 mtime = convert_timespec_to_time_t(mtime_ts);
4222 atime = convert_timespec_to_time_t(atime_ts);
4223 c_time = convert_timespec_to_time_t(ctime_ts);
4225 p = strrchr_m(smb_fname->base_name,'/');
4227 base_name = smb_fname->base_name;
4231 /* NT expects the name to be in an exact form of the *full*
4232 filename. See the trans2 torture test */
4233 if (ISDOT(base_name)) {
4234 dos_fname = talloc_strdup(mem_ctx, "\\");
4236 return NT_STATUS_NO_MEMORY;
4239 dos_fname = talloc_asprintf(mem_ctx,
4241 smb_fname->base_name);
4243 return NT_STATUS_NO_MEMORY;
4245 if (is_ntfs_stream_smb_fname(smb_fname)) {
4246 dos_fname = talloc_asprintf(dos_fname, "%s",
4247 smb_fname->stream_name);
4249 return NT_STATUS_NO_MEMORY;
4253 string_replace(dos_fname, '/', '\\');
4256 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4259 /* Do we have this path open ? */
4261 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4262 fsp1 = file_find_di_first(fileid);
4263 if (fsp1 && fsp1->initial_allocation_size) {
4264 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4268 if (!(mode & aDIR)) {
4269 file_size = get_file_size_stat(psbuf);
4273 pos = fsp->fh->position_information;
4277 access_mask = fsp->access_mask;
4279 /* GENERIC_EXECUTE mapping from Windows */
4280 access_mask = 0x12019F;
4283 /* This should be an index number - looks like
4286 I think this causes us to fail the IFSKIT
4287 BasicFileInformationTest. -tpot */
4288 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
4289 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
4291 switch (info_level) {
4292 case SMB_INFO_STANDARD:
4293 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4295 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4296 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4297 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4298 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4299 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4300 SSVAL(pdata,l1_attrFile,mode);
4303 case SMB_INFO_QUERY_EA_SIZE:
4305 unsigned int ea_size =
4306 estimate_ea_size(conn, fsp,
4307 smb_fname->base_name);
4308 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4310 srv_put_dos_date2(pdata,0,create_time);
4311 srv_put_dos_date2(pdata,4,atime);
4312 srv_put_dos_date2(pdata,8,mtime); /* write time */
4313 SIVAL(pdata,12,(uint32)file_size);
4314 SIVAL(pdata,16,(uint32)allocation_size);
4315 SSVAL(pdata,20,mode);
4316 SIVAL(pdata,22,ea_size);
4320 case SMB_INFO_IS_NAME_VALID:
4321 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4323 /* os/2 needs this ? really ?*/
4324 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4326 /* This is only reached for qpathinfo */
4330 case SMB_INFO_QUERY_EAS_FROM_LIST:
4332 size_t total_ea_len = 0;
4333 struct ea_list *ea_file_list = NULL;
4335 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4338 get_ea_list_from_file(mem_ctx, conn, fsp,
4339 smb_fname->base_name,
4341 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4343 if (!ea_list || (total_ea_len > data_size)) {
4345 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4349 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4353 case SMB_INFO_QUERY_ALL_EAS:
4355 /* We have data_size bytes to put EA's into. */
4356 size_t total_ea_len = 0;
4358 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4360 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4361 smb_fname->base_name,
4363 if (!ea_list || (total_ea_len > data_size)) {
4365 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4369 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4373 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4375 /* This is FileFullEaInformation - 0xF which maps to
4376 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4378 /* We have data_size bytes to put EA's into. */
4379 size_t total_ea_len = 0;
4380 struct ea_list *ea_file_list = NULL;
4382 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4384 /*TODO: add filtering and index handling */
4387 get_ea_list_from_file(mem_ctx, conn, fsp,
4388 smb_fname->base_name,
4390 if (!ea_file_list) {
4391 return NT_STATUS_NO_EAS_ON_FILE;
4394 status = fill_ea_chained_buffer(mem_ctx,
4398 conn, ea_file_list);
4399 if (!NT_STATUS_IS_OK(status)) {
4405 case SMB_FILE_BASIC_INFORMATION:
4406 case SMB_QUERY_FILE_BASIC_INFO:
4408 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4409 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4410 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4412 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4416 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4417 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4418 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4419 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4420 SIVAL(pdata,32,mode);
4422 DEBUG(5,("SMB_QFBI - "));
4423 DEBUG(5,("create: %s ", ctime(&create_time)));
4424 DEBUG(5,("access: %s ", ctime(&atime)));
4425 DEBUG(5,("write: %s ", ctime(&mtime)));
4426 DEBUG(5,("change: %s ", ctime(&c_time)));
4427 DEBUG(5,("mode: %x\n", mode));
4430 case SMB_FILE_STANDARD_INFORMATION:
4431 case SMB_QUERY_FILE_STANDARD_INFO:
4433 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4435 SOFF_T(pdata,0,allocation_size);
4436 SOFF_T(pdata,8,file_size);
4437 SIVAL(pdata,16,nlink);
4438 SCVAL(pdata,20,delete_pending?1:0);
4439 SCVAL(pdata,21,(mode&aDIR)?1:0);
4440 SSVAL(pdata,22,0); /* Padding. */
4443 case SMB_FILE_EA_INFORMATION:
4444 case SMB_QUERY_FILE_EA_INFO:
4446 unsigned int ea_size =
4447 estimate_ea_size(conn, fsp, smb_fname->base_name);
4448 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4450 SIVAL(pdata,0,ea_size);
4454 /* Get the 8.3 name - used if NT SMB was negotiated. */
4455 case SMB_QUERY_FILE_ALT_NAME_INFO:
4456 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4459 char mangled_name[13];
4460 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4461 if (!name_to_8_3(base_name,mangled_name,
4462 True,conn->params)) {
4463 return NT_STATUS_NO_MEMORY;
4465 len = srvstr_push(dstart, flags2,
4466 pdata+4, mangled_name,
4467 PTR_DIFF(dend, pdata+4),
4469 data_size = 4 + len;
4474 case SMB_QUERY_FILE_NAME_INFO:
4478 this must be *exactly* right for ACLs on mapped drives to work
4480 len = srvstr_push(dstart, flags2,
4482 PTR_DIFF(dend, pdata+4),
4484 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4485 data_size = 4 + len;
4490 case SMB_FILE_ALLOCATION_INFORMATION:
4491 case SMB_QUERY_FILE_ALLOCATION_INFO:
4492 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4494 SOFF_T(pdata,0,allocation_size);
4497 case SMB_FILE_END_OF_FILE_INFORMATION:
4498 case SMB_QUERY_FILE_END_OF_FILEINFO:
4499 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4501 SOFF_T(pdata,0,file_size);
4504 case SMB_QUERY_FILE_ALL_INFO:
4505 case SMB_FILE_ALL_INFORMATION:
4508 unsigned int ea_size =
4509 estimate_ea_size(conn, fsp, smb_fname->base_name);
4510 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4511 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4512 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4513 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4514 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4515 SIVAL(pdata,32,mode);
4516 SIVAL(pdata,36,0); /* padding. */
4518 SOFF_T(pdata,0,allocation_size);
4519 SOFF_T(pdata,8,file_size);
4520 SIVAL(pdata,16,nlink);
4521 SCVAL(pdata,20,delete_pending);
4522 SCVAL(pdata,21,(mode&aDIR)?1:0);
4525 SIVAL(pdata,0,ea_size);
4526 pdata += 4; /* EA info */
4527 len = srvstr_push(dstart, flags2,
4529 PTR_DIFF(dend, pdata+4),
4533 data_size = PTR_DIFF(pdata,(*ppdata));
4537 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4540 unsigned int ea_size =
4541 estimate_ea_size(conn, fsp, smb_fname->base_name);
4542 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4543 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4544 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4545 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4546 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4547 SIVAL(pdata, 0x20, mode);
4548 SIVAL(pdata, 0x24, 0); /* padding. */
4549 SBVAL(pdata, 0x28, allocation_size);
4550 SBVAL(pdata, 0x30, file_size);
4551 SIVAL(pdata, 0x38, nlink);
4552 SCVAL(pdata, 0x3C, delete_pending);
4553 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4554 SSVAL(pdata, 0x3E, 0); /* padding */
4555 SBVAL(pdata, 0x40, file_index);
4556 SIVAL(pdata, 0x48, ea_size);
4557 SIVAL(pdata, 0x4C, access_mask);
4558 SBVAL(pdata, 0x50, pos);
4559 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4560 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4564 len = srvstr_push(dstart, flags2,
4566 PTR_DIFF(dend, pdata+4),
4570 data_size = PTR_DIFF(pdata,(*ppdata));
4573 case SMB_FILE_INTERNAL_INFORMATION:
4575 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4576 SBVAL(pdata, 0, file_index);
4580 case SMB_FILE_ACCESS_INFORMATION:
4581 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4582 SIVAL(pdata, 0, access_mask);
4586 case SMB_FILE_NAME_INFORMATION:
4587 /* Pathname with leading '\'. */
4590 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4591 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4592 SIVAL(pdata,0,byte_len);
4593 data_size = 4 + byte_len;
4597 case SMB_FILE_DISPOSITION_INFORMATION:
4598 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4600 SCVAL(pdata,0,delete_pending);
4603 case SMB_FILE_POSITION_INFORMATION:
4604 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4606 SOFF_T(pdata,0,pos);
4609 case SMB_FILE_MODE_INFORMATION:
4610 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4611 SIVAL(pdata,0,mode);
4615 case SMB_FILE_ALIGNMENT_INFORMATION:
4616 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4617 SIVAL(pdata,0,0); /* No alignment needed. */
4622 * NT4 server just returns "invalid query" to this - if we try
4623 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4626 /* The first statement above is false - verified using Thursby
4627 * client against NT4 -- gcolley.
4629 case SMB_QUERY_FILE_STREAM_INFO:
4630 case SMB_FILE_STREAM_INFORMATION: {
4631 unsigned int num_streams;
4632 struct stream_struct *streams;
4634 DEBUG(10,("smbd_do_qfilepathinfo: "
4635 "SMB_FILE_STREAM_INFORMATION\n"));
4637 if (is_ntfs_stream_smb_fname(smb_fname)) {
4638 return NT_STATUS_INVALID_PARAMETER;
4641 status = SMB_VFS_STREAMINFO(
4642 conn, fsp, smb_fname->base_name, talloc_tos(),
4643 &num_streams, &streams);
4645 if (!NT_STATUS_IS_OK(status)) {
4646 DEBUG(10, ("could not get stream info: %s\n",
4647 nt_errstr(status)));
4651 status = marshall_stream_info(num_streams, streams,
4652 pdata, max_data_bytes,
4655 if (!NT_STATUS_IS_OK(status)) {
4656 DEBUG(10, ("marshall_stream_info failed: %s\n",
4657 nt_errstr(status)));
4661 TALLOC_FREE(streams);
4665 case SMB_QUERY_COMPRESSION_INFO:
4666 case SMB_FILE_COMPRESSION_INFORMATION:
4667 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4668 SOFF_T(pdata,0,file_size);
4669 SIVAL(pdata,8,0); /* ??? */
4670 SIVAL(pdata,12,0); /* ??? */
4674 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4675 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4676 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4677 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4678 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4679 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4680 SOFF_T(pdata,32,allocation_size);
4681 SOFF_T(pdata,40,file_size);
4682 SIVAL(pdata,48,mode);
4683 SIVAL(pdata,52,0); /* ??? */
4687 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4688 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4689 SIVAL(pdata,0,mode);
4695 * CIFS UNIX Extensions.
4698 case SMB_QUERY_FILE_UNIX_BASIC:
4700 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4701 data_size = PTR_DIFF(pdata,(*ppdata));
4705 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4707 for (i=0; i<100; i++)
4708 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4714 case SMB_QUERY_FILE_UNIX_INFO2:
4716 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4717 data_size = PTR_DIFF(pdata,(*ppdata));
4721 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4723 for (i=0; i<100; i++)
4724 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4730 case SMB_QUERY_FILE_UNIX_LINK:
4733 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4736 return NT_STATUS_NO_MEMORY;
4739 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4741 if(!S_ISLNK(psbuf->st_ex_mode)) {
4742 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4745 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4747 len = SMB_VFS_READLINK(conn,
4748 smb_fname->base_name,
4751 return map_nt_error_from_unix(errno);
4754 len = srvstr_push(dstart, flags2,
4756 PTR_DIFF(dend, pdata),
4759 data_size = PTR_DIFF(pdata,(*ppdata));
4764 #if defined(HAVE_POSIX_ACLS)
4765 case SMB_QUERY_POSIX_ACL:
4767 SMB_ACL_T file_acl = NULL;
4768 SMB_ACL_T def_acl = NULL;
4769 uint16 num_file_acls = 0;
4770 uint16 num_def_acls = 0;
4772 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4773 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4776 SMB_VFS_SYS_ACL_GET_FILE(conn,
4777 smb_fname->base_name,
4778 SMB_ACL_TYPE_ACCESS);
4781 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4782 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4783 "not implemented on "
4784 "filesystem containing %s\n",
4785 smb_fname->base_name));
4786 return NT_STATUS_NOT_IMPLEMENTED;
4789 if (S_ISDIR(psbuf->st_ex_mode)) {
4790 if (fsp && fsp->is_directory) {
4792 SMB_VFS_SYS_ACL_GET_FILE(
4794 fsp->fsp_name->base_name,
4795 SMB_ACL_TYPE_DEFAULT);
4798 SMB_VFS_SYS_ACL_GET_FILE(
4800 smb_fname->base_name,
4801 SMB_ACL_TYPE_DEFAULT);
4803 def_acl = free_empty_sys_acl(conn, def_acl);
4806 num_file_acls = count_acl_entries(conn, file_acl);
4807 num_def_acls = count_acl_entries(conn, def_acl);
4809 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4810 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4812 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4813 SMB_POSIX_ACL_HEADER_SIZE) ));
4815 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4818 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4820 return NT_STATUS_BUFFER_TOO_SMALL;
4823 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4824 SSVAL(pdata,2,num_file_acls);
4825 SSVAL(pdata,4,num_def_acls);
4826 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4828 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4831 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4833 return NT_STATUS_INTERNAL_ERROR;
4835 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_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;
4846 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4849 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4851 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4857 case SMB_QUERY_POSIX_LOCK:
4862 enum brl_type lock_type;
4864 /* We need an open file with a real fd for this. */
4865 if (!fsp || fsp->is_directory || fsp->fh->fd == -1) {
4866 return NT_STATUS_INVALID_LEVEL;
4869 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4870 return NT_STATUS_INVALID_PARAMETER;
4873 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4874 case POSIX_LOCK_TYPE_READ:
4875 lock_type = READ_LOCK;
4877 case POSIX_LOCK_TYPE_WRITE:
4878 lock_type = WRITE_LOCK;
4880 case POSIX_LOCK_TYPE_UNLOCK:
4882 /* There's no point in asking for an unlock... */
4883 return NT_STATUS_INVALID_PARAMETER;
4886 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4887 #if defined(HAVE_LONGLONG)
4888 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4889 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4890 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4891 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4892 #else /* HAVE_LONGLONG */
4893 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4894 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4895 #endif /* HAVE_LONGLONG */
4897 status = query_lock(fsp,
4904 if (ERROR_WAS_LOCK_DENIED(status)) {
4905 /* Here we need to report who has it locked... */
4906 data_size = POSIX_LOCK_DATA_SIZE;
4908 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4909 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4910 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4911 #if defined(HAVE_LONGLONG)
4912 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4913 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4914 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4915 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4916 #else /* HAVE_LONGLONG */
4917 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4918 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4919 #endif /* HAVE_LONGLONG */
4921 } else if (NT_STATUS_IS_OK(status)) {
4922 /* For success we just return a copy of what we sent
4923 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4924 data_size = POSIX_LOCK_DATA_SIZE;
4925 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4926 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4934 return NT_STATUS_INVALID_LEVEL;
4937 *pdata_size = data_size;
4938 return NT_STATUS_OK;
4941 /****************************************************************************
4942 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4943 file name or file id).
4944 ****************************************************************************/
4946 static void call_trans2qfilepathinfo(connection_struct *conn,
4947 struct smb_request *req,
4948 unsigned int tran_call,
4949 char **pparams, int total_params,
4950 char **ppdata, int total_data,
4951 unsigned int max_data_bytes)
4953 char *params = *pparams;
4954 char *pdata = *ppdata;
4956 unsigned int data_size = 0;
4957 unsigned int param_size = 2;
4958 struct smb_filename *smb_fname = NULL;
4959 bool delete_pending = False;
4960 struct timespec write_time_ts;
4961 files_struct *fsp = NULL;
4962 struct file_id fileid;
4963 struct ea_list *ea_list = NULL;
4964 int lock_data_count = 0;
4965 char *lock_data = NULL;
4966 bool ms_dfs_link = false;
4967 NTSTATUS status = NT_STATUS_OK;
4970 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4974 ZERO_STRUCT(write_time_ts);
4976 if (tran_call == TRANSACT2_QFILEINFO) {
4977 if (total_params < 4) {
4978 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4983 call_trans2qpipeinfo(conn, req, tran_call,
4984 pparams, total_params,
4990 fsp = file_fsp(req, SVAL(params,0));
4991 info_level = SVAL(params,2);
4993 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
4995 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4996 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5000 /* Initial check for valid fsp ptr. */
5001 if (!check_fsp_open(conn, req, fsp)) {
5005 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5007 if (!NT_STATUS_IS_OK(status)) {
5008 reply_nterror(req, status);
5012 if(fsp->fake_file_handle) {
5014 * This is actually for the QUOTA_FAKE_FILE --metze
5017 /* We know this name is ok, it's already passed the checks. */
5019 } else if(fsp->is_directory || fsp->fh->fd == -1) {
5021 * This is actually a QFILEINFO on a directory
5022 * handle (returned from an NT SMB). NT5.0 seems
5023 * to do this call. JRA.
5026 if (INFO_LEVEL_IS_UNIX(info_level)) {
5027 /* Always do lstat for UNIX calls. */
5028 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5029 DEBUG(3,("call_trans2qfilepathinfo: "
5030 "SMB_VFS_LSTAT of %s failed "
5032 smb_fname_str_dbg(smb_fname),
5035 map_nt_error_from_unix(errno));
5038 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5039 DEBUG(3,("call_trans2qfilepathinfo: "
5040 "SMB_VFS_STAT of %s failed (%s)\n",
5041 smb_fname_str_dbg(smb_fname),
5044 map_nt_error_from_unix(errno));
5048 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5049 get_file_infos(fileid, &delete_pending, &write_time_ts);
5052 * Original code - this is an open file.
5054 if (!check_fsp(conn, req, fsp)) {
5058 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5059 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5060 fsp->fnum, strerror(errno)));
5062 map_nt_error_from_unix(errno));
5065 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5066 get_file_infos(fileid, &delete_pending, &write_time_ts);
5073 if (total_params < 7) {
5074 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5078 info_level = SVAL(params,0);
5080 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5082 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5083 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5087 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
5089 STR_TERMINATE, &status);
5090 if (!NT_STATUS_IS_OK(status)) {
5091 reply_nterror(req, status);
5095 status = filename_convert(req,
5097 req->flags2 & FLAGS2_DFS_PATHNAMES,
5102 if (!NT_STATUS_IS_OK(status)) {
5103 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5104 reply_botherror(req,
5105 NT_STATUS_PATH_NOT_COVERED,
5106 ERRSRV, ERRbadpath);
5109 reply_nterror(req, status);
5113 /* If this is a stream, check if there is a delete_pending. */
5114 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5115 && is_ntfs_stream_smb_fname(smb_fname)) {
5116 struct smb_filename *smb_fname_base = NULL;
5118 /* Create an smb_filename with stream_name == NULL. */
5120 create_synthetic_smb_fname(talloc_tos(),
5121 smb_fname->base_name,
5124 if (!NT_STATUS_IS_OK(status)) {
5125 reply_nterror(req, status);
5129 if (INFO_LEVEL_IS_UNIX(info_level)) {
5130 /* Always do lstat for UNIX calls. */
5131 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5132 DEBUG(3,("call_trans2qfilepathinfo: "
5133 "SMB_VFS_LSTAT of %s failed "
5135 smb_fname_str_dbg(smb_fname_base),
5137 TALLOC_FREE(smb_fname_base);
5139 map_nt_error_from_unix(errno));
5143 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5144 DEBUG(3,("call_trans2qfilepathinfo: "
5145 "fileinfo of %s failed "
5147 smb_fname_str_dbg(smb_fname_base),
5149 TALLOC_FREE(smb_fname_base);
5151 map_nt_error_from_unix(errno));
5156 fileid = vfs_file_id_from_sbuf(conn,
5157 &smb_fname_base->st);
5158 TALLOC_FREE(smb_fname_base);
5159 get_file_infos(fileid, &delete_pending, NULL);
5160 if (delete_pending) {
5161 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5166 if (INFO_LEVEL_IS_UNIX(info_level)) {
5167 /* Always do lstat for UNIX calls. */
5168 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5169 DEBUG(3,("call_trans2qfilepathinfo: "
5170 "SMB_VFS_LSTAT of %s failed (%s)\n",
5171 smb_fname_str_dbg(smb_fname),
5174 map_nt_error_from_unix(errno));
5178 } else if (!VALID_STAT(smb_fname->st) &&
5179 SMB_VFS_STAT(conn, smb_fname) &&
5180 (info_level != SMB_INFO_IS_NAME_VALID)) {
5181 ms_dfs_link = check_msdfs_link(conn,
5182 smb_fname->base_name,
5186 DEBUG(3,("call_trans2qfilepathinfo: "
5187 "SMB_VFS_STAT of %s failed (%s)\n",
5188 smb_fname_str_dbg(smb_fname),
5191 map_nt_error_from_unix(errno));
5196 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5197 get_file_infos(fileid, &delete_pending, &write_time_ts);
5198 if (delete_pending) {
5199 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5204 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5205 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5206 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5208 /* Pull out any data sent here before we realloc. */
5209 switch (info_level) {
5210 case SMB_INFO_QUERY_EAS_FROM_LIST:
5212 /* Pull any EA list from the data portion. */
5215 if (total_data < 4) {
5217 req, NT_STATUS_INVALID_PARAMETER);
5220 ea_size = IVAL(pdata,0);
5222 if (total_data > 0 && ea_size != total_data) {
5223 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5224 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5226 req, NT_STATUS_INVALID_PARAMETER);
5230 if (!lp_ea_support(SNUM(conn))) {
5231 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5235 /* Pull out the list of names. */
5236 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5239 req, NT_STATUS_INVALID_PARAMETER);
5245 case SMB_QUERY_POSIX_LOCK:
5247 if (fsp == NULL || fsp->fh->fd == -1) {
5248 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5252 if (total_data != POSIX_LOCK_DATA_SIZE) {
5254 req, NT_STATUS_INVALID_PARAMETER);
5258 /* Copy the lock range data. */
5259 lock_data = (char *)TALLOC_MEMDUP(
5260 req, pdata, total_data);
5262 reply_nterror(req, NT_STATUS_NO_MEMORY);
5265 lock_data_count = total_data;
5271 *pparams = (char *)SMB_REALLOC(*pparams,2);
5272 if (*pparams == NULL) {
5273 reply_nterror(req, NT_STATUS_NO_MEMORY);
5280 * draft-leach-cifs-v1-spec-02.txt
5281 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5284 * The requested information is placed in the Data portion of the
5285 * transaction response. For the information levels greater than 0x100,
5286 * the transaction response has 1 parameter word which should be
5287 * ignored by the client.
5289 * However Windows only follows this rule for the IS_NAME_VALID call.
5291 switch (info_level) {
5292 case SMB_INFO_IS_NAME_VALID:
5297 if ((info_level & 0xFF00) == 0xFF00) {
5299 * We use levels that start with 0xFF00
5300 * internally to represent SMB2 specific levels
5302 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5306 status = smbd_do_qfilepathinfo(conn, req, info_level,
5308 delete_pending, write_time_ts,
5309 ms_dfs_link, ea_list,
5310 lock_data_count, lock_data,
5311 req->flags2, max_data_bytes,
5312 ppdata, &data_size);
5313 if (!NT_STATUS_IS_OK(status)) {
5314 reply_nterror(req, status);
5318 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5324 /****************************************************************************
5325 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5327 ****************************************************************************/
5329 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5330 connection_struct *conn,
5331 const struct smb_filename *smb_fname_old,
5332 const struct smb_filename *smb_fname_new)
5334 NTSTATUS status = NT_STATUS_OK;
5336 /* source must already exist. */
5337 if (!VALID_STAT(smb_fname_old->st)) {
5338 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5341 /* Disallow if newname already exists. */
5342 if (VALID_STAT(smb_fname_new->st)) {
5343 return NT_STATUS_OBJECT_NAME_COLLISION;
5346 /* No links from a directory. */
5347 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5348 return NT_STATUS_FILE_IS_A_DIRECTORY;
5351 /* Setting a hardlink to/from a stream isn't currently supported. */
5352 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5353 is_ntfs_stream_smb_fname(smb_fname_new)) {
5354 return NT_STATUS_INVALID_PARAMETER;
5357 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5358 smb_fname_old->base_name, smb_fname_new->base_name));
5360 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5361 smb_fname_new->base_name) != 0) {
5362 status = map_nt_error_from_unix(errno);
5363 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5364 nt_errstr(status), smb_fname_old->base_name,
5365 smb_fname_new->base_name));
5370 /****************************************************************************
5371 Deal with setting the time from any of the setfilepathinfo functions.
5372 ****************************************************************************/
5374 NTSTATUS smb_set_file_time(connection_struct *conn,
5376 const struct smb_filename *smb_fname,
5377 struct smb_file_time *ft,
5378 bool setting_write_time)
5380 struct smb_filename smb_fname_base;
5382 FILE_NOTIFY_CHANGE_LAST_ACCESS
5383 |FILE_NOTIFY_CHANGE_LAST_WRITE
5384 |FILE_NOTIFY_CHANGE_CREATION;
5386 if (!VALID_STAT(smb_fname->st)) {
5387 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5390 /* get some defaults (no modifications) if any info is zero or -1. */
5391 if (null_timespec(ft->create_time)) {
5392 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5395 if (null_timespec(ft->atime)) {
5396 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5399 if (null_timespec(ft->mtime)) {
5400 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5403 if (!setting_write_time) {
5404 /* ft->mtime comes from change time, not write time. */
5405 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5408 /* Ensure the resolution is the correct for
5409 * what we can store on this filesystem. */
5411 round_timespec(conn->ts_res, &ft->create_time);
5412 round_timespec(conn->ts_res, &ft->ctime);
5413 round_timespec(conn->ts_res, &ft->atime);
5414 round_timespec(conn->ts_res, &ft->mtime);
5416 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5417 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5418 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5419 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5420 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5421 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5422 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5423 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5425 if (setting_write_time) {
5427 * This was a Windows setfileinfo on an open file.
5428 * NT does this a lot. We also need to
5429 * set the time here, as it can be read by
5430 * FindFirst/FindNext and with the patch for bug #2045
5431 * in smbd/fileio.c it ensures that this timestamp is
5432 * kept sticky even after a write. We save the request
5433 * away and will set it on file close and after a write. JRA.
5436 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5437 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5440 if (fsp->base_fsp) {
5441 set_sticky_write_time_fsp(fsp->base_fsp,
5444 set_sticky_write_time_fsp(fsp, ft->mtime);
5447 set_sticky_write_time_path(
5448 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5453 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5455 /* Always call ntimes on the base, even if a stream was passed in. */
5456 smb_fname_base = *smb_fname;
5457 smb_fname_base.stream_name = NULL;
5459 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5460 return map_nt_error_from_unix(errno);
5463 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5464 smb_fname->base_name);
5465 return NT_STATUS_OK;
5468 /****************************************************************************
5469 Deal with setting the dosmode from any of the setfilepathinfo functions.
5470 ****************************************************************************/
5472 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5473 const struct smb_filename *smb_fname,
5476 struct smb_filename *smb_fname_base = NULL;
5479 if (!VALID_STAT(smb_fname->st)) {
5480 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5483 /* Always operate on the base_name, even if a stream was passed in. */
5484 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5485 NULL, &smb_fname->st,
5487 if (!NT_STATUS_IS_OK(status)) {
5492 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5499 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5501 /* check the mode isn't different, before changing it */
5502 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5503 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5504 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5505 (unsigned int)dosmode));
5507 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5509 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5511 smb_fname_str_dbg(smb_fname_base),
5513 status = map_nt_error_from_unix(errno);
5517 status = NT_STATUS_OK;
5519 TALLOC_FREE(smb_fname_base);
5523 /****************************************************************************
5524 Deal with setting the size from any of the setfilepathinfo functions.
5525 ****************************************************************************/
5527 static NTSTATUS smb_set_file_size(connection_struct *conn,
5528 struct smb_request *req,
5530 const struct smb_filename *smb_fname,
5531 const SMB_STRUCT_STAT *psbuf,
5533 bool fail_after_createfile)
5535 NTSTATUS status = NT_STATUS_OK;
5536 struct smb_filename *smb_fname_tmp = NULL;
5537 files_struct *new_fsp = NULL;
5539 if (!VALID_STAT(*psbuf)) {
5540 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5543 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5545 if (size == get_file_size_stat(psbuf)) {
5546 return NT_STATUS_OK;
5549 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5550 smb_fname_str_dbg(smb_fname), (double)size));
5552 if (fsp && fsp->fh->fd != -1) {
5553 /* Handle based call. */
5554 if (vfs_set_filelen(fsp, size) == -1) {
5555 return map_nt_error_from_unix(errno);
5557 trigger_write_time_update_immediate(fsp);
5558 return NT_STATUS_OK;
5561 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5562 if (!NT_STATUS_IS_OK(status)) {
5566 smb_fname_tmp->st = *psbuf;
5568 status = SMB_VFS_CREATE_FILE(
5571 0, /* root_dir_fid */
5572 smb_fname_tmp, /* fname */
5573 FILE_WRITE_ATTRIBUTES, /* access_mask */
5574 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5576 FILE_OPEN, /* create_disposition*/
5577 0, /* create_options */
5578 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5579 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5580 0, /* allocation_size */
5583 &new_fsp, /* result */
5586 TALLOC_FREE(smb_fname_tmp);
5588 if (!NT_STATUS_IS_OK(status)) {
5589 /* NB. We check for open_was_deferred in the caller. */
5593 /* See RAW-SFILEINFO-END-OF-FILE */
5594 if (fail_after_createfile) {
5595 close_file(req, new_fsp,NORMAL_CLOSE);
5596 return NT_STATUS_INVALID_LEVEL;
5599 if (vfs_set_filelen(new_fsp, size) == -1) {
5600 status = map_nt_error_from_unix(errno);
5601 close_file(req, new_fsp,NORMAL_CLOSE);
5605 trigger_write_time_update_immediate(new_fsp);
5606 close_file(req, new_fsp,NORMAL_CLOSE);
5607 return NT_STATUS_OK;
5610 /****************************************************************************
5611 Deal with SMB_INFO_SET_EA.
5612 ****************************************************************************/
5614 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5618 const struct smb_filename *smb_fname)
5620 struct ea_list *ea_list = NULL;
5621 TALLOC_CTX *ctx = NULL;
5622 NTSTATUS status = NT_STATUS_OK;
5624 if (total_data < 10) {
5626 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5627 length. They seem to have no effect. Bug #3212. JRA */
5629 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5630 /* We're done. We only get EA info in this call. */
5631 return NT_STATUS_OK;
5634 return NT_STATUS_INVALID_PARAMETER;
5637 if (IVAL(pdata,0) > total_data) {
5638 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5639 IVAL(pdata,0), (unsigned int)total_data));
5640 return NT_STATUS_INVALID_PARAMETER;
5644 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5646 return NT_STATUS_INVALID_PARAMETER;
5648 status = set_ea(conn, fsp, smb_fname, ea_list);
5653 /****************************************************************************
5654 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5655 ****************************************************************************/
5657 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5662 struct ea_list *ea_list = NULL;
5666 return NT_STATUS_INVALID_HANDLE;
5669 if (!lp_ea_support(SNUM(conn))) {
5670 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5671 "EA's not supported.\n",
5672 (unsigned int)total_data));
5673 return NT_STATUS_EAS_NOT_SUPPORTED;
5676 if (total_data < 10) {
5677 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5679 (unsigned int)total_data));
5680 return NT_STATUS_INVALID_PARAMETER;
5683 ea_list = read_nttrans_ea_list(talloc_tos(),
5688 return NT_STATUS_INVALID_PARAMETER;
5690 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5692 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5693 smb_fname_str_dbg(fsp->fsp_name),
5694 nt_errstr(status) ));
5700 /****************************************************************************
5701 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5702 ****************************************************************************/
5704 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5708 struct smb_filename *smb_fname)
5710 NTSTATUS status = NT_STATUS_OK;
5711 bool delete_on_close;
5714 if (total_data < 1) {
5715 return NT_STATUS_INVALID_PARAMETER;
5719 return NT_STATUS_INVALID_HANDLE;
5722 delete_on_close = (CVAL(pdata,0) ? True : False);
5723 dosmode = dos_mode(conn, smb_fname);
5725 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5726 "delete_on_close = %u\n",
5727 smb_fname_str_dbg(smb_fname),
5728 (unsigned int)dosmode,
5729 (unsigned int)delete_on_close ));
5731 if (delete_on_close) {
5732 status = can_set_delete_on_close(fsp, dosmode);
5733 if (!NT_STATUS_IS_OK(status)) {
5738 /* The set is across all open files on this dev/inode pair. */
5739 if (!set_delete_on_close(fsp, delete_on_close,
5740 &conn->server_info->utok)) {
5741 return NT_STATUS_ACCESS_DENIED;
5743 return NT_STATUS_OK;
5746 /****************************************************************************
5747 Deal with SMB_FILE_POSITION_INFORMATION.
5748 ****************************************************************************/
5750 static NTSTATUS smb_file_position_information(connection_struct *conn,
5755 uint64_t position_information;
5757 if (total_data < 8) {
5758 return NT_STATUS_INVALID_PARAMETER;
5762 /* Ignore on pathname based set. */
5763 return NT_STATUS_OK;
5766 position_information = (uint64_t)IVAL(pdata,0);
5767 #ifdef LARGE_SMB_OFF_T
5768 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5769 #else /* LARGE_SMB_OFF_T */
5770 if (IVAL(pdata,4) != 0) {
5771 /* more than 32 bits? */
5772 return NT_STATUS_INVALID_PARAMETER;
5774 #endif /* LARGE_SMB_OFF_T */
5776 DEBUG(10,("smb_file_position_information: Set file position "
5777 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5778 (double)position_information));
5779 fsp->fh->position_information = position_information;
5780 return NT_STATUS_OK;
5783 /****************************************************************************
5784 Deal with SMB_FILE_MODE_INFORMATION.
5785 ****************************************************************************/
5787 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5793 if (total_data < 4) {
5794 return NT_STATUS_INVALID_PARAMETER;
5796 mode = IVAL(pdata,0);
5797 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5798 return NT_STATUS_INVALID_PARAMETER;
5800 return NT_STATUS_OK;
5803 /****************************************************************************
5804 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5805 ****************************************************************************/
5807 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5808 struct smb_request *req,
5811 const struct smb_filename *smb_fname)
5813 char *link_target = NULL;
5814 const char *newname = smb_fname->base_name;
5815 TALLOC_CTX *ctx = talloc_tos();
5817 /* Set a symbolic link. */
5818 /* Don't allow this if follow links is false. */
5820 if (total_data == 0) {
5821 return NT_STATUS_INVALID_PARAMETER;
5824 if (!lp_symlinks(SNUM(conn))) {
5825 return NT_STATUS_ACCESS_DENIED;
5828 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5829 total_data, STR_TERMINATE);
5832 return NT_STATUS_INVALID_PARAMETER;
5835 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5836 newname, link_target ));
5838 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5839 return map_nt_error_from_unix(errno);
5842 return NT_STATUS_OK;
5845 /****************************************************************************
5846 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5847 ****************************************************************************/
5849 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5850 struct smb_request *req,
5851 const char *pdata, int total_data,
5852 const struct smb_filename *smb_fname_new)
5854 char *oldname = NULL;
5855 struct smb_filename *smb_fname_old = NULL;
5856 TALLOC_CTX *ctx = talloc_tos();
5857 NTSTATUS status = NT_STATUS_OK;
5859 /* Set a hard link. */
5860 if (total_data == 0) {
5861 return NT_STATUS_INVALID_PARAMETER;
5864 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5865 total_data, STR_TERMINATE, &status);
5866 if (!NT_STATUS_IS_OK(status)) {
5870 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5871 smb_fname_str_dbg(smb_fname_new), oldname));
5873 status = filename_convert(ctx,
5875 req->flags2 & FLAGS2_DFS_PATHNAMES,
5880 if (!NT_STATUS_IS_OK(status)) {
5884 return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
5887 /****************************************************************************
5888 Deal with SMB_FILE_RENAME_INFORMATION.
5889 ****************************************************************************/
5891 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5892 struct smb_request *req,
5896 struct smb_filename *smb_fname_src)
5901 char *newname = NULL;
5902 struct smb_filename *smb_fname_dst = NULL;
5903 bool dest_has_wcard = False;
5904 NTSTATUS status = NT_STATUS_OK;
5906 TALLOC_CTX *ctx = talloc_tos();
5908 if (total_data < 13) {
5909 return NT_STATUS_INVALID_PARAMETER;
5912 overwrite = (CVAL(pdata,0) ? True : False);
5913 root_fid = IVAL(pdata,4);
5914 len = IVAL(pdata,8);
5916 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5917 return NT_STATUS_INVALID_PARAMETER;
5920 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5923 if (!NT_STATUS_IS_OK(status)) {
5927 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5930 status = resolve_dfspath_wcard(ctx, conn,
5931 req->flags2 & FLAGS2_DFS_PATHNAMES,
5936 if (!NT_STATUS_IS_OK(status)) {
5940 /* Check the new name has no '/' characters. */
5941 if (strchr_m(newname, '/')) {
5942 return NT_STATUS_NOT_SUPPORTED;
5945 if (fsp && fsp->base_fsp) {
5946 /* newname must be a stream name. */
5947 if (newname[0] != ':') {
5948 return NT_STATUS_NOT_SUPPORTED;
5951 /* Create an smb_fname to call rename_internals_fsp() with. */
5952 status = create_synthetic_smb_fname(talloc_tos(),
5953 fsp->base_fsp->fsp_name->base_name, newname, NULL,
5955 if (!NT_STATUS_IS_OK(status)) {
5960 * Set the original last component, since
5961 * rename_internals_fsp() requires it.
5963 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
5965 if (smb_fname_dst->original_lcomp == NULL) {
5966 status = NT_STATUS_NO_MEMORY;
5972 * Build up an smb_fname_dst based on the filename passed in.
5973 * We basically just strip off the last component, and put on
5974 * the newname instead.
5976 char *base_name = NULL;
5978 /* newname must *not* be a stream name. */
5979 if (newname[0] == ':') {
5980 return NT_STATUS_NOT_SUPPORTED;
5984 * Strip off the last component (filename) of the path passed
5987 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
5989 return NT_STATUS_NO_MEMORY;
5991 p = strrchr_m(base_name, '/');
5995 base_name = talloc_strdup(ctx, "./");
5997 return NT_STATUS_NO_MEMORY;
6000 /* Append the new name. */
6001 base_name = talloc_asprintf_append(base_name,
6005 return NT_STATUS_NO_MEMORY;
6008 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6011 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6014 /* If an error we expect this to be
6015 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6017 if (!NT_STATUS_IS_OK(status)) {
6018 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6022 /* Create an smb_fname to call rename_internals_fsp() */
6023 status = create_synthetic_smb_fname(ctx,
6027 if (!NT_STATUS_IS_OK(status)) {
6034 DEBUG(10,("smb_file_rename_information: "
6035 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6036 fsp->fnum, fsp_str_dbg(fsp),
6037 smb_fname_str_dbg(smb_fname_dst)));
6038 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6041 DEBUG(10,("smb_file_rename_information: "
6042 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6043 smb_fname_str_dbg(smb_fname_src),
6044 smb_fname_str_dbg(smb_fname_dst)));
6045 status = rename_internals(ctx, conn, req, smb_fname_src,
6046 smb_fname_dst, 0, overwrite, false,
6048 FILE_WRITE_ATTRIBUTES);
6051 TALLOC_FREE(smb_fname_dst);
6055 /****************************************************************************
6056 Deal with SMB_SET_POSIX_ACL.
6057 ****************************************************************************/
6059 #if defined(HAVE_POSIX_ACLS)
6060 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6064 const struct smb_filename *smb_fname)
6066 uint16 posix_acl_version;
6067 uint16 num_file_acls;
6068 uint16 num_def_acls;
6069 bool valid_file_acls = True;
6070 bool valid_def_acls = True;
6072 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6073 return NT_STATUS_INVALID_PARAMETER;
6075 posix_acl_version = SVAL(pdata,0);
6076 num_file_acls = SVAL(pdata,2);
6077 num_def_acls = SVAL(pdata,4);
6079 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6080 valid_file_acls = False;
6084 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6085 valid_def_acls = False;
6089 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6090 return NT_STATUS_INVALID_PARAMETER;
6093 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6094 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6095 return NT_STATUS_INVALID_PARAMETER;
6098 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6099 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6100 (unsigned int)num_file_acls,
6101 (unsigned int)num_def_acls));
6103 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6104 smb_fname->base_name, num_file_acls,
6105 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6106 return map_nt_error_from_unix(errno);
6109 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6110 smb_fname->base_name, &smb_fname->st, num_def_acls,
6111 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6112 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6113 return map_nt_error_from_unix(errno);
6115 return NT_STATUS_OK;
6119 /****************************************************************************
6120 Deal with SMB_SET_POSIX_LOCK.
6121 ****************************************************************************/
6123 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6124 struct smb_request *req,
6132 bool blocking_lock = False;
6133 enum brl_type lock_type;
6135 NTSTATUS status = NT_STATUS_OK;
6137 if (fsp == NULL || fsp->fh->fd == -1) {
6138 return NT_STATUS_INVALID_HANDLE;
6141 if (total_data != POSIX_LOCK_DATA_SIZE) {
6142 return NT_STATUS_INVALID_PARAMETER;
6145 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6146 case POSIX_LOCK_TYPE_READ:
6147 lock_type = READ_LOCK;
6149 case POSIX_LOCK_TYPE_WRITE:
6150 /* Return the right POSIX-mappable error code for files opened read-only. */
6151 if (!fsp->can_write) {
6152 return NT_STATUS_INVALID_HANDLE;
6154 lock_type = WRITE_LOCK;
6156 case POSIX_LOCK_TYPE_UNLOCK:
6157 lock_type = UNLOCK_LOCK;
6160 return NT_STATUS_INVALID_PARAMETER;
6163 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6164 blocking_lock = False;
6165 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6166 blocking_lock = True;
6168 return NT_STATUS_INVALID_PARAMETER;
6171 if (!lp_blocking_locks(SNUM(conn))) {
6172 blocking_lock = False;
6175 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6176 #if defined(HAVE_LONGLONG)
6177 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6178 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6179 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6180 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6181 #else /* HAVE_LONGLONG */
6182 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6183 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6184 #endif /* HAVE_LONGLONG */
6186 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6187 "lock_pid = %u, count = %.0f, offset = %.0f\n",
6189 (unsigned int)lock_type,
6190 (unsigned int)lock_pid,
6194 if (lock_type == UNLOCK_LOCK) {
6195 status = do_unlock(smbd_messaging_context(),
6202 uint32 block_smbpid;
6204 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
6216 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6218 * A blocking lock was requested. Package up
6219 * this smb into a queued request and push it
6220 * onto the blocking lock queue.
6222 if(push_blocking_lock_request(br_lck,
6225 -1, /* infinite timeout. */
6233 TALLOC_FREE(br_lck);
6237 TALLOC_FREE(br_lck);
6243 /****************************************************************************
6244 Deal with SMB_SET_FILE_BASIC_INFO.
6245 ****************************************************************************/
6247 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6251 const struct smb_filename *smb_fname)
6253 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6254 struct smb_file_time ft;
6256 NTSTATUS status = NT_STATUS_OK;
6260 if (total_data < 36) {
6261 return NT_STATUS_INVALID_PARAMETER;
6264 /* Set the attributes */
6265 dosmode = IVAL(pdata,32);
6266 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6267 if (!NT_STATUS_IS_OK(status)) {
6272 ft.create_time = interpret_long_date(pdata);
6275 ft.atime = interpret_long_date(pdata+8);
6278 ft.mtime = interpret_long_date(pdata+16);
6281 ft.ctime = interpret_long_date(pdata+24);
6283 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6284 smb_fname_str_dbg(smb_fname)));
6286 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6290 /****************************************************************************
6291 Deal with SMB_INFO_STANDARD.
6292 ****************************************************************************/
6294 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6298 const struct smb_filename *smb_fname)
6300 struct smb_file_time ft;
6304 if (total_data < 12) {
6305 return NT_STATUS_INVALID_PARAMETER;
6309 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6311 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6313 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6315 DEBUG(10,("smb_set_info_standard: file %s\n",
6316 smb_fname_str_dbg(smb_fname)));
6318 return smb_set_file_time(conn,
6325 /****************************************************************************
6326 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6327 ****************************************************************************/
6329 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6330 struct smb_request *req,
6334 struct smb_filename *smb_fname)
6336 uint64_t allocation_size = 0;
6337 NTSTATUS status = NT_STATUS_OK;
6338 files_struct *new_fsp = NULL;
6340 if (!VALID_STAT(smb_fname->st)) {
6341 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6344 if (total_data < 8) {
6345 return NT_STATUS_INVALID_PARAMETER;
6348 allocation_size = (uint64_t)IVAL(pdata,0);
6349 #ifdef LARGE_SMB_OFF_T
6350 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6351 #else /* LARGE_SMB_OFF_T */
6352 if (IVAL(pdata,4) != 0) {
6353 /* more than 32 bits? */
6354 return NT_STATUS_INVALID_PARAMETER;
6356 #endif /* LARGE_SMB_OFF_T */
6358 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6359 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6360 (double)allocation_size));
6362 if (allocation_size) {
6363 allocation_size = smb_roundup(conn, allocation_size);
6366 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6367 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6368 (double)allocation_size));
6370 if (fsp && fsp->fh->fd != -1) {
6371 /* Open file handle. */
6372 /* Only change if needed. */
6373 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6374 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6375 return map_nt_error_from_unix(errno);
6378 /* But always update the time. */
6380 * This is equivalent to a write. Ensure it's seen immediately
6381 * if there are no pending writes.
6383 trigger_write_time_update_immediate(fsp);
6384 return NT_STATUS_OK;
6387 /* Pathname or stat or directory file. */
6388 status = SMB_VFS_CREATE_FILE(
6391 0, /* root_dir_fid */
6392 smb_fname, /* fname */
6393 FILE_WRITE_DATA, /* access_mask */
6394 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6396 FILE_OPEN, /* create_disposition*/
6397 0, /* create_options */
6398 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6399 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6400 0, /* allocation_size */
6403 &new_fsp, /* result */
6406 if (!NT_STATUS_IS_OK(status)) {
6407 /* NB. We check for open_was_deferred in the caller. */
6411 /* Only change if needed. */
6412 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6413 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6414 status = map_nt_error_from_unix(errno);
6415 close_file(req, new_fsp, NORMAL_CLOSE);
6420 /* Changing the allocation size should set the last mod time. */
6422 * This is equivalent to a write. Ensure it's seen immediately
6423 * if there are no pending writes.
6425 trigger_write_time_update_immediate(new_fsp);
6427 close_file(req, new_fsp, NORMAL_CLOSE);
6428 return NT_STATUS_OK;
6431 /****************************************************************************
6432 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6433 ****************************************************************************/
6435 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6436 struct smb_request *req,
6440 const struct smb_filename *smb_fname,
6441 bool fail_after_createfile)
6445 if (total_data < 8) {
6446 return NT_STATUS_INVALID_PARAMETER;
6449 size = IVAL(pdata,0);
6450 #ifdef LARGE_SMB_OFF_T
6451 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6452 #else /* LARGE_SMB_OFF_T */
6453 if (IVAL(pdata,4) != 0) {
6454 /* more than 32 bits? */
6455 return NT_STATUS_INVALID_PARAMETER;
6457 #endif /* LARGE_SMB_OFF_T */
6458 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6459 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6462 return smb_set_file_size(conn, req,
6467 fail_after_createfile);
6470 /****************************************************************************
6471 Allow a UNIX info mknod.
6472 ****************************************************************************/
6474 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6477 const struct smb_filename *smb_fname)
6479 uint32 file_type = IVAL(pdata,56);
6480 #if defined(HAVE_MAKEDEV)
6481 uint32 dev_major = IVAL(pdata,60);
6482 uint32 dev_minor = IVAL(pdata,68);
6484 SMB_DEV_T dev = (SMB_DEV_T)0;
6485 uint32 raw_unixmode = IVAL(pdata,84);
6489 if (total_data < 100) {
6490 return NT_STATUS_INVALID_PARAMETER;
6493 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6494 PERM_NEW_FILE, &unixmode);
6495 if (!NT_STATUS_IS_OK(status)) {
6499 #if defined(HAVE_MAKEDEV)
6500 dev = makedev(dev_major, dev_minor);
6503 switch (file_type) {
6504 #if defined(S_IFIFO)
6505 case UNIX_TYPE_FIFO:
6506 unixmode |= S_IFIFO;
6509 #if defined(S_IFSOCK)
6510 case UNIX_TYPE_SOCKET:
6511 unixmode |= S_IFSOCK;
6514 #if defined(S_IFCHR)
6515 case UNIX_TYPE_CHARDEV:
6516 unixmode |= S_IFCHR;
6519 #if defined(S_IFBLK)
6520 case UNIX_TYPE_BLKDEV:
6521 unixmode |= S_IFBLK;
6525 return NT_STATUS_INVALID_PARAMETER;
6528 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6529 "%.0f mode 0%o for file %s\n", (double)dev,
6530 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6532 /* Ok - do the mknod. */
6533 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6534 return map_nt_error_from_unix(errno);
6537 /* If any of the other "set" calls fail we
6538 * don't want to end up with a half-constructed mknod.
6541 if (lp_inherit_perms(SNUM(conn))) {
6543 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6545 return NT_STATUS_NO_MEMORY;
6547 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6549 TALLOC_FREE(parent);
6552 return NT_STATUS_OK;
6555 /****************************************************************************
6556 Deal with SMB_SET_FILE_UNIX_BASIC.
6557 ****************************************************************************/
6559 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6560 struct smb_request *req,
6564 const struct smb_filename *smb_fname)
6566 struct smb_file_time ft;
6567 uint32 raw_unixmode;
6570 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6571 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6572 NTSTATUS status = NT_STATUS_OK;
6573 bool delete_on_fail = False;
6574 enum perm_type ptype;
6575 files_struct *all_fsps = NULL;
6576 bool modify_mtime = true;
6578 SMB_STRUCT_STAT sbuf;
6582 if (total_data < 100) {
6583 return NT_STATUS_INVALID_PARAMETER;
6586 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6587 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6588 size=IVAL(pdata,0); /* first 8 Bytes are size */
6589 #ifdef LARGE_SMB_OFF_T
6590 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6591 #else /* LARGE_SMB_OFF_T */
6592 if (IVAL(pdata,4) != 0) {
6593 /* more than 32 bits? */
6594 return NT_STATUS_INVALID_PARAMETER;
6596 #endif /* LARGE_SMB_OFF_T */
6599 ft.atime = interpret_long_date(pdata+24); /* access_time */
6600 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6601 set_owner = (uid_t)IVAL(pdata,40);
6602 set_grp = (gid_t)IVAL(pdata,48);
6603 raw_unixmode = IVAL(pdata,84);
6605 if (VALID_STAT(smb_fname->st)) {
6606 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6607 ptype = PERM_EXISTING_DIR;
6609 ptype = PERM_EXISTING_FILE;
6612 ptype = PERM_NEW_FILE;
6615 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6617 if (!NT_STATUS_IS_OK(status)) {
6621 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6622 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6623 smb_fname_str_dbg(smb_fname), (double)size,
6624 (unsigned int)set_owner, (unsigned int)set_grp,
6625 (int)raw_unixmode));
6627 sbuf = smb_fname->st;
6629 if (!VALID_STAT(sbuf)) {
6630 struct smb_filename *smb_fname_tmp = NULL;
6632 * The only valid use of this is to create character and block
6633 * devices, and named pipes. This is deprecated (IMHO) and
6634 * a new info level should be used for mknod. JRA.
6637 status = smb_unix_mknod(conn,
6641 if (!NT_STATUS_IS_OK(status)) {
6645 status = copy_smb_filename(talloc_tos(), smb_fname,
6647 if (!NT_STATUS_IS_OK(status)) {
6651 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6652 status = map_nt_error_from_unix(errno);
6653 TALLOC_FREE(smb_fname_tmp);
6654 SMB_VFS_UNLINK(conn, smb_fname);
6658 sbuf = smb_fname_tmp->st;
6659 TALLOC_FREE(smb_fname_tmp);
6661 /* Ensure we don't try and change anything else. */
6662 raw_unixmode = SMB_MODE_NO_CHANGE;
6663 size = get_file_size_stat(&sbuf);
6664 ft.atime = sbuf.st_ex_atime;
6665 ft.mtime = sbuf.st_ex_mtime;
6667 * We continue here as we might want to change the
6670 delete_on_fail = True;
6674 /* Horrible backwards compatibility hack as an old server bug
6675 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6679 size = get_file_size_stat(&sbuf);
6684 * Deal with the UNIX specific mode set.
6687 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6688 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6689 "setting mode 0%o for file %s\n",
6690 (unsigned int)unixmode,
6691 smb_fname_str_dbg(smb_fname)));
6692 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6693 return map_nt_error_from_unix(errno);
6698 * Deal with the UNIX specific uid set.
6701 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6702 (sbuf.st_ex_uid != set_owner)) {
6705 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6706 "changing owner %u for path %s\n",
6707 (unsigned int)set_owner,
6708 smb_fname_str_dbg(smb_fname)));
6710 if (S_ISLNK(sbuf.st_ex_mode)) {
6711 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6712 set_owner, (gid_t)-1);
6714 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6715 set_owner, (gid_t)-1);
6719 status = map_nt_error_from_unix(errno);
6720 if (delete_on_fail) {
6721 SMB_VFS_UNLINK(conn, smb_fname);
6728 * Deal with the UNIX specific gid set.
6731 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6732 (sbuf.st_ex_gid != set_grp)) {
6733 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6734 "changing group %u for file %s\n",
6735 (unsigned int)set_owner,
6736 smb_fname_str_dbg(smb_fname)));
6737 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6739 status = map_nt_error_from_unix(errno);
6740 if (delete_on_fail) {
6741 SMB_VFS_UNLINK(conn, smb_fname);
6747 /* Deal with any size changes. */
6749 status = smb_set_file_size(conn, req,
6755 if (!NT_STATUS_IS_OK(status)) {
6759 /* Deal with any time changes. */
6760 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6761 /* No change, don't cancel anything. */
6765 id = vfs_file_id_from_sbuf(conn, &sbuf);
6766 for(all_fsps = file_find_di_first(id); all_fsps;
6767 all_fsps = file_find_di_next(all_fsps)) {
6769 * We're setting the time explicitly for UNIX.
6770 * Cancel any pending changes over all handles.
6772 all_fsps->update_write_time_on_close = false;
6773 TALLOC_FREE(all_fsps->update_write_time_event);
6777 * Override the "setting_write_time"
6778 * parameter here as it almost does what
6779 * we need. Just remember if we modified
6780 * mtime and send the notify ourselves.
6782 if (null_timespec(ft.mtime)) {
6783 modify_mtime = false;
6786 status = smb_set_file_time(conn,
6792 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6793 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6798 /****************************************************************************
6799 Deal with SMB_SET_FILE_UNIX_INFO2.
6800 ****************************************************************************/
6802 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6803 struct smb_request *req,
6807 const struct smb_filename *smb_fname)
6813 if (total_data < 116) {
6814 return NT_STATUS_INVALID_PARAMETER;
6817 /* Start by setting all the fields that are common between UNIX_BASIC
6820 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6822 if (!NT_STATUS_IS_OK(status)) {
6826 smb_fflags = IVAL(pdata, 108);
6827 smb_fmask = IVAL(pdata, 112);
6829 /* NB: We should only attempt to alter the file flags if the client
6830 * sends a non-zero mask.
6832 if (smb_fmask != 0) {
6833 int stat_fflags = 0;
6835 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6836 smb_fmask, &stat_fflags)) {
6837 /* Client asked to alter a flag we don't understand. */
6838 return NT_STATUS_INVALID_PARAMETER;
6841 if (fsp && fsp->fh->fd != -1) {
6842 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6843 return NT_STATUS_NOT_SUPPORTED;
6845 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
6846 stat_fflags) != 0) {
6847 return map_nt_error_from_unix(errno);
6852 /* XXX: need to add support for changing the create_time here. You
6853 * can do this for paths on Darwin with setattrlist(2). The right way
6854 * to hook this up is probably by extending the VFS utimes interface.
6857 return NT_STATUS_OK;
6860 /****************************************************************************
6861 Create a directory with POSIX semantics.
6862 ****************************************************************************/
6864 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6865 struct smb_request *req,
6868 struct smb_filename *smb_fname,
6869 int *pdata_return_size)
6871 NTSTATUS status = NT_STATUS_OK;
6872 uint32 raw_unixmode = 0;
6873 uint32 mod_unixmode = 0;
6874 mode_t unixmode = (mode_t)0;
6875 files_struct *fsp = NULL;
6876 uint16 info_level_return = 0;
6878 char *pdata = *ppdata;
6880 if (total_data < 18) {
6881 return NT_STATUS_INVALID_PARAMETER;
6884 raw_unixmode = IVAL(pdata,8);
6885 /* Next 4 bytes are not yet defined. */
6887 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6888 PERM_NEW_DIR, &unixmode);
6889 if (!NT_STATUS_IS_OK(status)) {
6893 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6895 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6896 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
6898 status = SMB_VFS_CREATE_FILE(
6901 0, /* root_dir_fid */
6902 smb_fname, /* fname */
6903 FILE_READ_ATTRIBUTES, /* access_mask */
6904 FILE_SHARE_NONE, /* share_access */
6905 FILE_CREATE, /* create_disposition*/
6906 FILE_DIRECTORY_FILE, /* create_options */
6907 mod_unixmode, /* file_attributes */
6908 0, /* oplock_request */
6909 0, /* allocation_size */
6915 if (NT_STATUS_IS_OK(status)) {
6916 close_file(req, fsp, NORMAL_CLOSE);
6919 info_level_return = SVAL(pdata,16);
6921 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6922 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6923 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6924 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6926 *pdata_return_size = 12;
6929 /* Realloc the data size */
6930 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6931 if (*ppdata == NULL) {
6932 *pdata_return_size = 0;
6933 return NT_STATUS_NO_MEMORY;
6937 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6938 SSVAL(pdata,2,0); /* No fnum. */
6939 SIVAL(pdata,4,info); /* Was directory created. */
6941 switch (info_level_return) {
6942 case SMB_QUERY_FILE_UNIX_BASIC:
6943 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6944 SSVAL(pdata,10,0); /* Padding. */
6945 store_file_unix_basic(conn, pdata + 12, fsp,
6948 case SMB_QUERY_FILE_UNIX_INFO2:
6949 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6950 SSVAL(pdata,10,0); /* Padding. */
6951 store_file_unix_basic_info2(conn, pdata + 12, fsp,
6955 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6956 SSVAL(pdata,10,0); /* Padding. */
6963 /****************************************************************************
6964 Open/Create a file with POSIX semantics.
6965 ****************************************************************************/
6967 static NTSTATUS smb_posix_open(connection_struct *conn,
6968 struct smb_request *req,
6971 struct smb_filename *smb_fname,
6972 int *pdata_return_size)
6974 bool extended_oplock_granted = False;
6975 char *pdata = *ppdata;
6977 uint32 wire_open_mode = 0;
6978 uint32 raw_unixmode = 0;
6979 uint32 mod_unixmode = 0;
6980 uint32 create_disp = 0;
6981 uint32 access_mask = 0;
6982 uint32 create_options = 0;
6983 NTSTATUS status = NT_STATUS_OK;
6984 mode_t unixmode = (mode_t)0;
6985 files_struct *fsp = NULL;
6986 int oplock_request = 0;
6988 uint16 info_level_return = 0;
6990 if (total_data < 18) {
6991 return NT_STATUS_INVALID_PARAMETER;
6994 flags = IVAL(pdata,0);
6995 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6996 if (oplock_request) {
6997 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7000 wire_open_mode = IVAL(pdata,4);
7002 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7003 return smb_posix_mkdir(conn, req,
7010 switch (wire_open_mode & SMB_ACCMODE) {
7012 access_mask = FILE_READ_DATA;
7015 access_mask = FILE_WRITE_DATA;
7018 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
7021 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7022 (unsigned int)wire_open_mode ));
7023 return NT_STATUS_INVALID_PARAMETER;
7026 wire_open_mode &= ~SMB_ACCMODE;
7028 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
7029 create_disp = FILE_CREATE;
7030 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
7031 create_disp = FILE_OVERWRITE_IF;
7032 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
7033 create_disp = FILE_OPEN_IF;
7034 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
7035 create_disp = FILE_OPEN;
7037 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7038 (unsigned int)wire_open_mode ));
7039 return NT_STATUS_INVALID_PARAMETER;
7042 raw_unixmode = IVAL(pdata,8);
7043 /* Next 4 bytes are not yet defined. */
7045 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7046 (VALID_STAT(smb_fname->st) ?
7047 PERM_EXISTING_FILE : PERM_NEW_FILE),
7050 if (!NT_STATUS_IS_OK(status)) {
7054 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7056 if (wire_open_mode & SMB_O_SYNC) {
7057 create_options |= FILE_WRITE_THROUGH;
7059 if (wire_open_mode & SMB_O_APPEND) {
7060 access_mask |= FILE_APPEND_DATA;
7062 if (wire_open_mode & SMB_O_DIRECT) {
7063 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7066 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7067 smb_fname_str_dbg(smb_fname),
7068 (unsigned int)wire_open_mode,
7069 (unsigned int)unixmode ));
7071 status = SMB_VFS_CREATE_FILE(
7074 0, /* root_dir_fid */
7075 smb_fname, /* fname */
7076 access_mask, /* access_mask */
7077 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7079 create_disp, /* create_disposition*/
7080 FILE_NON_DIRECTORY_FILE, /* create_options */
7081 mod_unixmode, /* file_attributes */
7082 oplock_request, /* oplock_request */
7083 0, /* allocation_size */
7089 if (!NT_STATUS_IS_OK(status)) {
7093 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7094 extended_oplock_granted = True;
7097 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7098 extended_oplock_granted = True;
7101 info_level_return = SVAL(pdata,16);
7103 /* Allocate the correct return size. */
7105 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7106 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7107 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7108 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7110 *pdata_return_size = 12;
7113 /* Realloc the data size */
7114 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7115 if (*ppdata == NULL) {
7116 close_file(req, fsp, ERROR_CLOSE);
7117 *pdata_return_size = 0;
7118 return NT_STATUS_NO_MEMORY;
7122 if (extended_oplock_granted) {
7123 if (flags & REQUEST_BATCH_OPLOCK) {
7124 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7126 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7128 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7129 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7131 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7134 SSVAL(pdata,2,fsp->fnum);
7135 SIVAL(pdata,4,info); /* Was file created etc. */
7137 switch (info_level_return) {
7138 case SMB_QUERY_FILE_UNIX_BASIC:
7139 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7140 SSVAL(pdata,10,0); /* padding. */
7141 store_file_unix_basic(conn, pdata + 12, fsp,
7144 case SMB_QUERY_FILE_UNIX_INFO2:
7145 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7146 SSVAL(pdata,10,0); /* padding. */
7147 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7151 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7152 SSVAL(pdata,10,0); /* padding. */
7155 return NT_STATUS_OK;
7158 /****************************************************************************
7159 Delete a file with POSIX semantics.
7160 ****************************************************************************/
7162 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7163 struct smb_request *req,
7166 struct smb_filename *smb_fname)
7168 NTSTATUS status = NT_STATUS_OK;
7169 files_struct *fsp = NULL;
7173 int create_options = 0;
7175 struct share_mode_lock *lck = NULL;
7177 if (total_data < 2) {
7178 return NT_STATUS_INVALID_PARAMETER;
7181 flags = SVAL(pdata,0);
7183 if (!VALID_STAT(smb_fname->st)) {
7184 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7187 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7188 !VALID_STAT_OF_DIR(smb_fname->st)) {
7189 return NT_STATUS_NOT_A_DIRECTORY;
7192 DEBUG(10,("smb_posix_unlink: %s %s\n",
7193 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7194 smb_fname_str_dbg(smb_fname)));
7196 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7197 create_options |= FILE_DIRECTORY_FILE;
7200 status = SMB_VFS_CREATE_FILE(
7203 0, /* root_dir_fid */
7204 smb_fname, /* fname */
7205 DELETE_ACCESS, /* access_mask */
7206 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7208 FILE_OPEN, /* create_disposition*/
7209 create_options, /* create_options */
7210 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7211 0, /* oplock_request */
7212 0, /* allocation_size */
7218 if (!NT_STATUS_IS_OK(status)) {
7223 * Don't lie to client. If we can't really delete due to
7224 * non-POSIX opens return SHARING_VIOLATION.
7227 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7230 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7231 "lock for file %s\n", fsp_str_dbg(fsp)));
7232 close_file(req, fsp, NORMAL_CLOSE);
7233 return NT_STATUS_INVALID_PARAMETER;
7237 * See if others still have the file open. If this is the case, then
7238 * don't delete. If all opens are POSIX delete we can set the delete
7239 * on close disposition.
7241 for (i=0; i<lck->num_share_modes; i++) {
7242 struct share_mode_entry *e = &lck->share_modes[i];
7243 if (is_valid_share_mode_entry(e)) {
7244 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7247 /* Fail with sharing violation. */
7248 close_file(req, fsp, NORMAL_CLOSE);
7250 return NT_STATUS_SHARING_VIOLATION;
7255 * Set the delete on close.
7257 status = smb_set_file_disposition_info(conn,
7263 if (!NT_STATUS_IS_OK(status)) {
7264 close_file(req, fsp, NORMAL_CLOSE);
7269 return close_file(req, fsp, NORMAL_CLOSE);
7272 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7273 struct smb_request *req,
7274 TALLOC_CTX *mem_ctx,
7275 uint16_t info_level,
7277 struct smb_filename *smb_fname,
7278 char **ppdata, int total_data,
7281 char *pdata = *ppdata;
7282 NTSTATUS status = NT_STATUS_OK;
7283 int data_return_size = 0;
7287 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7288 return NT_STATUS_INVALID_LEVEL;
7291 if (!CAN_WRITE(conn)) {
7292 /* Allow POSIX opens. The open path will deny
7293 * any non-readonly opens. */
7294 if (info_level != SMB_POSIX_PATH_OPEN) {
7295 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7299 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7300 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7301 fsp ? fsp->fnum : -1, info_level, total_data));
7303 switch (info_level) {
7305 case SMB_INFO_STANDARD:
7307 status = smb_set_info_standard(conn,
7315 case SMB_INFO_SET_EA:
7317 status = smb_info_set_ea(conn,
7325 case SMB_SET_FILE_BASIC_INFO:
7326 case SMB_FILE_BASIC_INFORMATION:
7328 status = smb_set_file_basic_info(conn,
7336 case SMB_FILE_ALLOCATION_INFORMATION:
7337 case SMB_SET_FILE_ALLOCATION_INFO:
7339 status = smb_set_file_allocation_info(conn, req,
7347 case SMB_FILE_END_OF_FILE_INFORMATION:
7348 case SMB_SET_FILE_END_OF_FILE_INFO:
7351 * XP/Win7 both fail after the createfile with
7352 * SMB_SET_FILE_END_OF_FILE_INFO but not
7353 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7354 * The level is known here, so pass it down
7358 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7360 status = smb_set_file_end_of_file_info(conn, req,
7369 case SMB_FILE_DISPOSITION_INFORMATION:
7370 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7373 /* JRA - We used to just ignore this on a path ?
7374 * Shouldn't this be invalid level on a pathname
7377 if (tran_call != TRANSACT2_SETFILEINFO) {
7378 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7381 status = smb_set_file_disposition_info(conn,
7389 case SMB_FILE_POSITION_INFORMATION:
7391 status = smb_file_position_information(conn,
7398 case SMB_FILE_FULL_EA_INFORMATION:
7400 status = smb_set_file_full_ea_info(conn,
7407 /* From tridge Samba4 :
7408 * MODE_INFORMATION in setfileinfo (I have no
7409 * idea what "mode information" on a file is - it takes a value of 0,
7410 * 2, 4 or 6. What could it be?).
7413 case SMB_FILE_MODE_INFORMATION:
7415 status = smb_file_mode_information(conn,
7422 * CIFS UNIX extensions.
7425 case SMB_SET_FILE_UNIX_BASIC:
7427 status = smb_set_file_unix_basic(conn, req,
7435 case SMB_SET_FILE_UNIX_INFO2:
7437 status = smb_set_file_unix_info2(conn, req,
7445 case SMB_SET_FILE_UNIX_LINK:
7448 /* We must have a pathname for this. */
7449 return NT_STATUS_INVALID_LEVEL;
7451 status = smb_set_file_unix_link(conn, req, pdata,
7452 total_data, smb_fname);
7456 case SMB_SET_FILE_UNIX_HLINK:
7459 /* We must have a pathname for this. */
7460 return NT_STATUS_INVALID_LEVEL;
7462 status = smb_set_file_unix_hlink(conn, req,
7468 case SMB_FILE_RENAME_INFORMATION:
7470 status = smb_file_rename_information(conn, req,
7476 #if defined(HAVE_POSIX_ACLS)
7477 case SMB_SET_POSIX_ACL:
7479 status = smb_set_posix_acl(conn,
7488 case SMB_SET_POSIX_LOCK:
7491 return NT_STATUS_INVALID_LEVEL;
7493 status = smb_set_posix_lock(conn, req,
7494 pdata, total_data, fsp);
7498 case SMB_POSIX_PATH_OPEN:
7501 /* We must have a pathname for this. */
7502 return NT_STATUS_INVALID_LEVEL;
7505 status = smb_posix_open(conn, req,
7513 case SMB_POSIX_PATH_UNLINK:
7516 /* We must have a pathname for this. */
7517 return NT_STATUS_INVALID_LEVEL;
7520 status = smb_posix_unlink(conn, req,
7528 return NT_STATUS_INVALID_LEVEL;
7531 if (!NT_STATUS_IS_OK(status)) {
7535 *ret_data_size = data_return_size;
7536 return NT_STATUS_OK;
7539 /****************************************************************************
7540 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7541 ****************************************************************************/
7543 static void call_trans2setfilepathinfo(connection_struct *conn,
7544 struct smb_request *req,
7545 unsigned int tran_call,
7546 char **pparams, int total_params,
7547 char **ppdata, int total_data,
7548 unsigned int max_data_bytes)
7550 char *params = *pparams;
7551 char *pdata = *ppdata;
7553 struct smb_filename *smb_fname = NULL;
7554 files_struct *fsp = NULL;
7555 NTSTATUS status = NT_STATUS_OK;
7556 int data_return_size = 0;
7559 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7563 if (tran_call == TRANSACT2_SETFILEINFO) {
7564 if (total_params < 4) {
7565 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7569 fsp = file_fsp(req, SVAL(params,0));
7570 /* Basic check for non-null fsp. */
7571 if (!check_fsp_open(conn, req, fsp)) {
7574 info_level = SVAL(params,2);
7576 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7578 if (!NT_STATUS_IS_OK(status)) {
7579 reply_nterror(req, status);
7583 if(fsp->is_directory || fsp->fh->fd == -1) {
7585 * This is actually a SETFILEINFO on a directory
7586 * handle (returned from an NT SMB). NT5.0 seems
7587 * to do this call. JRA.
7589 if (INFO_LEVEL_IS_UNIX(info_level)) {
7590 /* Always do lstat for UNIX calls. */
7591 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7592 DEBUG(3,("call_trans2setfilepathinfo: "
7593 "SMB_VFS_LSTAT of %s failed "
7595 smb_fname_str_dbg(smb_fname),
7597 reply_nterror(req, map_nt_error_from_unix(errno));
7601 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7602 DEBUG(3,("call_trans2setfilepathinfo: "
7603 "fileinfo of %s failed (%s)\n",
7604 smb_fname_str_dbg(smb_fname),
7606 reply_nterror(req, map_nt_error_from_unix(errno));
7610 } else if (fsp->print_file) {
7612 * Doing a DELETE_ON_CLOSE should cancel a print job.
7614 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7615 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
7617 DEBUG(3,("call_trans2setfilepathinfo: "
7618 "Cancelling print job (%s)\n",
7622 send_trans2_replies(conn, req, params, 2,
7628 NT_STATUS_OBJECT_PATH_NOT_FOUND);
7633 * Original code - this is an open file.
7635 if (!check_fsp(conn, req, fsp)) {
7639 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7640 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7641 "of fnum %d failed (%s)\n", fsp->fnum,
7643 reply_nterror(req, map_nt_error_from_unix(errno));
7651 if (total_params < 7) {
7652 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7656 info_level = SVAL(params,0);
7657 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
7658 total_params - 6, STR_TERMINATE,
7660 if (!NT_STATUS_IS_OK(status)) {
7661 reply_nterror(req, status);
7665 status = filename_convert(req, conn,
7666 req->flags2 & FLAGS2_DFS_PATHNAMES,
7671 if (!NT_STATUS_IS_OK(status)) {
7672 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7673 reply_botherror(req,
7674 NT_STATUS_PATH_NOT_COVERED,
7675 ERRSRV, ERRbadpath);
7678 reply_nterror(req, status);
7682 if (INFO_LEVEL_IS_UNIX(info_level)) {
7684 * For CIFS UNIX extensions the target name may not exist.
7687 /* Always do lstat for UNIX calls. */
7688 SMB_VFS_LSTAT(conn, smb_fname);
7690 } else if (!VALID_STAT(smb_fname->st) &&
7691 SMB_VFS_STAT(conn, smb_fname)) {
7692 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7694 smb_fname_str_dbg(smb_fname),
7696 reply_nterror(req, map_nt_error_from_unix(errno));
7701 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7702 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
7703 fsp ? fsp->fnum : -1, info_level,total_data));
7705 /* Realloc the parameter size */
7706 *pparams = (char *)SMB_REALLOC(*pparams,2);
7707 if (*pparams == NULL) {
7708 reply_nterror(req, NT_STATUS_NO_MEMORY);
7715 status = smbd_do_setfilepathinfo(conn, req, req,
7721 if (!NT_STATUS_IS_OK(status)) {
7722 if (open_was_deferred(req->mid)) {
7723 /* We have re-scheduled this call. */
7726 if (blocking_lock_was_deferred(req->mid)) {
7727 /* We have re-scheduled this call. */
7730 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7731 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7732 ERRSRV, ERRbadpath);
7735 if (info_level == SMB_POSIX_PATH_OPEN) {
7736 reply_openerror(req, status);
7740 reply_nterror(req, status);
7744 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7750 /****************************************************************************
7751 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7752 ****************************************************************************/
7754 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7755 char **pparams, int total_params,
7756 char **ppdata, int total_data,
7757 unsigned int max_data_bytes)
7759 struct smb_filename *smb_dname = NULL;
7760 char *params = *pparams;
7761 char *pdata = *ppdata;
7762 char *directory = NULL;
7763 NTSTATUS status = NT_STATUS_OK;
7764 struct ea_list *ea_list = NULL;
7765 TALLOC_CTX *ctx = talloc_tos();
7767 if (!CAN_WRITE(conn)) {
7768 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7772 if (total_params < 5) {
7773 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7777 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7778 total_params - 4, STR_TERMINATE,
7780 if (!NT_STATUS_IS_OK(status)) {
7781 reply_nterror(req, status);
7785 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7787 status = filename_convert(ctx,
7789 req->flags2 & FLAGS2_DFS_PATHNAMES,
7795 if (!NT_STATUS_IS_OK(status)) {
7796 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7797 reply_botherror(req,
7798 NT_STATUS_PATH_NOT_COVERED,
7799 ERRSRV, ERRbadpath);
7802 reply_nterror(req, status);
7807 * OS/2 workplace shell seems to send SET_EA requests of "null"
7808 * length (4 bytes containing IVAL 4).
7809 * They seem to have no effect. Bug #3212. JRA.
7812 if (total_data && (total_data != 4)) {
7813 /* Any data in this call is an EA list. */
7814 if (total_data < 10) {
7815 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7819 if (IVAL(pdata,0) > total_data) {
7820 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7821 IVAL(pdata,0), (unsigned int)total_data));
7822 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7826 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7829 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7833 if (!lp_ea_support(SNUM(conn))) {
7834 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7838 /* If total_data == 4 Windows doesn't care what values
7839 * are placed in that field, it just ignores them.
7840 * The System i QNTC IBM SMB client puts bad values here,
7841 * so ignore them. */
7843 status = create_directory(conn, req, smb_dname);
7845 if (!NT_STATUS_IS_OK(status)) {
7846 reply_nterror(req, status);
7850 /* Try and set any given EA. */
7852 status = set_ea(conn, NULL, smb_dname, ea_list);
7853 if (!NT_STATUS_IS_OK(status)) {
7854 reply_nterror(req, status);
7859 /* Realloc the parameter and data sizes */
7860 *pparams = (char *)SMB_REALLOC(*pparams,2);
7861 if(*pparams == NULL) {
7862 reply_nterror(req, NT_STATUS_NO_MEMORY);
7869 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7872 TALLOC_FREE(smb_dname);
7876 /****************************************************************************
7877 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7878 We don't actually do this - we just send a null response.
7879 ****************************************************************************/
7881 static void call_trans2findnotifyfirst(connection_struct *conn,
7882 struct smb_request *req,
7883 char **pparams, int total_params,
7884 char **ppdata, int total_data,
7885 unsigned int max_data_bytes)
7887 char *params = *pparams;
7890 if (total_params < 6) {
7891 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7895 info_level = SVAL(params,4);
7896 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7898 switch (info_level) {
7903 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7907 /* Realloc the parameter and data sizes */
7908 *pparams = (char *)SMB_REALLOC(*pparams,6);
7909 if (*pparams == NULL) {
7910 reply_nterror(req, NT_STATUS_NO_MEMORY);
7915 SSVAL(params,0,fnf_handle);
7916 SSVAL(params,2,0); /* No changes */
7917 SSVAL(params,4,0); /* No EA errors */
7924 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7929 /****************************************************************************
7930 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7931 changes). Currently this does nothing.
7932 ****************************************************************************/
7934 static void call_trans2findnotifynext(connection_struct *conn,
7935 struct smb_request *req,
7936 char **pparams, int total_params,
7937 char **ppdata, int total_data,
7938 unsigned int max_data_bytes)
7940 char *params = *pparams;
7942 DEBUG(3,("call_trans2findnotifynext\n"));
7944 /* Realloc the parameter and data sizes */
7945 *pparams = (char *)SMB_REALLOC(*pparams,4);
7946 if (*pparams == NULL) {
7947 reply_nterror(req, NT_STATUS_NO_MEMORY);
7952 SSVAL(params,0,0); /* No changes */
7953 SSVAL(params,2,0); /* No EA errors */
7955 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7960 /****************************************************************************
7961 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7962 ****************************************************************************/
7964 static void call_trans2getdfsreferral(connection_struct *conn,
7965 struct smb_request *req,
7966 char **pparams, int total_params,
7967 char **ppdata, int total_data,
7968 unsigned int max_data_bytes)
7970 char *params = *pparams;
7971 char *pathname = NULL;
7973 int max_referral_level;
7974 NTSTATUS status = NT_STATUS_OK;
7975 TALLOC_CTX *ctx = talloc_tos();
7977 DEBUG(10,("call_trans2getdfsreferral\n"));
7979 if (total_params < 3) {
7980 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7984 max_referral_level = SVAL(params,0);
7986 if(!lp_host_msdfs()) {
7987 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
7991 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7992 total_params - 2, STR_TERMINATE);
7994 reply_nterror(req, NT_STATUS_NOT_FOUND);
7997 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7998 ppdata,&status)) < 0) {
7999 reply_nterror(req, status);
8003 SSVAL(req->inbuf, smb_flg2,
8004 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8005 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8010 #define LMCAT_SPL 0x53
8011 #define LMFUNC_GETJOBID 0x60
8013 /****************************************************************************
8014 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8015 ****************************************************************************/
8017 static void call_trans2ioctl(connection_struct *conn,
8018 struct smb_request *req,
8019 char **pparams, int total_params,
8020 char **ppdata, int total_data,
8021 unsigned int max_data_bytes)
8023 char *pdata = *ppdata;
8024 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8026 /* check for an invalid fid before proceeding */
8029 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8033 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8034 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8035 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8036 if (*ppdata == NULL) {
8037 reply_nterror(req, NT_STATUS_NO_MEMORY);
8042 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8043 CAN ACCEPT THIS IN UNICODE. JRA. */
8045 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
8046 srvstr_push(pdata, req->flags2, pdata + 2,
8047 global_myname(), 15,
8048 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8049 srvstr_push(pdata, req->flags2, pdata+18,
8050 lp_servicename(SNUM(conn)), 13,
8051 STR_ASCII|STR_TERMINATE); /* Service name */
8052 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8057 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8058 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8061 /****************************************************************************
8062 Reply to a SMBfindclose (stop trans2 directory search).
8063 ****************************************************************************/
8065 void reply_findclose(struct smb_request *req)
8068 struct smbd_server_connection *sconn = smbd_server_conn;
8070 START_PROFILE(SMBfindclose);
8073 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8074 END_PROFILE(SMBfindclose);
8078 dptr_num = SVALS(req->vwv+0, 0);
8080 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8082 dptr_close(sconn, &dptr_num);
8084 reply_outbuf(req, 0, 0);
8086 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8088 END_PROFILE(SMBfindclose);
8092 /****************************************************************************
8093 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8094 ****************************************************************************/
8096 void reply_findnclose(struct smb_request *req)
8100 START_PROFILE(SMBfindnclose);
8103 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8104 END_PROFILE(SMBfindnclose);
8108 dptr_num = SVAL(req->vwv+0, 0);
8110 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8112 /* We never give out valid handles for a
8113 findnotifyfirst - so any dptr_num is ok here.
8116 reply_outbuf(req, 0, 0);
8118 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8120 END_PROFILE(SMBfindnclose);
8124 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8125 struct trans_state *state)
8127 if (get_Protocol() >= PROTOCOL_NT1) {
8128 req->flags2 |= 0x40; /* IS_LONG_NAME */
8129 SSVAL(req->inbuf,smb_flg2,req->flags2);
8132 if (conn->encrypt_level == Required && !req->encrypted) {
8133 if (state->call != TRANSACT2_QFSINFO &&
8134 state->call != TRANSACT2_SETFSINFO) {
8135 DEBUG(0,("handle_trans2: encryption required "
8137 (unsigned int)state->call));
8138 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8143 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8145 /* Now we must call the relevant TRANS2 function */
8146 switch(state->call) {
8147 case TRANSACT2_OPEN:
8149 START_PROFILE(Trans2_open);
8150 call_trans2open(conn, req,
8151 &state->param, state->total_param,
8152 &state->data, state->total_data,
8153 state->max_data_return);
8154 END_PROFILE(Trans2_open);
8158 case TRANSACT2_FINDFIRST:
8160 START_PROFILE(Trans2_findfirst);
8161 call_trans2findfirst(conn, req,
8162 &state->param, state->total_param,
8163 &state->data, state->total_data,
8164 state->max_data_return);
8165 END_PROFILE(Trans2_findfirst);
8169 case TRANSACT2_FINDNEXT:
8171 START_PROFILE(Trans2_findnext);
8172 call_trans2findnext(conn, req,
8173 &state->param, state->total_param,
8174 &state->data, state->total_data,
8175 state->max_data_return);
8176 END_PROFILE(Trans2_findnext);
8180 case TRANSACT2_QFSINFO:
8182 START_PROFILE(Trans2_qfsinfo);
8183 call_trans2qfsinfo(conn, req,
8184 &state->param, state->total_param,
8185 &state->data, state->total_data,
8186 state->max_data_return);
8187 END_PROFILE(Trans2_qfsinfo);
8191 case TRANSACT2_SETFSINFO:
8193 START_PROFILE(Trans2_setfsinfo);
8194 call_trans2setfsinfo(conn, req,
8195 &state->param, state->total_param,
8196 &state->data, state->total_data,
8197 state->max_data_return);
8198 END_PROFILE(Trans2_setfsinfo);
8202 case TRANSACT2_QPATHINFO:
8203 case TRANSACT2_QFILEINFO:
8205 START_PROFILE(Trans2_qpathinfo);
8206 call_trans2qfilepathinfo(conn, req, state->call,
8207 &state->param, state->total_param,
8208 &state->data, state->total_data,
8209 state->max_data_return);
8210 END_PROFILE(Trans2_qpathinfo);
8214 case TRANSACT2_SETPATHINFO:
8215 case TRANSACT2_SETFILEINFO:
8217 START_PROFILE(Trans2_setpathinfo);
8218 call_trans2setfilepathinfo(conn, req, state->call,
8219 &state->param, state->total_param,
8220 &state->data, state->total_data,
8221 state->max_data_return);
8222 END_PROFILE(Trans2_setpathinfo);
8226 case TRANSACT2_FINDNOTIFYFIRST:
8228 START_PROFILE(Trans2_findnotifyfirst);
8229 call_trans2findnotifyfirst(conn, req,
8230 &state->param, state->total_param,
8231 &state->data, state->total_data,
8232 state->max_data_return);
8233 END_PROFILE(Trans2_findnotifyfirst);
8237 case TRANSACT2_FINDNOTIFYNEXT:
8239 START_PROFILE(Trans2_findnotifynext);
8240 call_trans2findnotifynext(conn, req,
8241 &state->param, state->total_param,
8242 &state->data, state->total_data,
8243 state->max_data_return);
8244 END_PROFILE(Trans2_findnotifynext);
8248 case TRANSACT2_MKDIR:
8250 START_PROFILE(Trans2_mkdir);
8251 call_trans2mkdir(conn, req,
8252 &state->param, state->total_param,
8253 &state->data, state->total_data,
8254 state->max_data_return);
8255 END_PROFILE(Trans2_mkdir);
8259 case TRANSACT2_GET_DFS_REFERRAL:
8261 START_PROFILE(Trans2_get_dfs_referral);
8262 call_trans2getdfsreferral(conn, req,
8263 &state->param, state->total_param,
8264 &state->data, state->total_data,
8265 state->max_data_return);
8266 END_PROFILE(Trans2_get_dfs_referral);
8270 case TRANSACT2_IOCTL:
8272 START_PROFILE(Trans2_ioctl);
8273 call_trans2ioctl(conn, req,
8274 &state->param, state->total_param,
8275 &state->data, state->total_data,
8276 state->max_data_return);
8277 END_PROFILE(Trans2_ioctl);
8282 /* Error in request */
8283 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8284 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8288 /****************************************************************************
8289 Reply to a SMBtrans2.
8290 ****************************************************************************/
8292 void reply_trans2(struct smb_request *req)
8294 connection_struct *conn = req->conn;
8299 unsigned int tran_call;
8300 struct trans_state *state;
8303 START_PROFILE(SMBtrans2);
8305 if (req->wct < 14) {
8306 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8307 END_PROFILE(SMBtrans2);
8311 dsoff = SVAL(req->vwv+12, 0);
8312 dscnt = SVAL(req->vwv+11, 0);
8313 psoff = SVAL(req->vwv+10, 0);
8314 pscnt = SVAL(req->vwv+9, 0);
8315 tran_call = SVAL(req->vwv+14, 0);
8317 result = allow_new_trans(conn->pending_trans, req->mid);
8318 if (!NT_STATUS_IS_OK(result)) {
8319 DEBUG(2, ("Got invalid trans2 request: %s\n",
8320 nt_errstr(result)));
8321 reply_nterror(req, result);
8322 END_PROFILE(SMBtrans2);
8327 switch (tran_call) {
8328 /* List the allowed trans2 calls on IPC$ */
8329 case TRANSACT2_OPEN:
8330 case TRANSACT2_GET_DFS_REFERRAL:
8331 case TRANSACT2_QFILEINFO:
8332 case TRANSACT2_QFSINFO:
8333 case TRANSACT2_SETFSINFO:
8336 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8337 END_PROFILE(SMBtrans2);
8342 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8343 DEBUG(0, ("talloc failed\n"));
8344 reply_nterror(req, NT_STATUS_NO_MEMORY);
8345 END_PROFILE(SMBtrans2);
8349 state->cmd = SMBtrans2;
8351 state->mid = req->mid;
8352 state->vuid = req->vuid;
8353 state->setup_count = SVAL(req->vwv+13, 0);
8354 state->setup = NULL;
8355 state->total_param = SVAL(req->vwv+0, 0);
8356 state->param = NULL;
8357 state->total_data = SVAL(req->vwv+1, 0);
8359 state->max_param_return = SVAL(req->vwv+2, 0);
8360 state->max_data_return = SVAL(req->vwv+3, 0);
8361 state->max_setup_return = SVAL(req->vwv+4, 0);
8362 state->close_on_completion = BITSETW(req->vwv+5, 0);
8363 state->one_way = BITSETW(req->vwv+5, 1);
8365 state->call = tran_call;
8367 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8368 is so as a sanity check */
8369 if (state->setup_count != 1) {
8371 * Need to have rc=0 for ioctl to get job id for OS/2.
8372 * Network printing will fail if function is not successful.
8373 * Similar function in reply.c will be used if protocol
8374 * is LANMAN1.0 instead of LM1.2X002.
8375 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8376 * outbuf doesn't have to be set(only job id is used).
8378 if ( (state->setup_count == 4)
8379 && (tran_call == TRANSACT2_IOCTL)
8380 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8381 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8382 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8384 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8385 DEBUG(2,("Transaction is %d\n",tran_call));
8387 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8388 END_PROFILE(SMBtrans2);
8393 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8396 if (state->total_data) {
8398 if (trans_oob(state->total_data, 0, dscnt)
8399 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8403 /* Can't use talloc here, the core routines do realloc on the
8404 * params and data. */
8405 state->data = (char *)SMB_MALLOC(state->total_data);
8406 if (state->data == NULL) {
8407 DEBUG(0,("reply_trans2: data malloc fail for %u "
8408 "bytes !\n", (unsigned int)state->total_data));
8410 reply_nterror(req, NT_STATUS_NO_MEMORY);
8411 END_PROFILE(SMBtrans2);
8415 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8418 if (state->total_param) {
8420 if (trans_oob(state->total_param, 0, pscnt)
8421 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8425 /* Can't use talloc here, the core routines do realloc on the
8426 * params and data. */
8427 state->param = (char *)SMB_MALLOC(state->total_param);
8428 if (state->param == NULL) {
8429 DEBUG(0,("reply_trans: param malloc fail for %u "
8430 "bytes !\n", (unsigned int)state->total_param));
8431 SAFE_FREE(state->data);
8433 reply_nterror(req, NT_STATUS_NO_MEMORY);
8434 END_PROFILE(SMBtrans2);
8438 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8441 state->received_data = dscnt;
8442 state->received_param = pscnt;
8444 if ((state->received_param == state->total_param) &&
8445 (state->received_data == state->total_data)) {
8447 handle_trans2(conn, req, state);
8449 SAFE_FREE(state->data);
8450 SAFE_FREE(state->param);
8452 END_PROFILE(SMBtrans2);
8456 DLIST_ADD(conn->pending_trans, state);
8458 /* We need to send an interim response then receive the rest
8459 of the parameter/data bytes */
8460 reply_outbuf(req, 0, 0);
8461 show_msg((char *)req->outbuf);
8462 END_PROFILE(SMBtrans2);
8467 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8468 SAFE_FREE(state->data);
8469 SAFE_FREE(state->param);
8471 END_PROFILE(SMBtrans2);
8472 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8476 /****************************************************************************
8477 Reply to a SMBtranss2
8478 ****************************************************************************/
8480 void reply_transs2(struct smb_request *req)
8482 connection_struct *conn = req->conn;
8483 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8484 struct trans_state *state;
8486 START_PROFILE(SMBtranss2);
8488 show_msg((char *)req->inbuf);
8491 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8492 END_PROFILE(SMBtranss2);
8496 for (state = conn->pending_trans; state != NULL;
8497 state = state->next) {
8498 if (state->mid == req->mid) {
8503 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8504 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8505 END_PROFILE(SMBtranss2);
8509 /* Revise state->total_param and state->total_data in case they have
8510 changed downwards */
8512 if (SVAL(req->vwv+0, 0) < state->total_param)
8513 state->total_param = SVAL(req->vwv+0, 0);
8514 if (SVAL(req->vwv+1, 0) < state->total_data)
8515 state->total_data = SVAL(req->vwv+1, 0);
8517 pcnt = SVAL(req->vwv+2, 0);
8518 poff = SVAL(req->vwv+3, 0);
8519 pdisp = SVAL(req->vwv+4, 0);
8521 dcnt = SVAL(req->vwv+5, 0);
8522 doff = SVAL(req->vwv+6, 0);
8523 ddisp = SVAL(req->vwv+7, 0);
8525 state->received_param += pcnt;
8526 state->received_data += dcnt;
8528 if ((state->received_data > state->total_data) ||
8529 (state->received_param > state->total_param))
8533 if (trans_oob(state->total_param, pdisp, pcnt)
8534 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8537 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8541 if (trans_oob(state->total_data, ddisp, dcnt)
8542 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8545 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8548 if ((state->received_param < state->total_param) ||
8549 (state->received_data < state->total_data)) {
8550 END_PROFILE(SMBtranss2);
8554 handle_trans2(conn, req, state);
8556 DLIST_REMOVE(conn->pending_trans, state);
8557 SAFE_FREE(state->data);
8558 SAFE_FREE(state->param);
8561 END_PROFILE(SMBtranss2);
8566 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8567 DLIST_REMOVE(conn->pending_trans, state);
8568 SAFE_FREE(state->data);
8569 SAFE_FREE(state->param);
8571 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8572 END_PROFILE(SMBtranss2);