LCOV - code coverage report
Current view: top level - source3/smbd - smb2_trans2.c (source / functions) Hit Total Coverage
Test: coverage report for support-claim-type-attributes 6b5c566e Lines: 1931 2417 79.9 %
Date: 2023-11-21 12:31:41 Functions: 49 52 94.2 %

          Line data    Source code
       1             : /*
       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
       9             : 
      10             :    Extensively modified by Andrew Tridgell, 1995
      11             : 
      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.
      16             : 
      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.
      21             : 
      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/>.
      24             : */
      25             : 
      26             : #include "includes.h"
      27             : #include "ntioctl.h"
      28             : #include "system/filesys.h"
      29             : #include "lib/util/time_basic.h"
      30             : #include "version.h"
      31             : #include "smbd/smbd.h"
      32             : #include "smbd/globals.h"
      33             : #include "../libcli/auth/libcli_auth.h"
      34             : #include "../librpc/gen_ndr/xattr.h"
      35             : #include "../librpc/gen_ndr/ndr_security.h"
      36             : #include "../librpc/gen_ndr/ndr_smb3posix.h"
      37             : #include "libcli/security/security.h"
      38             : #include "trans2.h"
      39             : #include "auth.h"
      40             : #include "smbprofile.h"
      41             : #include "rpc_server/srv_pipe_hnd.h"
      42             : #include "printing.h"
      43             : #include "lib/util_ea.h"
      44             : #include "lib/readdir_attr.h"
      45             : #include "messages.h"
      46             : #include "libcli/smb/smb2_posix.h"
      47             : #include "lib/util/string_wrappers.h"
      48             : #include "source3/lib/substitute.h"
      49             : #include "source3/lib/adouble.h"
      50             : 
      51             : #define DIR_ENTRY_SAFETY_MARGIN 4096
      52             : 
      53             : static uint32_t generate_volume_serial_number(
      54             :                                 const struct loadparm_substitution *lp_sub,
      55             :                                 int snum);
      56             : 
      57             : /****************************************************************************
      58             :  Check if an open file handle is a symlink.
      59             : ****************************************************************************/
      60             : 
      61      797164 : NTSTATUS refuse_symlink_fsp(const files_struct *fsp)
      62             : {
      63             : 
      64      797164 :         if (!VALID_STAT(fsp->fsp_name->st)) {
      65           0 :                 return NT_STATUS_ACCESS_DENIED;
      66             :         }
      67      797164 :         if (S_ISLNK(fsp->fsp_name->st.st_ex_mode)) {
      68         108 :                 return NT_STATUS_ACCESS_DENIED;
      69             :         }
      70      797056 :         if (fsp_get_pathref_fd(fsp) == -1) {
      71         172 :                 return NT_STATUS_ACCESS_DENIED;
      72             :         }
      73      796884 :         return NT_STATUS_OK;
      74             : }
      75             : 
      76        6627 : NTSTATUS check_access_fsp(struct files_struct *fsp,
      77             :                           uint32_t access_mask)
      78             : {
      79        6627 :         if (!fsp->fsp_flags.is_fsa) {
      80         134 :                 return smbd_check_access_rights_fsp(fsp->conn->cwd_fsp,
      81             :                                                     fsp,
      82             :                                                     false,
      83             :                                                     access_mask);
      84             :         }
      85        6493 :         if (!(fsp->access_mask & access_mask)) {
      86          40 :                 return NT_STATUS_ACCESS_DENIED;
      87             :         }
      88        6453 :         return NT_STATUS_OK;
      89             : }
      90             : 
      91             : /********************************************************************
      92             :  Roundup a value to the nearest allocation roundup size boundary.
      93             :  Only do this for Windows clients.
      94             : ********************************************************************/
      95             : 
      96     1730244 : uint64_t smb_roundup(connection_struct *conn, uint64_t val)
      97             : {
      98     1730244 :         uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
      99             : 
     100             :         /* Only roundup for Windows clients. */
     101     1730244 :         enum remote_arch_types ra_type = get_remote_arch();
     102     1730244 :         if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
     103           0 :                 val = SMB_ROUNDUP(val,rval);
     104             :         }
     105     1730244 :         return val;
     106             : }
     107             : 
     108             : /****************************************************************************
     109             :  Utility functions for dealing with extended attributes.
     110             : ****************************************************************************/
     111             : 
     112             : /****************************************************************************
     113             :  Refuse to allow clients to overwrite our private xattrs.
     114             : ****************************************************************************/
     115             : 
     116      724219 : bool samba_private_attr_name(const char *unix_ea_name)
     117             : {
     118      724219 :         bool prohibited = false;
     119             : 
     120      724219 :         prohibited |= strequal(unix_ea_name, SAMBA_POSIX_INHERITANCE_EA_NAME);
     121      724219 :         prohibited |= strequal(unix_ea_name, SAMBA_XATTR_DOS_ATTRIB);
     122      724219 :         prohibited |= strequal(unix_ea_name, SAMBA_XATTR_MARKER);
     123      724219 :         prohibited |= strequal(unix_ea_name, XATTR_NTACL_NAME);
     124      724219 :         prohibited |= strequal(unix_ea_name, AFPINFO_EA_NETATALK);
     125             : 
     126      724219 :         if (prohibited) {
     127      711052 :                 return true;
     128             :         }
     129             : 
     130       12211 :         if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
     131             :                         strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
     132         106 :                 return true;
     133             :         }
     134       11037 :         return false;
     135             : }
     136             : 
     137             : /****************************************************************************
     138             :  Get one EA value. Fill in a struct ea_struct.
     139             : ****************************************************************************/
     140             : 
     141       15142 : NTSTATUS get_ea_value_fsp(TALLOC_CTX *mem_ctx,
     142             :                           files_struct *fsp,
     143             :                           const char *ea_name,
     144             :                           struct ea_struct *pea)
     145             : {
     146             :         /* Get the value of this xattr. Max size is 64k. */
     147       15142 :         size_t attr_size = 256;
     148       15142 :         char *val = NULL;
     149         575 :         ssize_t sizeret;
     150       15142 :         size_t max_xattr_size = 0;
     151         575 :         NTSTATUS status;
     152             : 
     153       15142 :         if (fsp == NULL) {
     154           0 :                 return NT_STATUS_INVALID_HANDLE;
     155             :         }
     156       15142 :         status = refuse_symlink_fsp(fsp);
     157       15142 :         if (!NT_STATUS_IS_OK(status)) {
     158           0 :                 return status;
     159             :         }
     160             : 
     161       15142 :         max_xattr_size = lp_smbd_max_xattr_size(SNUM(fsp->conn));
     162             : 
     163       15256 :  again:
     164             : 
     165       15256 :         val = talloc_realloc(mem_ctx, val, char, attr_size);
     166       15256 :         if (!val) {
     167           0 :                 return NT_STATUS_NO_MEMORY;
     168             :         }
     169             : 
     170       15256 :         sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
     171       15256 :         if (sizeret == -1 && errno == ERANGE && attr_size < max_xattr_size) {
     172         114 :                 attr_size = max_xattr_size;
     173         114 :                 goto again;
     174             :         }
     175             : 
     176       15142 :         if (sizeret == -1) {
     177        2608 :                 return map_nt_error_from_unix(errno);
     178             :         }
     179             : 
     180       12534 :         DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
     181       12534 :         dump_data(10, (uint8_t *)val, sizeret);
     182             : 
     183       12534 :         pea->flags = 0;
     184       12534 :         if (strnequal(ea_name, "user.", 5)) {
     185       12534 :                 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
     186             :         } else {
     187           0 :                 pea->name = talloc_strdup(mem_ctx, ea_name);
     188             :         }
     189       12534 :         if (pea->name == NULL) {
     190           0 :                 TALLOC_FREE(val);
     191           0 :                 return NT_STATUS_NO_MEMORY;
     192             :         }
     193       12534 :         pea->value.data = (unsigned char *)val;
     194       12534 :         pea->value.length = (size_t)sizeret;
     195       12534 :         return NT_STATUS_OK;
     196             : }
     197             : 
     198      750341 : NTSTATUS get_ea_names_from_fsp(TALLOC_CTX *mem_ctx,
     199             :                                 files_struct *fsp,
     200             :                                 char ***pnames,
     201             :                                 size_t *pnum_names)
     202             : {
     203        1071 :         char smallbuf[1024];
     204             :         /* Get a list of all xattrs. Max namesize is 64k. */
     205      750341 :         size_t ea_namelist_size = 1024;
     206      750341 :         char *ea_namelist = smallbuf;
     207      750341 :         char *to_free = NULL;
     208             : 
     209        1071 :         char *p;
     210        1071 :         char **names;
     211        1071 :         size_t num_names;
     212      750341 :         ssize_t sizeret = -1;
     213        1071 :         NTSTATUS status;
     214             : 
     215      750341 :         if (pnames) {
     216      749071 :                 *pnames = NULL;
     217             :         }
     218      750341 :         *pnum_names = 0;
     219             : 
     220      750341 :         if ((fsp == NULL) || !NT_STATUS_IS_OK(refuse_symlink_fsp(fsp))) {
     221             :                 /*
     222             :                  * Callers may pass fsp == NULL when passing smb_fname->fsp of a
     223             :                  * symlink. This is ok, handle it here, by just return no EA's
     224             :                  * on a symlink.
     225             :                  */
     226         268 :                 return NT_STATUS_OK;
     227             :         }
     228             : 
     229      750073 :         sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
     230             :                                      ea_namelist_size);
     231             : 
     232      750073 :         if ((sizeret == -1) && (errno == ERANGE)) {
     233           0 :                 ea_namelist_size = 65536;
     234           0 :                 ea_namelist = talloc_array(mem_ctx, char, ea_namelist_size);
     235           0 :                 if (ea_namelist == NULL) {
     236           0 :                         return NT_STATUS_NO_MEMORY;
     237             :                 }
     238           0 :                 to_free = ea_namelist;
     239             : 
     240           0 :                 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
     241             :                                              ea_namelist_size);
     242             :         }
     243             : 
     244      750073 :         if (sizeret == -1) {
     245           0 :                 status = map_nt_error_from_unix(errno);
     246           0 :                 TALLOC_FREE(to_free);
     247           0 :                 return status;
     248             :         }
     249             : 
     250      750073 :         DBG_DEBUG("ea_namelist size = %zd\n", sizeret);
     251             : 
     252      750073 :         if (sizeret == 0) {
     253       40852 :                 TALLOC_FREE(to_free);
     254       40852 :                 return NT_STATUS_OK;
     255             :         }
     256             : 
     257             :         /*
     258             :          * Ensure the result is 0-terminated
     259             :          */
     260             : 
     261      709221 :         if (ea_namelist[sizeret-1] != '\0') {
     262           0 :                 TALLOC_FREE(to_free);
     263           0 :                 return NT_STATUS_INTERNAL_ERROR;
     264             :         }
     265             : 
     266             :         /*
     267             :          * count the names
     268             :          */
     269      708191 :         num_names = 0;
     270             : 
     271     4165528 :         for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
     272     3456307 :                 num_names += 1;
     273             :         }
     274             : 
     275      709221 :         *pnum_names = num_names;
     276             : 
     277      709221 :         if (pnames == NULL) {
     278        1261 :                 TALLOC_FREE(to_free);
     279        1261 :                 return NT_STATUS_OK;
     280             :         }
     281             : 
     282      707960 :         names = talloc_array(mem_ctx, char *, num_names);
     283      707960 :         if (names == NULL) {
     284           0 :                 DEBUG(0, ("talloc failed\n"));
     285           0 :                 TALLOC_FREE(to_free);
     286           0 :                 return NT_STATUS_NO_MEMORY;
     287             :         }
     288             : 
     289      707960 :         if (ea_namelist == smallbuf) {
     290      707960 :                 ea_namelist = talloc_memdup(names, smallbuf, sizeret);
     291      707960 :                 if (ea_namelist == NULL) {
     292           0 :                         TALLOC_FREE(names);
     293           0 :                         return NT_STATUS_NO_MEMORY;
     294             :                 }
     295             :         } else {
     296           0 :                 talloc_steal(names, ea_namelist);
     297             : 
     298           0 :                 ea_namelist = talloc_realloc(names, ea_namelist, char,
     299             :                                              sizeret);
     300           0 :                 if (ea_namelist == NULL) {
     301           0 :                         TALLOC_FREE(names);
     302           0 :                         return NT_STATUS_NO_MEMORY;
     303             :                 }
     304             :         }
     305             : 
     306      707960 :         num_names = 0;
     307             : 
     308     4157618 :         for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
     309     3449658 :                 names[num_names++] = p;
     310             :         }
     311             : 
     312      707960 :         *pnames = names;
     313             : 
     314      707960 :         return NT_STATUS_OK;
     315             : }
     316             : 
     317             : /****************************************************************************
     318             :  Return a linked list of the total EA's. Plus the total size
     319             : ****************************************************************************/
     320             : 
     321      743078 : static NTSTATUS get_ea_list_from_fsp(TALLOC_CTX *mem_ctx,
     322             :                                 files_struct *fsp,
     323             :                                 size_t *pea_total_len,
     324             :                                 struct ea_list **ea_list)
     325             : {
     326             :         /* Get a list of all xattrs. Max namesize is 64k. */
     327         994 :         size_t i, num_names;
     328         994 :         char **names;
     329      743078 :         struct ea_list *ea_list_head = NULL;
     330      743078 :         bool posix_pathnames = false;
     331         994 :         NTSTATUS status;
     332             : 
     333      743078 :         *pea_total_len = 0;
     334      743078 :         *ea_list = NULL;
     335             : 
     336             :         /* symlink */
     337      743078 :         if (fsp == NULL) {
     338           0 :                 return NT_STATUS_OK;
     339             :         }
     340             : 
     341      743078 :         if (!lp_ea_support(SNUM(fsp->conn))) {
     342           0 :                 return NT_STATUS_OK;
     343             :         }
     344             : 
     345      743078 :         if (fsp_is_alternate_stream(fsp)) {
     346           8 :                 return NT_STATUS_INVALID_PARAMETER;
     347             :         }
     348             : 
     349      743070 :         posix_pathnames = (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
     350             : 
     351      743070 :         status = get_ea_names_from_fsp(talloc_tos(),
     352             :                                 fsp,
     353             :                                 &names,
     354             :                                 &num_names);
     355             : 
     356      743070 :         if (!NT_STATUS_IS_OK(status)) {
     357           0 :                 return status;
     358             :         }
     359             : 
     360      743070 :         if (num_names == 0) {
     361       41097 :                 return NT_STATUS_OK;
     362             :         }
     363             : 
     364     4136946 :         for (i=0; i<num_names; i++) {
     365        5395 :                 struct ea_list *listp;
     366        5395 :                 fstring dos_ea_name;
     367             : 
     368             :                 /*
     369             :                  * POSIX EA names are divided into several namespaces by
     370             :                  * means of string prefixes. Usually, the system controls
     371             :                  * semantics for each namespace, but the 'user' namespace is
     372             :                  * available for arbitrary use, which comes closest to
     373             :                  * Windows EA semantics. Hence, we map POSIX EAs from the
     374             :                  * 'user' namespace to Windows EAs, and just ignore all the
     375             :                  * other namespaces. Also, a few specific names in the 'user'
     376             :                  * namespace are used by Samba internally. Filter them out as
     377             :                  * well, and only present the EAs that are available for
     378             :                  * arbitrary use.
     379             :                  */
     380     3434973 :                 if (!strnequal(names[i], "user.", 5)
     381      706665 :                     || samba_private_attr_name(names[i]))
     382     3428859 :                         continue;
     383             : 
     384             :                 /*
     385             :                  * Filter out any underlying POSIX EA names
     386             :                  * that a Windows client can't handle.
     387             :                  */
     388       12224 :                 if (!posix_pathnames &&
     389        6110 :                                 is_invalid_windows_ea_name(names[i])) {
     390           0 :                         continue;
     391             :                 }
     392             : 
     393        6114 :                 listp = talloc(mem_ctx, struct ea_list);
     394        6114 :                 if (listp == NULL) {
     395           0 :                         return NT_STATUS_NO_MEMORY;
     396             :                 }
     397             : 
     398        6689 :                 status = get_ea_value_fsp(listp,
     399             :                                           fsp,
     400        6114 :                                           names[i],
     401             :                                           &listp->ea);
     402             : 
     403        6114 :                 if (!NT_STATUS_IS_OK(status)) {
     404           0 :                         TALLOC_FREE(listp);
     405           0 :                         return status;
     406             :                 }
     407             : 
     408        6114 :                 if (listp->ea.value.length == 0) {
     409             :                         /*
     410             :                          * We can never return a zero length EA.
     411             :                          * Windows reports the EA's as corrupted.
     412             :                          */
     413           0 :                         TALLOC_FREE(listp);
     414           0 :                         continue;
     415        6114 :                 } else if (listp->ea.value.length > 65536) {
     416             :                         /*
     417             :                          * SMB clients may report error with file
     418             :                          * if large EA is presented to them.
     419             :                          */
     420           0 :                         DBG_ERR("EA [%s] on file [%s] exceeds "
     421             :                                 "maximum permitted EA size of 64KiB: %zu\n.",
     422             :                                 listp->ea.name, fsp_str_dbg(fsp),
     423             :                                 listp->ea.value.length);
     424           0 :                         TALLOC_FREE(listp);
     425           0 :                         continue;
     426             :                 }
     427             : 
     428        6114 :                 push_ascii_fstring(dos_ea_name, listp->ea.name);
     429             : 
     430        6114 :                 *pea_total_len +=
     431        6114 :                         4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
     432             : 
     433        6114 :                 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
     434             :                           "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
     435             :                           (unsigned int)listp->ea.value.length));
     436             : 
     437        6114 :                 DLIST_ADD_END(ea_list_head, listp);
     438             : 
     439             :         }
     440             : 
     441             :         /* Add on 4 for total length. */
     442      701973 :         if (*pea_total_len) {
     443        3902 :                 *pea_total_len += 4;
     444             :         }
     445             : 
     446      701973 :         DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
     447             :                    (unsigned int)*pea_total_len));
     448             : 
     449      701973 :         *ea_list = ea_list_head;
     450      701973 :         return NT_STATUS_OK;
     451             : }
     452             : 
     453             : /****************************************************************************
     454             :  Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
     455             :  that was filled.
     456             : ****************************************************************************/
     457             : 
     458         170 : static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
     459             :         connection_struct *conn, struct ea_list *ea_list)
     460             : {
     461         170 :         unsigned int ret_data_size = 4;
     462         170 :         char *p = pdata;
     463             : 
     464         170 :         SMB_ASSERT(total_data_size >= 4);
     465             : 
     466         170 :         if (!lp_ea_support(SNUM(conn))) {
     467           0 :                 SIVAL(pdata,4,0);
     468           0 :                 return 4;
     469             :         }
     470             : 
     471         358 :         for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
     472          28 :                 size_t dos_namelen;
     473          28 :                 fstring dos_ea_name;
     474         188 :                 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
     475         188 :                 dos_namelen = strlen(dos_ea_name);
     476         188 :                 if (dos_namelen > 255 || dos_namelen == 0) {
     477             :                         break;
     478             :                 }
     479         188 :                 if (ea_list->ea.value.length > 65535) {
     480           0 :                         break;
     481             :                 }
     482         188 :                 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
     483           0 :                         break;
     484             :                 }
     485             : 
     486             :                 /* We know we have room. */
     487         188 :                 SCVAL(p,0,ea_list->ea.flags);
     488         188 :                 SCVAL(p,1,dos_namelen);
     489         188 :                 SSVAL(p,2,ea_list->ea.value.length);
     490         188 :                 strlcpy(p+4, dos_ea_name, dos_namelen+1);
     491         188 :                 if (ea_list->ea.value.length > 0) {
     492         139 :                         memcpy(p + 4 + dos_namelen + 1,
     493         111 :                                ea_list->ea.value.data,
     494             :                                ea_list->ea.value.length);
     495             :                 }
     496             : 
     497         188 :                 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
     498         188 :                 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
     499             :         }
     500             : 
     501         170 :         ret_data_size = PTR_DIFF(p, pdata);
     502         170 :         DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
     503         170 :         SIVAL(pdata,0,ret_data_size);
     504         170 :         return ret_data_size;
     505             : }
     506             : 
     507      555278 : static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
     508             :                                        char *pdata,
     509             :                                        unsigned int total_data_size,
     510             :                                        unsigned int *ret_data_size,
     511             :                                        connection_struct *conn,
     512             :                                        struct ea_list *ea_list)
     513             : {
     514      555278 :         uint8_t *p = (uint8_t *)pdata;
     515      555278 :         uint8_t *last_start = NULL;
     516      555278 :         bool do_store_data = (pdata != NULL);
     517             : 
     518      555278 :         *ret_data_size = 0;
     519             : 
     520      555278 :         if (!lp_ea_support(SNUM(conn))) {
     521           0 :                 return NT_STATUS_NO_EAS_ON_FILE;
     522             :         }
     523             : 
     524      557422 :         for (; ea_list; ea_list = ea_list->next) {
     525           0 :                 size_t dos_namelen;
     526           0 :                 fstring dos_ea_name;
     527           0 :                 size_t this_size;
     528        2144 :                 size_t pad = 0;
     529             : 
     530        2144 :                 if (last_start != NULL && do_store_data) {
     531           8 :                         SIVAL(last_start, 0, PTR_DIFF(p, last_start));
     532             :                 }
     533        2144 :                 last_start = p;
     534             : 
     535        2144 :                 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
     536        2144 :                 dos_namelen = strlen(dos_ea_name);
     537        2144 :                 if (dos_namelen > 255 || dos_namelen == 0) {
     538           0 :                         return NT_STATUS_INTERNAL_ERROR;
     539             :                 }
     540        2144 :                 if (ea_list->ea.value.length > 65535) {
     541           0 :                         return NT_STATUS_INTERNAL_ERROR;
     542             :                 }
     543             : 
     544        2144 :                 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
     545             : 
     546        2144 :                 if (ea_list->next) {
     547        1071 :                         pad = (4 - (this_size % 4)) % 4;
     548        1071 :                         this_size += pad;
     549             :                 }
     550             : 
     551        2144 :                 if (do_store_data) {
     552          18 :                         if (this_size > total_data_size) {
     553           0 :                                 return NT_STATUS_INFO_LENGTH_MISMATCH;
     554             :                         }
     555             : 
     556             :                         /* We know we have room. */
     557          18 :                         SIVAL(p, 0x00, 0); /* next offset */
     558          18 :                         SCVAL(p, 0x04, ea_list->ea.flags);
     559          18 :                         SCVAL(p, 0x05, dos_namelen);
     560          18 :                         SSVAL(p, 0x06, ea_list->ea.value.length);
     561          18 :                         strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
     562          18 :                         memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
     563          18 :                         if (pad) {
     564           0 :                                 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
     565             :                                         '\0',
     566             :                                         pad);
     567             :                         }
     568          18 :                         total_data_size -= this_size;
     569             :                 }
     570             : 
     571        2144 :                 p += this_size;
     572             :         }
     573             : 
     574      555278 :         *ret_data_size = PTR_DIFF(p, pdata);
     575      555278 :         DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
     576      555278 :         return NT_STATUS_OK;
     577             : }
     578             : 
     579      739031 : unsigned int estimate_ea_size(files_struct *fsp)
     580             : {
     581      739031 :         size_t total_ea_len = 0;
     582         473 :         TALLOC_CTX *mem_ctx;
     583      739031 :         struct ea_list *ea_list = NULL;
     584         473 :         NTSTATUS status;
     585             : 
     586             :         /* symlink */
     587      739031 :         if (fsp == NULL) {
     588           0 :                 return 0;
     589             :         }
     590             : 
     591      739031 :         if (!lp_ea_support(SNUM(fsp->conn))) {
     592           0 :                 return 0;
     593             :         }
     594             : 
     595      739031 :         mem_ctx = talloc_stackframe();
     596             : 
     597             :         /* If this is a stream fsp, then we need to instead find the
     598             :          * estimated ea len from the main file, not the stream
     599             :          * (streams cannot have EAs), but the estimate isn't just 0 in
     600             :          * this case! */
     601      739031 :         fsp = metadata_fsp(fsp);
     602      739031 :         (void)get_ea_list_from_fsp(mem_ctx,
     603             :                                    fsp,
     604             :                                    &total_ea_len,
     605             :                                    &ea_list);
     606             : 
     607      739031 :         if(fsp->conn->sconn->using_smb2) {
     608           0 :                 unsigned int ret_data_size;
     609             :                 /*
     610             :                  * We're going to be using fill_ea_chained_buffer() to
     611             :                  * marshall EA's - this size is significantly larger
     612             :                  * than the SMB1 buffer. Re-calculate the size without
     613             :                  * marshalling.
     614             :                  */
     615      555268 :                 status = fill_ea_chained_buffer(mem_ctx,
     616             :                                                 NULL,
     617             :                                                 0,
     618             :                                                 &ret_data_size,
     619      555268 :                                                 fsp->conn,
     620             :                                                 ea_list);
     621      555268 :                 if (!NT_STATUS_IS_OK(status)) {
     622           0 :                         ret_data_size = 0;
     623             :                 }
     624      555268 :                 total_ea_len = ret_data_size;
     625             :         }
     626      739031 :         TALLOC_FREE(mem_ctx);
     627      739031 :         return total_ea_len;
     628             : }
     629             : 
     630             : /****************************************************************************
     631             :  Ensure the EA name is case insensitive by matching any existing EA name.
     632             : ****************************************************************************/
     633             : 
     634        3835 : static void canonicalize_ea_name(files_struct *fsp,
     635             :                         fstring unix_ea_name)
     636             : {
     637         493 :         size_t total_ea_len;
     638        3835 :         TALLOC_CTX *mem_ctx = talloc_tos();
     639         493 :         struct ea_list *ea_list;
     640        3835 :         NTSTATUS status = get_ea_list_from_fsp(mem_ctx,
     641             :                                                fsp,
     642             :                                                &total_ea_len,
     643             :                                                &ea_list);
     644        3835 :         if (!NT_STATUS_IS_OK(status)) {
     645           0 :                 return;
     646             :         }
     647             : 
     648        4838 :         for (; ea_list; ea_list = ea_list->next) {
     649        2116 :                 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
     650        1113 :                         DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
     651             :                                 &unix_ea_name[5], ea_list->ea.name));
     652        1113 :                         strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
     653        1113 :                         break;
     654             :                 }
     655             :         }
     656             : }
     657             : 
     658             : /****************************************************************************
     659             :  Set or delete an extended attribute.
     660             : ****************************************************************************/
     661             : 
     662        3205 : NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
     663             :                 struct ea_list *ea_list)
     664             : {
     665         500 :         NTSTATUS status;
     666        3205 :         bool posix_pathnames = false;
     667             : 
     668        3205 :         if (!lp_ea_support(SNUM(conn))) {
     669           0 :                 return NT_STATUS_EAS_NOT_SUPPORTED;
     670             :         }
     671             : 
     672        3205 :         if (fsp == NULL) {
     673           0 :                 return NT_STATUS_INVALID_HANDLE;
     674             :         }
     675             : 
     676        3205 :         posix_pathnames = (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
     677             : 
     678        3205 :         status = refuse_symlink_fsp(fsp);
     679        3205 :         if (!NT_STATUS_IS_OK(status)) {
     680          12 :                 return status;
     681             :         }
     682             : 
     683        3193 :         status = check_access_fsp(fsp, FILE_WRITE_EA);
     684        3193 :         if (!NT_STATUS_IS_OK(status)) {
     685           0 :                 return status;
     686             :         }
     687             : 
     688             :         /* Setting EAs on streams isn't supported. */
     689        3193 :         if (fsp_is_alternate_stream(fsp)) {
     690           4 :                 return NT_STATUS_INVALID_PARAMETER;
     691             :         }
     692             : 
     693             :         /*
     694             :          * Filter out invalid Windows EA names - before
     695             :          * we set *any* of them.
     696             :          */
     697             : 
     698        3189 :         if (!posix_pathnames && ea_list_has_invalid_name(ea_list)) {
     699         235 :                 return STATUS_INVALID_EA_NAME;
     700             :         }
     701             : 
     702        6787 :         for (;ea_list; ea_list = ea_list->next) {
     703         493 :                 int ret;
     704         493 :                 fstring unix_ea_name;
     705             : 
     706             :                 /*
     707             :                  * Complementing the forward mapping from POSIX EAs to
     708             :                  * Windows EAs in get_ea_list_from_fsp(), here we map in the
     709             :                  * opposite direction from Windows EAs to the 'user' namespace
     710             :                  * of POSIX EAs. Hence, all POSIX EA names the we set here must
     711             :                  * start with a 'user.' prefix.
     712             :                  */
     713        3835 :                 fstrcpy(unix_ea_name, "user.");
     714        3835 :                 fstrcat(unix_ea_name, ea_list->ea.name);
     715             : 
     716        3835 :                 canonicalize_ea_name(fsp, unix_ea_name);
     717             : 
     718        3835 :                 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
     719             : 
     720        3835 :                 if (samba_private_attr_name(unix_ea_name)) {
     721           0 :                         DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
     722           0 :                         return NT_STATUS_ACCESS_DENIED;
     723             :                 }
     724             : 
     725        3835 :                 if (ea_list->ea.value.length == 0) {
     726             :                         /* Remove the attribute. */
     727        1060 :                         DBG_DEBUG("deleting ea name %s on "
     728             :                                   "file %s by file descriptor.\n",
     729             :                                   unix_ea_name, fsp_str_dbg(fsp));
     730        1060 :                         ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
     731             : #ifdef ENOATTR
     732             :                         /* Removing a non existent attribute always succeeds. */
     733        1060 :                         if (ret == -1 && errno == ENOATTR) {
     734           5 :                                 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
     735             :                                                 unix_ea_name));
     736           4 :                                 ret = 0;
     737             :                         }
     738             : #endif
     739             :                 } else {
     740        2775 :                         DEBUG(10,("set_ea: setting ea name %s on file "
     741             :                                   "%s by file descriptor.\n",
     742             :                                   unix_ea_name, fsp_str_dbg(fsp)));
     743        2775 :                         ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
     744             :                                                 ea_list->ea.value.data, ea_list->ea.value.length, 0);
     745             :                 }
     746             : 
     747        3834 :                 if (ret == -1) {
     748             : #ifdef ENOTSUP
     749           2 :                         if (errno == ENOTSUP) {
     750           0 :                                 return NT_STATUS_EAS_NOT_SUPPORTED;
     751             :                         }
     752             : #endif
     753           2 :                         return map_nt_error_from_unix(errno);
     754             :                 }
     755             : 
     756             :         }
     757        2952 :         return NT_STATUS_OK;
     758             : }
     759             : 
     760             : /****************************************************************************
     761             :  Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
     762             : ****************************************************************************/
     763             : 
     764        3024 : struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
     765             : {
     766        3024 :         struct ea_list *ea_list_head = NULL;
     767        3024 :         size_t offset = 0;
     768        3024 :         size_t bytes_used = 0;
     769             : 
     770        6794 :         while (offset < data_size) {
     771        3778 :                 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
     772             : 
     773        3778 :                 if (!eal) {
     774           8 :                         return NULL;
     775             :                 }
     776             : 
     777        3770 :                 DLIST_ADD_END(ea_list_head, eal);
     778        3770 :                 offset += bytes_used;
     779             :         }
     780             : 
     781        2508 :         return ea_list_head;
     782             : }
     783             : 
     784             : /****************************************************************************
     785             :  Count the total EA size needed.
     786             : ****************************************************************************/
     787             : 
     788         166 : static size_t ea_list_size(struct ea_list *ealist)
     789             : {
     790          28 :         fstring dos_ea_name;
     791          28 :         struct ea_list *listp;
     792         166 :         size_t ret = 0;
     793             : 
     794         350 :         for (listp = ealist; listp; listp = listp->next) {
     795         184 :                 push_ascii_fstring(dos_ea_name, listp->ea.name);
     796         184 :                 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
     797             :         }
     798             :         /* Add on 4 for total length. */
     799         166 :         if (ret) {
     800         166 :                 ret += 4;
     801             :         }
     802             : 
     803         166 :         return ret;
     804             : }
     805             : 
     806             : /****************************************************************************
     807             :  Return a union of EA's from a file list and a list of names.
     808             :  The TALLOC context for the two lists *MUST* be identical as we steal
     809             :  memory from one list to add to another. JRA.
     810             : ****************************************************************************/
     811             : 
     812         166 : static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
     813             : {
     814          28 :         struct ea_list *nlistp, *flistp;
     815             : 
     816         350 :         for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
     817         340 :                 for (flistp = file_list; flistp; flistp = flistp->next) {
     818         263 :                         if (strequal(nlistp->ea.name, flistp->ea.name)) {
     819          88 :                                 break;
     820             :                         }
     821             :                 }
     822             : 
     823         184 :                 if (flistp) {
     824             :                         /* Copy the data from this entry. */
     825         107 :                         nlistp->ea.flags = flistp->ea.flags;
     826         107 :                         nlistp->ea.value = flistp->ea.value;
     827             :                 } else {
     828             :                         /* Null entry. */
     829          77 :                         nlistp->ea.flags = 0;
     830          77 :                         ZERO_STRUCT(nlistp->ea.value);
     831             :                 }
     832             :         }
     833             : 
     834         166 :         *total_ea_len = ea_list_size(name_list);
     835         166 :         return name_list;
     836             : }
     837             : 
     838             : /****************************************************************************
     839             :  Return the filetype for UNIX extensions.
     840             : ****************************************************************************/
     841             : 
     842         576 : static uint32_t unix_filetype(mode_t mode)
     843             : {
     844         576 :         if(S_ISREG(mode))
     845         280 :                 return UNIX_TYPE_FILE;
     846         296 :         else if(S_ISDIR(mode))
     847          80 :                 return UNIX_TYPE_DIR;
     848             : #ifdef S_ISLNK
     849         216 :         else if(S_ISLNK(mode))
     850         208 :                 return UNIX_TYPE_SYMLINK;
     851             : #endif
     852             : #ifdef S_ISCHR
     853           8 :         else if(S_ISCHR(mode))
     854           0 :                 return UNIX_TYPE_CHARDEV;
     855             : #endif
     856             : #ifdef S_ISBLK
     857           8 :         else if(S_ISBLK(mode))
     858           0 :                 return UNIX_TYPE_BLKDEV;
     859             : #endif
     860             : #ifdef S_ISFIFO
     861           8 :         else if(S_ISFIFO(mode))
     862           4 :                 return UNIX_TYPE_FIFO;
     863             : #endif
     864             : #ifdef S_ISSOCK
     865           4 :         else if(S_ISSOCK(mode))
     866           4 :                 return UNIX_TYPE_SOCKET;
     867             : #endif
     868             : 
     869           0 :         DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
     870           0 :         return UNIX_TYPE_UNKNOWN;
     871             : }
     872             : 
     873             : /****************************************************************************
     874             :  Map wire perms onto standard UNIX permissions. Obey share restrictions.
     875             : ****************************************************************************/
     876             : 
     877        3086 : NTSTATUS unix_perms_from_wire(connection_struct *conn,
     878             :                               const SMB_STRUCT_STAT *psbuf,
     879             :                               uint32_t perms,
     880             :                               enum perm_type ptype,
     881             :                               mode_t *ret_perms)
     882             : {
     883        3086 :         mode_t ret = 0;
     884             : 
     885        3086 :         if (perms == SMB_MODE_NO_CHANGE) {
     886         132 :                 if (!VALID_STAT(*psbuf)) {
     887           0 :                         return NT_STATUS_INVALID_PARAMETER;
     888             :                 } else {
     889         132 :                         *ret_perms = psbuf->st_ex_mode;
     890         132 :                         return NT_STATUS_OK;
     891             :                 }
     892             :         }
     893             : 
     894        2954 :         ret = wire_perms_to_unix(perms);
     895             : 
     896        2954 :         if (ptype == PERM_NEW_FILE) {
     897             :                 /*
     898             :                  * "create mask"/"force create mode" are
     899             :                  * only applied to new files, not existing ones.
     900             :                  */
     901        2173 :                 ret &= lp_create_mask(SNUM(conn));
     902             :                 /* Add in force bits */
     903        2173 :                 ret |= lp_force_create_mode(SNUM(conn));
     904         781 :         } else if (ptype == PERM_NEW_DIR) {
     905             :                 /*
     906             :                  * "directory mask"/"force directory mode" are
     907             :                  * only applied to new directories, not existing ones.
     908             :                  */
     909         701 :                 ret &= lp_directory_mask(SNUM(conn));
     910             :                 /* Add in force bits */
     911         701 :                 ret |= lp_force_directory_mode(SNUM(conn));
     912             :         }
     913             : 
     914        2954 :         *ret_perms = ret;
     915        2954 :         return NT_STATUS_OK;
     916             : }
     917             : 
     918             : /****************************************************************************
     919             :  Get a level dependent lanman2 dir entry.
     920             : ****************************************************************************/
     921             : 
     922             : struct smbd_dirptr_lanman2_state {
     923             :         connection_struct *conn;
     924             :         uint32_t info_level;
     925             :         bool check_mangled_names;
     926             :         bool case_sensitive;
     927             : };
     928             : 
     929      908548 : static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
     930             :                                          void *private_data,
     931             :                                          const char *dname,
     932             :                                          const char *mask,
     933             :                                          char **_fname)
     934             : {
     935      908548 :         struct smbd_dirptr_lanman2_state *state =
     936             :                 (struct smbd_dirptr_lanman2_state *)private_data;
     937         315 :         bool ok;
     938         315 :         char mangled_name[13]; /* mangled 8.3 name. */
     939         315 :         bool got_match;
     940         315 :         const char *fname;
     941             : 
     942             :         /* Mangle fname if it's an illegal name. */
     943      908548 :         if (mangle_must_mangle(dname, state->conn->params)) {
     944             :                 /*
     945             :                  * Slow path - ensure we can push the original name as UCS2. If
     946             :                  * not, then just don't return this name.
     947             :                  */
     948           0 :                 NTSTATUS status;
     949         106 :                 size_t ret_len = 0;
     950         106 :                 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
     951         106 :                 uint8_t *tmp = talloc_array(talloc_tos(),
     952             :                                         uint8_t,
     953             :                                         len);
     954             : 
     955         106 :                 status = srvstr_push(NULL,
     956             :                         FLAGS2_UNICODE_STRINGS,
     957             :                         tmp,
     958             :                         dname,
     959             :                         len,
     960             :                         STR_TERMINATE,
     961             :                         &ret_len);
     962             : 
     963         106 :                 TALLOC_FREE(tmp);
     964             : 
     965         106 :                 if (!NT_STATUS_IS_OK(status)) {
     966          40 :                         return false;
     967             :                 }
     968             : 
     969          66 :                 ok = name_to_8_3(dname, mangled_name,
     970          66 :                                  true, state->conn->params);
     971          66 :                 if (!ok) {
     972           0 :                         return false;
     973             :                 }
     974          66 :                 fname = mangled_name;
     975             :         } else {
     976      908127 :                 fname = dname;
     977             :         }
     978             : 
     979      908823 :         got_match = mask_match(fname, mask,
     980      908508 :                                state->case_sensitive);
     981             : 
     982      908508 :         if(!got_match && state->check_mangled_names &&
     983        5747 :            !mangle_is_8_3(fname, false, state->conn->params)) {
     984             :                 /*
     985             :                  * It turns out that NT matches wildcards against
     986             :                  * both long *and* short names. This may explain some
     987             :                  * of the wildcard weirdness from old DOS clients
     988             :                  * that some people have been seeing.... JRA.
     989             :                  */
     990             :                 /* Force the mangling into 8.3. */
     991        3348 :                 ok = name_to_8_3(fname, mangled_name,
     992        3348 :                                  false, state->conn->params);
     993        3348 :                 if (!ok) {
     994           0 :                         return false;
     995             :                 }
     996             : 
     997        3348 :                 got_match = mask_match(mangled_name, mask,
     998        3348 :                                        state->case_sensitive);
     999             :         }
    1000             : 
    1001      908508 :         if (!got_match) {
    1002        5743 :                 return false;
    1003             :         }
    1004             : 
    1005      902765 :         *_fname = talloc_strdup(ctx, fname);
    1006      902765 :         if (*_fname == NULL) {
    1007           0 :                 return false;
    1008             :         }
    1009             : 
    1010      902450 :         return true;
    1011             : }
    1012             : 
    1013      625635 : static uint32_t get_dirent_ea_size(uint32_t mode, files_struct *fsp)
    1014             : {
    1015      625635 :         if (!(mode & FILE_ATTRIBUTE_REPARSE_POINT)) {
    1016      625265 :                 unsigned ea_size = estimate_ea_size(fsp);
    1017      625265 :                 return ea_size;
    1018             :         }
    1019         370 :         return IO_REPARSE_TAG_DFS;
    1020             : }
    1021             : 
    1022      894407 : static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
    1023             :                                     connection_struct *conn,
    1024             :                                     uint16_t flags2,
    1025             :                                     uint32_t info_level,
    1026             :                                     struct ea_list *name_list,
    1027             :                                     bool check_mangled_names,
    1028             :                                     bool requires_resume_key,
    1029             :                                     uint32_t mode,
    1030             :                                     const char *fname,
    1031             :                                     const struct smb_filename *smb_fname,
    1032             :                                     int space_remaining,
    1033             :                                     uint8_t align,
    1034             :                                     bool do_pad,
    1035             :                                     char *base_data,
    1036             :                                     char **ppdata,
    1037             :                                     char *end_data,
    1038             :                                     uint64_t *last_entry_off)
    1039             : {
    1040      894407 :         char *p, *q, *pdata = *ppdata;
    1041      894407 :         uint32_t reskey=0;
    1042      894407 :         uint64_t file_size = 0;
    1043      894407 :         uint64_t allocation_size = 0;
    1044      894407 :         uint64_t file_id = 0;
    1045      894407 :         size_t len = 0;
    1046      894407 :         struct timespec mdate_ts = {0};
    1047      894407 :         struct timespec adate_ts = {0};
    1048      894407 :         struct timespec cdate_ts = {0};
    1049      894407 :         struct timespec create_date_ts = {0};
    1050      894407 :         time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
    1051         227 :         char *nameptr;
    1052         227 :         char *last_entry_ptr;
    1053         227 :         bool was_8_3;
    1054         227 :         int off;
    1055      894407 :         int pad = 0;
    1056         227 :         NTSTATUS status;
    1057      894407 :         struct readdir_attr_data *readdir_attr_data = NULL;
    1058         227 :         uint32_t ea_size;
    1059             : 
    1060      894407 :         if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
    1061      833460 :                 file_size = get_file_size_stat(&smb_fname->st);
    1062             :         }
    1063      894407 :         allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
    1064             : 
    1065             :         /*
    1066             :          * Skip SMB_VFS_FREADDIR_ATTR if the directory entry is a symlink or
    1067             :          * a DFS symlink.
    1068             :          */
    1069      894407 :         if (smb_fname->fsp != NULL &&
    1070      894180 :             !(mode & FILE_ATTRIBUTE_REPARSE_POINT)) {
    1071      894037 :                 status = SMB_VFS_FREADDIR_ATTR(smb_fname->fsp,
    1072             :                                                ctx,
    1073             :                                                &readdir_attr_data);
    1074      894037 :                 if (!NT_STATUS_IS_OK(status)) {
    1075      893733 :                         if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED,
    1076             :                                              status)) {
    1077           0 :                                 return status;
    1078             :                         }
    1079             :                 }
    1080             :         }
    1081             : 
    1082      894407 :         file_id = SMB_VFS_FS_FILE_ID(conn, &smb_fname->st);
    1083             : 
    1084      894407 :         mdate_ts = smb_fname->st.st_ex_mtime;
    1085      894407 :         adate_ts = smb_fname->st.st_ex_atime;
    1086      894407 :         create_date_ts = get_create_timespec(conn, NULL, smb_fname);
    1087      894407 :         cdate_ts = get_change_timespec(conn, NULL, smb_fname);
    1088             : 
    1089      894407 :         if (lp_dos_filetime_resolution(SNUM(conn))) {
    1090           0 :                 dos_filetime_timespec(&create_date_ts);
    1091           0 :                 dos_filetime_timespec(&mdate_ts);
    1092           0 :                 dos_filetime_timespec(&adate_ts);
    1093           0 :                 dos_filetime_timespec(&cdate_ts);
    1094             :         }
    1095             : 
    1096      894407 :         create_date = convert_timespec_to_time_t(create_date_ts);
    1097      894407 :         mdate = convert_timespec_to_time_t(mdate_ts);
    1098      894407 :         adate = convert_timespec_to_time_t(adate_ts);
    1099             : 
    1100             :         /* align the record */
    1101      894407 :         SMB_ASSERT(align >= 1);
    1102             : 
    1103      894407 :         off = (int)PTR_DIFF(pdata, base_data);
    1104      894407 :         pad = (off + (align-1)) & ~(align-1);
    1105      894407 :         pad -= off;
    1106             : 
    1107      894407 :         if (pad && pad > space_remaining) {
    1108           0 :                 DEBUG(9,("smbd_marshall_dir_entry: out of space "
    1109             :                         "for padding (wanted %u, had %d)\n",
    1110             :                         (unsigned int)pad,
    1111             :                         space_remaining ));
    1112           0 :                 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
    1113             :         }
    1114             : 
    1115      894407 :         off += pad;
    1116             :         /* initialize padding to 0 */
    1117      894407 :         if (pad) {
    1118      643383 :                 memset(pdata, 0, pad);
    1119             :         }
    1120      894407 :         space_remaining -= pad;
    1121             : 
    1122      894407 :         DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
    1123             :                 space_remaining ));
    1124             : 
    1125      894407 :         pdata += pad;
    1126      894407 :         p = pdata;
    1127      894407 :         last_entry_ptr = p;
    1128             : 
    1129      894407 :         pad = 0;
    1130      894407 :         off = 0;
    1131             : 
    1132      894407 :         switch (info_level) {
    1133        8406 :         case SMB_FIND_INFO_STANDARD:
    1134        8406 :                 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
    1135        8406 :                 if(requires_resume_key) {
    1136           0 :                         SIVAL(p,0,reskey);
    1137           0 :                         p += 4;
    1138             :                 }
    1139        8406 :                 srv_put_dos_date2(p,0,create_date);
    1140        8406 :                 srv_put_dos_date2(p,4,adate);
    1141        8406 :                 srv_put_dos_date2(p,8,mdate);
    1142        8406 :                 SIVAL(p,12,(uint32_t)file_size);
    1143        8406 :                 SIVAL(p,16,(uint32_t)allocation_size);
    1144        8406 :                 SSVAL(p,20,mode);
    1145        8406 :                 p += 23;
    1146        8406 :                 nameptr = p;
    1147        8406 :                 if (flags2 & FLAGS2_UNICODE_STRINGS) {
    1148        8406 :                         p += ucs2_align(base_data, p, 0);
    1149             :                 }
    1150        8406 :                 status = srvstr_push(base_data, flags2, p,
    1151             :                                   fname, PTR_DIFF(end_data, p),
    1152             :                                   STR_TERMINATE, &len);
    1153        8406 :                 if (!NT_STATUS_IS_OK(status)) {
    1154          40 :                         return status;
    1155             :                 }
    1156        8406 :                 if (flags2 & FLAGS2_UNICODE_STRINGS) {
    1157        8406 :                         if (len > 2) {
    1158        8406 :                                 SCVAL(nameptr, -1, len - 2);
    1159             :                         } else {
    1160           0 :                                 SCVAL(nameptr, -1, 0);
    1161             :                         }
    1162             :                 } else {
    1163           0 :                         if (len > 1) {
    1164           0 :                                 SCVAL(nameptr, -1, len - 1);
    1165             :                         } else {
    1166           0 :                                 SCVAL(nameptr, -1, 0);
    1167             :                         }
    1168             :                 }
    1169        8406 :                 p += len;
    1170        8406 :                 break;
    1171             : 
    1172      106206 :         case SMB_FIND_EA_SIZE:
    1173      106206 :                 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
    1174      106206 :                 if (requires_resume_key) {
    1175       97800 :                         SIVAL(p,0,reskey);
    1176       97800 :                         p += 4;
    1177             :                 }
    1178      106206 :                 srv_put_dos_date2(p,0,create_date);
    1179      106206 :                 srv_put_dos_date2(p,4,adate);
    1180      106206 :                 srv_put_dos_date2(p,8,mdate);
    1181      106206 :                 SIVAL(p,12,(uint32_t)file_size);
    1182      106206 :                 SIVAL(p,16,(uint32_t)allocation_size);
    1183      106206 :                 SSVAL(p,20,mode);
    1184             :                 {
    1185      106206 :                         ea_size = estimate_ea_size(smb_fname->fsp);
    1186      106206 :                         SIVAL(p,22,ea_size); /* Extended attributes */
    1187             :                 }
    1188      106206 :                 p += 27;
    1189      106206 :                 nameptr = p - 1;
    1190      106206 :                 status = srvstr_push(base_data, flags2,
    1191             :                                   p, fname, PTR_DIFF(end_data, p),
    1192             :                                   STR_TERMINATE | STR_NOALIGN, &len);
    1193      106206 :                 if (!NT_STATUS_IS_OK(status)) {
    1194           0 :                         return status;
    1195             :                 }
    1196      106206 :                 if (flags2 & FLAGS2_UNICODE_STRINGS) {
    1197      106206 :                         if (len > 2) {
    1198      106206 :                                 len -= 2;
    1199             :                         } else {
    1200           0 :                                 len = 0;
    1201             :                         }
    1202             :                 } else {
    1203           0 :                         if (len > 1) {
    1204           0 :                                 len -= 1;
    1205             :                         } else {
    1206           0 :                                 len = 0;
    1207             :                         }
    1208             :                 }
    1209      106206 :                 SCVAL(nameptr,0,len);
    1210      106206 :                 p += len;
    1211      106206 :                 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
    1212      106206 :                 break;
    1213             : 
    1214          18 :         case SMB_FIND_EA_LIST:
    1215             :         {
    1216          18 :                 struct ea_list *file_list = NULL;
    1217          18 :                 size_t ea_len = 0;
    1218             : 
    1219          18 :                 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
    1220          18 :                 if (!name_list) {
    1221           0 :                         return NT_STATUS_INVALID_PARAMETER;
    1222             :                 }
    1223          18 :                 if (requires_resume_key) {
    1224          18 :                         SIVAL(p,0,reskey);
    1225          18 :                         p += 4;
    1226             :                 }
    1227          18 :                 srv_put_dos_date2(p,0,create_date);
    1228          18 :                 srv_put_dos_date2(p,4,adate);
    1229          18 :                 srv_put_dos_date2(p,8,mdate);
    1230          18 :                 SIVAL(p,12,(uint32_t)file_size);
    1231          18 :                 SIVAL(p,16,(uint32_t)allocation_size);
    1232          18 :                 SSVAL(p,20,mode);
    1233          18 :                 p += 22; /* p now points to the EA area. */
    1234             : 
    1235          18 :                 status = get_ea_list_from_fsp(ctx,
    1236          18 :                                                smb_fname->fsp,
    1237             :                                                &ea_len, &file_list);
    1238          18 :                 if (!NT_STATUS_IS_OK(status)) {
    1239           0 :                         file_list = NULL;
    1240             :                 }
    1241          18 :                 name_list = ea_list_union(name_list, file_list, &ea_len);
    1242             : 
    1243             :                 /* We need to determine if this entry will fit in the space available. */
    1244             :                 /* Max string size is 255 bytes. */
    1245          18 :                 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
    1246           0 :                         DEBUG(9,("smbd_marshall_dir_entry: out of space "
    1247             :                                 "(wanted %u, had %d)\n",
    1248             :                                 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
    1249             :                                 space_remaining ));
    1250           0 :                         return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
    1251             :                 }
    1252             : 
    1253             :                 /* Push the ea_data followed by the name. */
    1254          18 :                 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
    1255          18 :                 nameptr = p;
    1256          18 :                 status = srvstr_push(base_data, flags2,
    1257             :                                   p + 1, fname, PTR_DIFF(end_data, p+1),
    1258             :                                   STR_TERMINATE | STR_NOALIGN, &len);
    1259          18 :                 if (!NT_STATUS_IS_OK(status)) {
    1260           0 :                         return status;
    1261             :                 }
    1262          18 :                 if (flags2 & FLAGS2_UNICODE_STRINGS) {
    1263          18 :                         if (len > 2) {
    1264          18 :                                 len -= 2;
    1265             :                         } else {
    1266           0 :                                 len = 0;
    1267             :                         }
    1268             :                 } else {
    1269           0 :                         if (len > 1) {
    1270           0 :                                 len -= 1;
    1271             :                         } else {
    1272           0 :                                 len = 0;
    1273             :                         }
    1274             :                 }
    1275          18 :                 SCVAL(nameptr,0,len);
    1276          18 :                 p += len + 1;
    1277          18 :                 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
    1278          18 :                 break;
    1279             :         }
    1280             : 
    1281      113644 :         case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
    1282      113644 :                 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
    1283      113644 :                 was_8_3 = mangle_is_8_3(fname, True, conn->params);
    1284      113644 :                 p += 4;
    1285      113644 :                 SIVAL(p,0,reskey); p += 4;
    1286      113644 :                 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
    1287      113644 :                 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
    1288      113644 :                 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
    1289      113644 :                 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
    1290      113644 :                 SOFF_T(p,0,file_size); p += 8;
    1291      113644 :                 SOFF_T(p,0,allocation_size); p += 8;
    1292      113644 :                 SIVAL(p,0,mode); p += 4;
    1293      113644 :                 q = p; p += 4; /* q is placeholder for name length. */
    1294      113644 :                 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
    1295      113644 :                 SIVAL(p, 0, ea_size);
    1296      113644 :                 p += 4;
    1297             :                 /* Clear the short name buffer. This is
    1298             :                  * IMPORTANT as not doing so will trigger
    1299             :                  * a Win2k client bug. JRA.
    1300             :                  */
    1301      113644 :                 if (!was_8_3 && check_mangled_names) {
    1302          25 :                         char mangled_name[13]; /* mangled 8.3 name. */
    1303       20088 :                         if (!name_to_8_3(fname,mangled_name,True,
    1304       20088 :                                            conn->params)) {
    1305             :                                 /* Error - mangle failed ! */
    1306           0 :                                 memset(mangled_name,'\0',12);
    1307             :                         }
    1308       20088 :                         mangled_name[12] = 0;
    1309       20088 :                         status = srvstr_push(base_data, flags2,
    1310             :                                           p+2, mangled_name, 24,
    1311             :                                           STR_UPPER|STR_UNICODE, &len);
    1312       20088 :                         if (!NT_STATUS_IS_OK(status)) {
    1313           0 :                                 return status;
    1314             :                         }
    1315       20088 :                         if (len < 24) {
    1316       10899 :                                 memset(p + 2 + len,'\0',24 - len);
    1317             :                         }
    1318       20088 :                         SSVAL(p, 0, len);
    1319             :                 } else {
    1320       93556 :                         memset(p,'\0',26);
    1321             :                 }
    1322      113644 :                 p += 2 + 24;
    1323      113644 :                 status = srvstr_push(base_data, flags2, p,
    1324             :                                   fname, PTR_DIFF(end_data, p),
    1325             :                                   STR_TERMINATE_ASCII, &len);
    1326      113644 :                 if (!NT_STATUS_IS_OK(status)) {
    1327          12 :                         return status;
    1328             :                 }
    1329      113632 :                 SIVAL(q,0,len);
    1330      113632 :                 p += len;
    1331             : 
    1332      113632 :                 len = PTR_DIFF(p, pdata);
    1333      113632 :                 pad = (len + (align-1)) & ~(align-1);
    1334             :                 /*
    1335             :                  * offset to the next entry, the caller
    1336             :                  * will overwrite it for the last entry
    1337             :                  * that's why we always include the padding
    1338             :                  */
    1339      113632 :                 SIVAL(pdata,0,pad);
    1340             :                 /*
    1341             :                  * set padding to zero
    1342             :                  */
    1343      113632 :                 if (do_pad) {
    1344       50044 :                         memset(p, 0, pad - len);
    1345       50044 :                         p = pdata + pad;
    1346             :                 } else {
    1347       63588 :                         p = pdata + len;
    1348             :                 }
    1349      113498 :                 break;
    1350             : 
    1351       20700 :         case SMB_FIND_FILE_DIRECTORY_INFO:
    1352       20700 :                 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
    1353       20700 :                 p += 4;
    1354       20700 :                 SIVAL(p,0,reskey); p += 4;
    1355       20700 :                 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
    1356       20700 :                 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
    1357       20700 :                 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
    1358       20700 :                 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
    1359       20700 :                 SOFF_T(p,0,file_size); p += 8;
    1360       20700 :                 SOFF_T(p,0,allocation_size); p += 8;
    1361       20700 :                 SIVAL(p,0,mode); p += 4;
    1362       20700 :                 status = srvstr_push(base_data, flags2,
    1363             :                                   p + 4, fname, PTR_DIFF(end_data, p+4),
    1364             :                                   STR_TERMINATE_ASCII, &len);
    1365       20700 :                 if (!NT_STATUS_IS_OK(status)) {
    1366           0 :                         return status;
    1367             :                 }
    1368       20700 :                 SIVAL(p,0,len);
    1369       20700 :                 p += 4 + len;
    1370             : 
    1371       20700 :                 len = PTR_DIFF(p, pdata);
    1372       20700 :                 pad = (len + (align-1)) & ~(align-1);
    1373             :                 /*
    1374             :                  * offset to the next entry, the caller
    1375             :                  * will overwrite it for the last entry
    1376             :                  * that's why we always include the padding
    1377             :                  */
    1378       20700 :                 SIVAL(pdata,0,pad);
    1379             :                 /*
    1380             :                  * set padding to zero
    1381             :                  */
    1382       20700 :                 if (do_pad) {
    1383        8406 :                         memset(p, 0, pad - len);
    1384        8406 :                         p = pdata + pad;
    1385             :                 } else {
    1386       12294 :                         p = pdata + len;
    1387             :                 }
    1388       20700 :                 break;
    1389             : 
    1390      420921 :         case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
    1391      420921 :                 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
    1392      420921 :                 p += 4;
    1393      420921 :                 SIVAL(p,0,reskey); p += 4;
    1394      420921 :                 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
    1395      420921 :                 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
    1396      420921 :                 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
    1397      420921 :                 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
    1398      420921 :                 SOFF_T(p,0,file_size); p += 8;
    1399      420921 :                 SOFF_T(p,0,allocation_size); p += 8;
    1400      420921 :                 SIVAL(p,0,mode); p += 4;
    1401      420921 :                 q = p; p += 4; /* q is placeholder for name length. */
    1402      420921 :                 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
    1403      420921 :                 SIVAL(p, 0, ea_size);
    1404      420921 :                 p +=4;
    1405      420921 :                 status = srvstr_push(base_data, flags2, p,
    1406             :                                   fname, PTR_DIFF(end_data, p),
    1407             :                                   STR_TERMINATE_ASCII, &len);
    1408      420921 :                 if (!NT_STATUS_IS_OK(status)) {
    1409           0 :                         return status;
    1410             :                 }
    1411      420921 :                 SIVAL(q, 0, len);
    1412      420921 :                 p += len;
    1413             : 
    1414      420921 :                 len = PTR_DIFF(p, pdata);
    1415      420921 :                 pad = (len + (align-1)) & ~(align-1);
    1416             :                 /*
    1417             :                  * offset to the next entry, the caller
    1418             :                  * will overwrite it for the last entry
    1419             :                  * that's why we always include the padding
    1420             :                  */
    1421      420921 :                 SIVAL(pdata,0,pad);
    1422             :                 /*
    1423             :                  * set padding to zero
    1424             :                  */
    1425      420921 :                 if (do_pad) {
    1426        8841 :                         memset(p, 0, pad - len);
    1427        8841 :                         p = pdata + pad;
    1428             :                 } else {
    1429      412080 :                         p = pdata + len;
    1430             :                 }
    1431      420834 :                 break;
    1432             : 
    1433      131903 :         case SMB_FIND_FILE_NAMES_INFO:
    1434      131903 :                 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
    1435      131903 :                 p += 4;
    1436      131903 :                 SIVAL(p,0,reskey); p += 4;
    1437      131903 :                 p += 4;
    1438             :                 /* this must *not* be null terminated or w2k gets in a loop trying to set an
    1439             :                    acl on a dir (tridge) */
    1440      131903 :                 status = srvstr_push(base_data, flags2, p,
    1441             :                                   fname, PTR_DIFF(end_data, p),
    1442             :                                   STR_TERMINATE_ASCII, &len);
    1443      131903 :                 if (!NT_STATUS_IS_OK(status)) {
    1444           0 :                         return status;
    1445             :                 }
    1446      131903 :                 SIVAL(p, -4, len);
    1447      131903 :                 p += len;
    1448             : 
    1449      131903 :                 len = PTR_DIFF(p, pdata);
    1450      131903 :                 pad = (len + (align-1)) & ~(align-1);
    1451             :                 /*
    1452             :                  * offset to the next entry, the caller
    1453             :                  * will overwrite it for the last entry
    1454             :                  * that's why we always include the padding
    1455             :                  */
    1456      131903 :                 SIVAL(pdata,0,pad);
    1457             :                 /*
    1458             :                  * set padding to zero
    1459             :                  */
    1460      131903 :                 if (do_pad) {
    1461           6 :                         memset(p, 0, pad - len);
    1462           6 :                         p = pdata + pad;
    1463             :                 } else {
    1464      131897 :                         p = pdata + len;
    1465             :                 }
    1466      131897 :                 break;
    1467             : 
    1468       19638 :         case SMB_FIND_ID_FULL_DIRECTORY_INFO:
    1469       19638 :                 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
    1470       19638 :                 p += 4;
    1471       19638 :                 SIVAL(p,0,reskey); p += 4;
    1472       19638 :                 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
    1473       19638 :                 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
    1474       19638 :                 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
    1475       19638 :                 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
    1476       19638 :                 SOFF_T(p,0,file_size); p += 8;
    1477       19638 :                 SOFF_T(p,0,allocation_size); p += 8;
    1478       19638 :                 SIVAL(p,0,mode); p += 4;
    1479       19638 :                 q = p; p += 4; /* q is placeholder for name length. */
    1480       19638 :                 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
    1481       19638 :                 SIVAL(p, 0, ea_size);
    1482       19638 :                 p += 4;
    1483       19638 :                 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
    1484       19638 :                 SBVAL(p,0,file_id); p += 8;
    1485       19638 :                 status = srvstr_push(base_data, flags2, p,
    1486             :                                   fname, PTR_DIFF(end_data, p),
    1487             :                                   STR_TERMINATE_ASCII, &len);
    1488       19638 :                 if (!NT_STATUS_IS_OK(status)) {
    1489           0 :                         return status;
    1490             :                 }
    1491       19638 :                 SIVAL(q, 0, len);
    1492       19638 :                 p += len;
    1493             : 
    1494       19638 :                 len = PTR_DIFF(p, pdata);
    1495       19638 :                 pad = (len + (align-1)) & ~(align-1);
    1496             :                 /*
    1497             :                  * offset to the next entry, the caller
    1498             :                  * will overwrite it for the last entry
    1499             :                  * that's why we always include the padding
    1500             :                  */
    1501       19638 :                 SIVAL(pdata,0,pad);
    1502             :                 /*
    1503             :                  * set padding to zero
    1504             :                  */
    1505       19638 :                 if (do_pad) {
    1506        8406 :                         memset(p, 0, pad - len);
    1507        8406 :                         p = pdata + pad;
    1508             :                 } else {
    1509       11232 :                         p = pdata + len;
    1510             :                 }
    1511       19638 :                 break;
    1512             : 
    1513       71530 :         case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
    1514       71530 :                 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
    1515       71530 :                 was_8_3 = mangle_is_8_3(fname, True, conn->params);
    1516       71530 :                 p += 4;
    1517       71530 :                 SIVAL(p,0,reskey); p += 4;
    1518       71530 :                 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
    1519       71530 :                 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
    1520       71530 :                 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
    1521       71530 :                 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
    1522       71530 :                 SOFF_T(p,0,file_size); p += 8;
    1523       71530 :                 SOFF_T(p,0,allocation_size); p += 8;
    1524       71530 :                 SIVAL(p,0,mode); p += 4;
    1525       71530 :                 q = p; p += 4; /* q is placeholder for name length */
    1526       71530 :                 if (readdir_attr_data &&
    1527          98 :                     readdir_attr_data->type == RDATTR_AAPL) {
    1528             :                         /*
    1529             :                          * OS X specific SMB2 extension negotiated via
    1530             :                          * AAPL create context: return max_access in
    1531             :                          * ea_size field.
    1532             :                          */
    1533          98 :                         ea_size = readdir_attr_data->attr_data.aapl.max_access;
    1534             :                 } else {
    1535       71432 :                         ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
    1536             :                 }
    1537       71530 :                 SIVAL(p,0,ea_size); /* Extended attributes */
    1538       71530 :                 p += 4;
    1539             : 
    1540       71530 :                 if (readdir_attr_data &&
    1541          98 :                     readdir_attr_data->type == RDATTR_AAPL) {
    1542             :                         /*
    1543             :                          * OS X specific SMB2 extension negotiated via
    1544             :                          * AAPL create context: return resource fork
    1545             :                          * length and compressed FinderInfo in
    1546             :                          * shortname field.
    1547             :                          *
    1548             :                          * According to documentation short_name_len
    1549             :                          * should be 0, but on the wire behaviour
    1550             :                          * shows its set to 24 by clients.
    1551             :                          */
    1552          98 :                         SSVAL(p, 0, 24);
    1553             : 
    1554             :                         /* Resourefork length */
    1555          98 :                         SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
    1556             : 
    1557             :                         /* Compressed FinderInfo */
    1558          98 :                         memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
    1559       71432 :                 } else if (!was_8_3 && check_mangled_names) {
    1560           0 :                         char mangled_name[13]; /* mangled 8.3 name. */
    1561       22221 :                         if (!name_to_8_3(fname,mangled_name,True,
    1562       22221 :                                         conn->params)) {
    1563             :                                 /* Error - mangle failed ! */
    1564           0 :                                 memset(mangled_name,'\0',12);
    1565             :                         }
    1566       22221 :                         mangled_name[12] = 0;
    1567       22221 :                         status = srvstr_push(base_data, flags2,
    1568             :                                           p+2, mangled_name, 24,
    1569             :                                           STR_UPPER|STR_UNICODE, &len);
    1570       22221 :                         if (!NT_STATUS_IS_OK(status)) {
    1571           0 :                                 return status;
    1572             :                         }
    1573       22221 :                         SSVAL(p, 0, len);
    1574       22221 :                         if (len < 24) {
    1575       20585 :                                 memset(p + 2 + len,'\0',24 - len);
    1576             :                         }
    1577       22221 :                         SSVAL(p, 0, len);
    1578             :                 } else {
    1579             :                         /* Clear the short name buffer. This is
    1580             :                          * IMPORTANT as not doing so will trigger
    1581             :                          * a Win2k client bug. JRA.
    1582             :                          */
    1583       49211 :                         memset(p,'\0',26);
    1584             :                 }
    1585       71530 :                 p += 26;
    1586             : 
    1587             :                 /* Reserved ? */
    1588       71530 :                 if (readdir_attr_data &&
    1589          98 :                     readdir_attr_data->type == RDATTR_AAPL) {
    1590             :                         /*
    1591             :                          * OS X specific SMB2 extension negotiated via
    1592             :                          * AAPL create context: return UNIX mode in
    1593             :                          * reserved field.
    1594             :                          */
    1595          98 :                         uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
    1596          98 :                         SSVAL(p, 0, aapl_mode);
    1597             :                 } else {
    1598       71432 :                         SSVAL(p, 0, 0);
    1599             :                 }
    1600       71530 :                 p += 2;
    1601             : 
    1602       71530 :                 SBVAL(p,0,file_id); p += 8;
    1603       71530 :                 status = srvstr_push(base_data, flags2, p,
    1604             :                                   fname, PTR_DIFF(end_data, p),
    1605             :                                   STR_TERMINATE_ASCII, &len);
    1606       71530 :                 if (!NT_STATUS_IS_OK(status)) {
    1607          28 :                         return status;
    1608             :                 }
    1609       71502 :                 SIVAL(q,0,len);
    1610       71502 :                 p += len;
    1611             : 
    1612       71502 :                 len = PTR_DIFF(p, pdata);
    1613       71502 :                 pad = (len + (align-1)) & ~(align-1);
    1614             :                 /*
    1615             :                  * offset to the next entry, the caller
    1616             :                  * will overwrite it for the last entry
    1617             :                  * that's why we always include the padding
    1618             :                  */
    1619       71502 :                 SIVAL(pdata,0,pad);
    1620             :                 /*
    1621             :                  * set padding to zero
    1622             :                  */
    1623       71502 :                 if (do_pad) {
    1624        8406 :                         memset(p, 0, pad - len);
    1625        8406 :                         p = pdata + pad;
    1626             :                 } else {
    1627       63096 :                         p = pdata + len;
    1628             :                 }
    1629       71502 :                 break;
    1630             : 
    1631             :         /* CIFS UNIX Extension. */
    1632             : 
    1633          10 :         case SMB_FIND_FILE_UNIX:
    1634             :         case SMB_FIND_FILE_UNIX_INFO2:
    1635          10 :                 p+= 4;
    1636          10 :                 SIVAL(p,0,reskey); p+= 4;    /* Used for continuing search. */
    1637             : 
    1638             :                 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
    1639             : 
    1640          10 :                 if (info_level == SMB_FIND_FILE_UNIX) {
    1641           6 :                         DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
    1642           6 :                         p = store_file_unix_basic(conn, p,
    1643             :                                                 NULL, &smb_fname->st);
    1644           6 :                         status = srvstr_push(base_data, flags2, p,
    1645             :                                           fname, PTR_DIFF(end_data, p),
    1646             :                                           STR_TERMINATE, &len);
    1647           6 :                         if (!NT_STATUS_IS_OK(status)) {
    1648           0 :                                 return status;
    1649             :                         }
    1650             :                 } else {
    1651           4 :                         DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
    1652           4 :                         p = store_file_unix_basic_info2(conn, p,
    1653             :                                                 NULL, &smb_fname->st);
    1654           4 :                         nameptr = p;
    1655           4 :                         p += 4;
    1656           4 :                         status = srvstr_push(base_data, flags2, p, fname,
    1657             :                                           PTR_DIFF(end_data, p), 0, &len);
    1658           4 :                         if (!NT_STATUS_IS_OK(status)) {
    1659           0 :                                 return status;
    1660             :                         }
    1661           4 :                         SIVAL(nameptr, 0, len);
    1662             :                 }
    1663             : 
    1664          10 :                 p += len;
    1665             : 
    1666          10 :                 len = PTR_DIFF(p, pdata);
    1667          10 :                 pad = (len + (align-1)) & ~(align-1);
    1668             :                 /*
    1669             :                  * offset to the next entry, the caller
    1670             :                  * will overwrite it for the last entry
    1671             :                  * that's why we always include the padding
    1672             :                  */
    1673          10 :                 SIVAL(pdata,0,pad);
    1674             :                 /*
    1675             :                  * set padding to zero
    1676             :                  */
    1677          10 :                 if (do_pad) {
    1678          10 :                         memset(p, 0, pad - len);
    1679          10 :                         p = pdata + pad;
    1680             :                 } else {
    1681           0 :                         p = pdata + len;
    1682             :                 }
    1683             :                 /* End of SMB_QUERY_FILE_UNIX_BASIC */
    1684             : 
    1685          10 :                 break;
    1686             : 
    1687             :         /* SMB2 UNIX Extension. */
    1688             : 
    1689        1431 :         case SMB2_FILE_POSIX_INFORMATION:
    1690             :                 {
    1691        1431 :                         struct smb3_file_posix_information info = {};
    1692           0 :                         uint8_t buf[sizeof(info)];
    1693        1431 :                         struct ndr_push ndr = {
    1694             :                                 .data = buf,
    1695             :                                 .alloc_size = sizeof(buf),
    1696             :                                 .fixed_buf_size = true,
    1697             :                         };
    1698           0 :                         enum ndr_err_code ndr_err;
    1699             : 
    1700        1431 :                         p+= 4;
    1701        1431 :                         SIVAL(p,0,reskey); p+= 4;
    1702             : 
    1703        1431 :                         DBG_DEBUG("SMB2_FILE_POSIX_INFORMATION\n");
    1704             : 
    1705        1431 :                         if (!(conn->sconn->using_smb2)) {
    1706           0 :                                 return NT_STATUS_INVALID_LEVEL;
    1707             :                         }
    1708             : 
    1709        1431 :                         smb3_file_posix_information_init(
    1710        1431 :                                 conn, &smb_fname->st, 0, mode, &info);
    1711             : 
    1712        1431 :                         ndr_err = ndr_push_smb3_file_posix_information(
    1713             :                                 &ndr, NDR_SCALARS|NDR_BUFFERS, &info);
    1714        1431 :                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    1715           0 :                                 return NT_STATUS_INSUFFICIENT_RESOURCES;
    1716             :                         }
    1717             : 
    1718        1431 :                         memcpy(p, buf, ndr.offset);
    1719        1431 :                         p += ndr.offset;
    1720             : 
    1721        1431 :                         nameptr = p;
    1722        1431 :                         p += 4;
    1723        1431 :                         status = srvstr_push(base_data, flags2, p, fname,
    1724             :                                         PTR_DIFF(end_data, p), 0, &len);
    1725        1431 :                         if (!NT_STATUS_IS_OK(status)) {
    1726           0 :                                 return status;
    1727             :                         }
    1728        1431 :                         SIVAL(nameptr, 0, len);
    1729             : 
    1730        1431 :                         p += len;
    1731             : 
    1732        1431 :                         len = PTR_DIFF(p, pdata);
    1733        1431 :                         pad = (len + (align-1)) & ~(align-1);
    1734             :                         /*
    1735             :                          * offset to the next entry, the caller
    1736             :                          * will overwrite it for the last entry
    1737             :                          * that's why we always include the padding
    1738             :                          */
    1739        1431 :                         SIVAL(pdata,0,pad);
    1740        1431 :                         break;
    1741             :                 }
    1742             : 
    1743           0 :         default:
    1744           0 :                 return NT_STATUS_INVALID_LEVEL;
    1745             :         }
    1746             : 
    1747      894367 :         if (PTR_DIFF(p,pdata) > space_remaining) {
    1748         668 :                 DEBUG(9,("smbd_marshall_dir_entry: out of space "
    1749             :                         "(wanted %u, had %d)\n",
    1750             :                         (unsigned int)PTR_DIFF(p,pdata),
    1751             :                         space_remaining ));
    1752         668 :                 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
    1753             :         }
    1754             : 
    1755             :         /* Setup the last entry pointer, as an offset from base_data */
    1756      893699 :         *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
    1757             :         /* Advance the data pointer to the next slot */
    1758      893699 :         *ppdata = p;
    1759             : 
    1760      893699 :         return NT_STATUS_OK;
    1761             : }
    1762             : 
    1763      921969 : NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
    1764             :                                connection_struct *conn,
    1765             :                                struct dptr_struct *dirptr,
    1766             :                                uint16_t flags2,
    1767             :                                const char *path_mask,
    1768             :                                uint32_t dirtype,
    1769             :                                int info_level,
    1770             :                                int requires_resume_key,
    1771             :                                bool dont_descend,
    1772             :                                bool ask_sharemode,
    1773             :                                bool get_dosmode,
    1774             :                                uint8_t align,
    1775             :                                bool do_pad,
    1776             :                                char **ppdata,
    1777             :                                char *base_data,
    1778             :                                char *end_data,
    1779             :                                int space_remaining,
    1780             :                                struct smb_filename **_smb_fname,
    1781             :                                int *_last_entry_off,
    1782             :                                struct ea_list *name_list,
    1783             :                                struct file_id *file_id)
    1784             : {
    1785         316 :         const char *p;
    1786      921969 :         const char *mask = NULL;
    1787      921969 :         uint32_t mode = 0;
    1788      921969 :         char *fname = NULL;
    1789      921969 :         struct smb_filename *smb_fname = NULL;
    1790         316 :         struct smbd_dirptr_lanman2_state state;
    1791         316 :         bool ok;
    1792      921969 :         uint64_t last_entry_off = 0;
    1793         316 :         NTSTATUS status;
    1794         316 :         enum mangled_names_options mangled_names;
    1795         316 :         bool marshall_with_83_names;
    1796             : 
    1797      921969 :         mangled_names = lp_mangled_names(conn->params);
    1798             : 
    1799      921969 :         ZERO_STRUCT(state);
    1800      921969 :         state.conn = conn;
    1801      921969 :         state.info_level = info_level;
    1802      921969 :         if (mangled_names != MANGLED_NAMES_NO) {
    1803      920373 :                 state.check_mangled_names = true;
    1804             :         }
    1805      921969 :         state.case_sensitive = dptr_case_sensitive(dirptr);
    1806             : 
    1807      921969 :         p = strrchr_m(path_mask,'/');
    1808      921969 :         if(p != NULL) {
    1809           0 :                 if(p[1] == '\0') {
    1810           0 :                         mask = "*.*";
    1811             :                 } else {
    1812           0 :                         mask = p+1;
    1813             :                 }
    1814             :         } else {
    1815      921653 :                 mask = path_mask;
    1816             :         }
    1817             : 
    1818      921969 :         ok = smbd_dirptr_get_entry(ctx,
    1819             :                                    dirptr,
    1820             :                                    mask,
    1821             :                                    dirtype,
    1822             :                                    dont_descend,
    1823             :                                    ask_sharemode,
    1824             :                                    get_dosmode,
    1825             :                                    smbd_dirptr_lanman2_match_fn,
    1826             :                                    &state,
    1827             :                                    &fname,
    1828             :                                    &smb_fname,
    1829             :                                    &mode);
    1830      921969 :         if (!ok) {
    1831       27562 :                 return NT_STATUS_END_OF_FILE;
    1832             :         }
    1833             : 
    1834      894407 :         marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
    1835             : 
    1836      894407 :         status = smbd_marshall_dir_entry(ctx,
    1837             :                                      conn,
    1838             :                                      flags2,
    1839             :                                      info_level,
    1840             :                                      name_list,
    1841             :                                      marshall_with_83_names,
    1842             :                                      requires_resume_key,
    1843             :                                      mode,
    1844             :                                      fname,
    1845             :                                      smb_fname,
    1846             :                                      space_remaining,
    1847             :                                      align,
    1848             :                                      do_pad,
    1849             :                                      base_data,
    1850             :                                      ppdata,
    1851             :                                      end_data,
    1852             :                                      &last_entry_off);
    1853      894407 :         if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
    1854          40 :                 DEBUG(1,("Conversion error: illegal character: %s\n",
    1855             :                          smb_fname_str_dbg(smb_fname)));
    1856             :         }
    1857             : 
    1858      894407 :         if (file_id != NULL) {
    1859      695646 :                 *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
    1860             :         }
    1861             : 
    1862      894407 :         if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
    1863         668 :                 smbd_dirptr_push_overflow(dirptr, &fname, &smb_fname, mode);
    1864             :         }
    1865             : 
    1866      894407 :         if (!NT_STATUS_IS_OK(status)) {
    1867         708 :                 TALLOC_FREE(smb_fname);
    1868         708 :                 TALLOC_FREE(fname);
    1869         708 :                 return status;
    1870             :         }
    1871             : 
    1872      893699 :         smbd_dirptr_set_last_name_sent(dirptr, &smb_fname->base_name);
    1873             : 
    1874      893699 :         if (_smb_fname != NULL) {
    1875             :                 /*
    1876             :                  * smb_fname is already talloc'ed off ctx.
    1877             :                  * We just need to make sure we don't return
    1878             :                  * any stream_name, and replace base_name
    1879             :                  * with fname in case base_name got mangled.
    1880             :                  * This allows us to preserve any smb_fname->fsp
    1881             :                  * for asynchronous handle lookups.
    1882             :                  */
    1883      694950 :                 TALLOC_FREE(smb_fname->stream_name);
    1884             : 
    1885             :                 /*
    1886             :                  * smbd_dirptr_set_last_name_sent() above consumed
    1887             :                  * base_name
    1888             :                  */
    1889      694950 :                 smb_fname->base_name = talloc_strdup(smb_fname, fname);
    1890             : 
    1891      694950 :                 if (smb_fname->base_name == NULL) {
    1892           0 :                         TALLOC_FREE(smb_fname);
    1893           0 :                         TALLOC_FREE(fname);
    1894           0 :                         return NT_STATUS_NO_MEMORY;
    1895             :                 }
    1896      694950 :                 *_smb_fname = smb_fname;
    1897             :         } else {
    1898      198749 :                 TALLOC_FREE(smb_fname);
    1899             :         }
    1900      893699 :         TALLOC_FREE(fname);
    1901             : 
    1902      893699 :         *_last_entry_off = last_entry_off;
    1903      893699 :         return NT_STATUS_OK;
    1904             : }
    1905             : 
    1906         112 : unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
    1907             : {
    1908           0 :         const struct loadparm_substitution *lp_sub =
    1909         112 :                 loadparm_s3_global_substitution();
    1910             : 
    1911         112 :         E_md4hash(lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),objid);
    1912         112 :         return objid;
    1913             : }
    1914             : 
    1915          40 : static void samba_extended_info_version(struct smb_extended_info *extended_info)
    1916             : {
    1917          40 :         SMB_ASSERT(extended_info != NULL);
    1918             : 
    1919          40 :         extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
    1920          40 :         extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
    1921             :                                        | ((SAMBA_VERSION_MINOR & 0xff) << 16)
    1922             :                                        | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
    1923             : #ifdef SAMBA_VERSION_REVISION
    1924             :         extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
    1925             : #endif
    1926          40 :         extended_info->samba_subversion = 0;
    1927             : #ifdef SAMBA_VERSION_RC_RELEASE
    1928             :         extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
    1929             : #else
    1930             : #ifdef SAMBA_VERSION_PRE_RELEASE
    1931          40 :         extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
    1932             : #endif
    1933             : #endif
    1934             : #ifdef SAMBA_VERSION_VENDOR_PATCH
    1935             :         extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
    1936             : #endif
    1937          40 :         extended_info->samba_gitcommitdate = 0;
    1938             : #ifdef SAMBA_VERSION_COMMIT_TIME
    1939             :         unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
    1940             : #endif
    1941             : 
    1942          40 :         memset(extended_info->samba_version_string, 0,
    1943             :                sizeof(extended_info->samba_version_string));
    1944             : 
    1945          40 :         snprintf (extended_info->samba_version_string,
    1946             :                   sizeof(extended_info->samba_version_string),
    1947             :                   "%s", samba_version_string());
    1948          40 : }
    1949             : 
    1950           0 : static bool fsinfo_unix_valid_level(connection_struct *conn,
    1951             :                                     uint16_t info_level)
    1952             : {
    1953           0 :         if (conn->sconn->using_smb2 &&
    1954             :             info_level == SMB2_FS_POSIX_INFORMATION_INTERNAL) {
    1955           0 :                 return true;
    1956             :         }
    1957             : #if defined(SMB1SERVER)
    1958             :         if (lp_smb1_unix_extensions() &&
    1959             :                         info_level == SMB_QUERY_POSIX_FS_INFO) {
    1960             :                 return true;
    1961             :         }
    1962             : #endif
    1963           0 :         return false;
    1964             : }
    1965             : 
    1966        3424 : NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
    1967             :                          connection_struct *conn,
    1968             :                          TALLOC_CTX *mem_ctx,
    1969             :                          uint16_t info_level,
    1970             :                          uint16_t flags2,
    1971             :                          unsigned int max_data_bytes,
    1972             :                          size_t *fixed_portion,
    1973             :                          struct smb_filename *fname,
    1974             :                          char **ppdata,
    1975             :                          int *ret_data_len)
    1976             : {
    1977           0 :         const struct loadparm_substitution *lp_sub =
    1978        3424 :                 loadparm_s3_global_substitution();
    1979           0 :         char *pdata, *end_data;
    1980        3424 :         int data_len = 0;
    1981        3424 :         size_t len = 0;
    1982        3424 :         const char *vname = volume_label(talloc_tos(), SNUM(conn));
    1983        3424 :         int snum = SNUM(conn);
    1984        3424 :         const char *fstype = lp_fstype(SNUM(conn));
    1985        3424 :         const char *filename = NULL;
    1986        3424 :         const uint64_t bytes_per_sector = 512;
    1987        3424 :         uint32_t additional_flags = 0;
    1988           0 :         struct smb_filename smb_fname;
    1989           0 :         SMB_STRUCT_STAT st;
    1990        3424 :         NTSTATUS status = NT_STATUS_OK;
    1991           0 :         uint64_t df_ret;
    1992           0 :         uint32_t serial;
    1993             : 
    1994        3424 :         if (fname == NULL || fname->base_name == NULL) {
    1995        1373 :                 filename = ".";
    1996             :         } else {
    1997        2051 :                 filename = fname->base_name;
    1998             :         }
    1999             : 
    2000        3424 :         if (IS_IPC(conn)) {
    2001         240 :                 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
    2002           0 :                         DEBUG(0,("smbd_do_qfsinfo: not an allowed "
    2003             :                                 "info level (0x%x) on IPC$.\n",
    2004             :                                 (unsigned int)info_level));
    2005           0 :                         return NT_STATUS_ACCESS_DENIED;
    2006             :                 }
    2007             :         }
    2008             : 
    2009        3424 :         DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
    2010             : 
    2011        3424 :         smb_fname = (struct smb_filename) {
    2012             :                 .base_name = discard_const_p(char, filename),
    2013        3424 :                 .flags = fname ? fname->flags : 0,
    2014        3424 :                 .twrp = fname ? fname->twrp : 0,
    2015             :         };
    2016             : 
    2017        3424 :         if(info_level != SMB_FS_QUOTA_INFORMATION
    2018        3420 :            && SMB_VFS_STAT(conn, &smb_fname) != 0) {
    2019           0 :                 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
    2020           0 :                 return map_nt_error_from_unix(errno);
    2021             :         }
    2022             : 
    2023        3424 :         st = smb_fname.st;
    2024             : 
    2025        3424 :         if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
    2026           0 :                 return NT_STATUS_INVALID_PARAMETER;
    2027             :         }
    2028             : 
    2029        3424 :         *ppdata = (char *)SMB_REALLOC(
    2030             :                 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
    2031        3424 :         if (*ppdata == NULL) {
    2032           0 :                 return NT_STATUS_NO_MEMORY;
    2033             :         }
    2034             : 
    2035        3424 :         pdata = *ppdata;
    2036        3424 :         memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
    2037        3424 :         end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
    2038             : 
    2039        3424 :         *fixed_portion = 0;
    2040             : 
    2041        3424 :         switch (info_level) {
    2042           0 :                 case SMB_INFO_ALLOCATION:
    2043             :                 {
    2044           0 :                         uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
    2045           0 :                         data_len = 18;
    2046           0 :                         df_ret = get_dfree_info(conn, &smb_fname, &bsize,
    2047             :                                                 &dfree, &dsize);
    2048           0 :                         if (df_ret == (uint64_t)-1) {
    2049           0 :                                 return map_nt_error_from_unix(errno);
    2050             :                         }
    2051             : 
    2052           0 :                         block_size = lp_block_size(snum);
    2053           0 :                         if (bsize < block_size) {
    2054           0 :                                 uint64_t factor = block_size/bsize;
    2055           0 :                                 bsize = block_size;
    2056           0 :                                 dsize /= factor;
    2057           0 :                                 dfree /= factor;
    2058             :                         }
    2059           0 :                         if (bsize > block_size) {
    2060           0 :                                 uint64_t factor = bsize/block_size;
    2061           0 :                                 bsize = block_size;
    2062           0 :                                 dsize *= factor;
    2063           0 :                                 dfree *= factor;
    2064             :                         }
    2065           0 :                         sectors_per_unit = bsize/bytes_per_sector;
    2066             : 
    2067           0 :                         DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
    2068             : cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
    2069             :                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
    2070             : 
    2071             :                         /*
    2072             :                          * For large drives, return max values and not modulo.
    2073             :                          */
    2074           0 :                         dsize = MIN(dsize, UINT32_MAX);
    2075           0 :                         dfree = MIN(dfree, UINT32_MAX);
    2076             : 
    2077           0 :                         SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
    2078           0 :                         SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
    2079           0 :                         SIVAL(pdata,l1_cUnit,dsize);
    2080           0 :                         SIVAL(pdata,l1_cUnitAvail,dfree);
    2081           0 :                         SSVAL(pdata,l1_cbSector,bytes_per_sector);
    2082           0 :                         break;
    2083             :                 }
    2084             : 
    2085           0 :                 case SMB_INFO_VOLUME:
    2086             :                         /* Return volume name */
    2087             :                         /*
    2088             :                          * Add volume serial number - hash of a combination of
    2089             :                          * the called hostname and the service name.
    2090             :                          */
    2091           0 :                         serial = generate_volume_serial_number(lp_sub, snum);
    2092           0 :                         SIVAL(pdata,0,serial);
    2093             :                         /*
    2094             :                          * Win2k3 and previous mess this up by sending a name length
    2095             :                          * one byte short. I believe only older clients (OS/2 Win9x) use
    2096             :                          * this call so try fixing this by adding a terminating null to
    2097             :                          * the pushed string. The change here was adding the STR_TERMINATE. JRA.
    2098             :                          */
    2099           0 :                         status = srvstr_push(
    2100             :                                 pdata, flags2,
    2101             :                                 pdata+l2_vol_szVolLabel, vname,
    2102             :                                 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
    2103             :                                 STR_NOALIGN|STR_TERMINATE, &len);
    2104           0 :                         if (!NT_STATUS_IS_OK(status)) {
    2105           0 :                                 return status;
    2106             :                         }
    2107           0 :                         SCVAL(pdata,l2_vol_cch,len);
    2108           0 :                         data_len = l2_vol_szVolLabel + len;
    2109           0 :                         DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, "
    2110             :                                  "name = %s serial = 0x%04"PRIx32"\n",
    2111             :                                  (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
    2112             :                                  (unsigned)len, vname, serial));
    2113           0 :                         break;
    2114             : 
    2115         548 :                 case SMB_QUERY_FS_ATTRIBUTE_INFO:
    2116             :                 case SMB_FS_ATTRIBUTE_INFORMATION:
    2117             : 
    2118         548 :                         additional_flags = 0;
    2119             : #if defined(HAVE_SYS_QUOTAS)
    2120         548 :                         additional_flags |= FILE_VOLUME_QUOTAS;
    2121             : #endif
    2122             : 
    2123         548 :                         if(lp_nt_acl_support(SNUM(conn))) {
    2124         548 :                                 additional_flags |= FILE_PERSISTENT_ACLS;
    2125             :                         }
    2126             : 
    2127             :                         /* Capabilities are filled in at connection time through STATVFS call */
    2128         548 :                         additional_flags |= conn->fs_capabilities;
    2129         548 :                         additional_flags |= lp_parm_int(conn->params->service,
    2130             :                                                         "share", "fake_fscaps",
    2131             :                                                         0);
    2132             : 
    2133         548 :                         SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
    2134             :                                 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
    2135             :                                 additional_flags); /* FS ATTRIBUTES */
    2136             : 
    2137         548 :                         SIVAL(pdata,4,255); /* Max filename component length */
    2138             :                         /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
    2139             :                                 and will think we can't do long filenames */
    2140         548 :                         status = srvstr_push(pdata, flags2, pdata+12, fstype,
    2141             :                                           PTR_DIFF(end_data, pdata+12),
    2142             :                                           STR_UNICODE, &len);
    2143         548 :                         if (!NT_STATUS_IS_OK(status)) {
    2144           0 :                                 return status;
    2145             :                         }
    2146         548 :                         SIVAL(pdata,8,len);
    2147         548 :                         data_len = 12 + len;
    2148         548 :                         if (max_data_bytes >= 16 && data_len > max_data_bytes) {
    2149             :                                 /* the client only requested a portion of the
    2150             :                                    file system name */
    2151          16 :                                 data_len = max_data_bytes;
    2152          16 :                                 status = STATUS_BUFFER_OVERFLOW;
    2153             :                         }
    2154         548 :                         *fixed_portion = 16;
    2155         548 :                         break;
    2156             : 
    2157           0 :                 case SMB_QUERY_FS_LABEL_INFO:
    2158             :                 case SMB_FS_LABEL_INFORMATION:
    2159           0 :                         status = srvstr_push(pdata, flags2, pdata+4, vname,
    2160             :                                           PTR_DIFF(end_data, pdata+4), 0, &len);
    2161           0 :                         if (!NT_STATUS_IS_OK(status)) {
    2162           0 :                                 return status;
    2163             :                         }
    2164           0 :                         data_len = 4 + len;
    2165           0 :                         SIVAL(pdata,0,len);
    2166           0 :                         break;
    2167             : 
    2168         130 :                 case SMB_QUERY_FS_VOLUME_INFO:
    2169             :                 case SMB_FS_VOLUME_INFORMATION:
    2170         130 :                         put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,
    2171             :                                                     pdata, &st.st_ex_btime);
    2172             :                         /*
    2173             :                          * Add volume serial number - hash of a combination of
    2174             :                          * the called hostname and the service name.
    2175             :                          */
    2176         130 :                         serial = generate_volume_serial_number(lp_sub, snum);
    2177         130 :                         SIVAL(pdata,8,serial);
    2178             : 
    2179             :                         /* Max label len is 32 characters. */
    2180         130 :                         status = srvstr_push(pdata, flags2, pdata+18, vname,
    2181             :                                           PTR_DIFF(end_data, pdata+18),
    2182             :                                           STR_UNICODE, &len);
    2183         130 :                         if (!NT_STATUS_IS_OK(status)) {
    2184           0 :                                 return status;
    2185             :                         }
    2186         130 :                         SIVAL(pdata,12,len);
    2187         130 :                         data_len = 18+len;
    2188             : 
    2189         130 :                         DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO "
    2190             :                                  "namelen = %d, vol=%s serv=%s "
    2191             :                                  "serial=0x%04"PRIx32"\n",
    2192             :                                  (int)strlen(vname),vname,
    2193             :                                  lp_servicename(talloc_tos(), lp_sub, snum),
    2194             :                                  serial));
    2195         130 :                         if (max_data_bytes >= 24 && data_len > max_data_bytes) {
    2196             :                                 /* the client only requested a portion of the
    2197             :                                    volume label */
    2198           0 :                                 data_len = max_data_bytes;
    2199           0 :                                 status = STATUS_BUFFER_OVERFLOW;
    2200             :                         }
    2201         130 :                         *fixed_portion = 24;
    2202         130 :                         break;
    2203             : 
    2204        1214 :                 case SMB_QUERY_FS_SIZE_INFO:
    2205             :                 case SMB_FS_SIZE_INFORMATION:
    2206             :                 {
    2207           0 :                         uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
    2208        1214 :                         data_len = 24;
    2209        1214 :                         df_ret = get_dfree_info(conn, &smb_fname, &bsize,
    2210             :                                                 &dfree, &dsize);
    2211        1214 :                         if (df_ret == (uint64_t)-1) {
    2212           0 :                                 return map_nt_error_from_unix(errno);
    2213             :                         }
    2214        1214 :                         block_size = lp_block_size(snum);
    2215        1214 :                         if (bsize < block_size) {
    2216        1168 :                                 uint64_t factor = block_size/bsize;
    2217        1168 :                                 bsize = block_size;
    2218        1168 :                                 dsize /= factor;
    2219        1168 :                                 dfree /= factor;
    2220             :                         }
    2221        1214 :                         if (bsize > block_size) {
    2222          42 :                                 uint64_t factor = bsize/block_size;
    2223          42 :                                 bsize = block_size;
    2224          42 :                                 dsize *= factor;
    2225          42 :                                 dfree *= factor;
    2226             :                         }
    2227        1214 :                         sectors_per_unit = bsize/bytes_per_sector;
    2228        1214 :                         DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
    2229             : cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
    2230             :                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
    2231        1214 :                         SBIG_UINT(pdata,0,dsize);
    2232        1214 :                         SBIG_UINT(pdata,8,dfree);
    2233        1214 :                         SIVAL(pdata,16,sectors_per_unit);
    2234        1214 :                         SIVAL(pdata,20,bytes_per_sector);
    2235        1214 :                         *fixed_portion = 24;
    2236        1214 :                         break;
    2237             :                 }
    2238             : 
    2239         432 :                 case SMB_FS_FULL_SIZE_INFORMATION:
    2240             :                 {
    2241           0 :                         uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
    2242         432 :                         data_len = 32;
    2243         432 :                         df_ret = get_dfree_info(conn, &smb_fname, &bsize,
    2244             :                                                 &dfree, &dsize);
    2245         432 :                         if (df_ret == (uint64_t)-1) {
    2246           0 :                                 return map_nt_error_from_unix(errno);
    2247             :                         }
    2248         432 :                         block_size = lp_block_size(snum);
    2249         432 :                         if (bsize < block_size) {
    2250         428 :                                 uint64_t factor = block_size/bsize;
    2251         428 :                                 bsize = block_size;
    2252         428 :                                 dsize /= factor;
    2253         428 :                                 dfree /= factor;
    2254             :                         }
    2255         432 :                         if (bsize > block_size) {
    2256           4 :                                 uint64_t factor = bsize/block_size;
    2257           4 :                                 bsize = block_size;
    2258           4 :                                 dsize *= factor;
    2259           4 :                                 dfree *= factor;
    2260             :                         }
    2261         432 :                         sectors_per_unit = bsize/bytes_per_sector;
    2262         432 :                         DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
    2263             : cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
    2264             :                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
    2265         432 :                         SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
    2266         432 :                         SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
    2267         432 :                         SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
    2268         432 :                         SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
    2269         432 :                         SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
    2270         432 :                         *fixed_portion = 32;
    2271         432 :                         break;
    2272             :                 }
    2273             : 
    2274          44 :                 case SMB_QUERY_FS_DEVICE_INFO:
    2275             :                 case SMB_FS_DEVICE_INFORMATION:
    2276             :                 {
    2277          44 :                         uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
    2278             : 
    2279          44 :                         if (!CAN_WRITE(conn)) {
    2280           0 :                                 characteristics |= FILE_READ_ONLY_DEVICE;
    2281             :                         }
    2282          44 :                         data_len = 8;
    2283          44 :                         SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
    2284          44 :                         SIVAL(pdata,4,characteristics);
    2285          44 :                         *fixed_portion = 8;
    2286          44 :                         break;
    2287             :                 }
    2288             : 
    2289             : #ifdef HAVE_SYS_QUOTAS
    2290           4 :                 case SMB_FS_QUOTA_INFORMATION:
    2291             :                 /*
    2292             :                  * what we have to send --metze:
    2293             :                  *
    2294             :                  * Unknown1:            24 NULL bytes
    2295             :                  * Soft Quota Threshold: 8 bytes seems like uint64_t or so
    2296             :                  * Hard Quota Limit:    8 bytes seems like uint64_t or so
    2297             :                  * Quota Flags:         2 byte :
    2298             :                  * Unknown3:            6 NULL bytes
    2299             :                  *
    2300             :                  * 48 bytes total
    2301             :                  *
    2302             :                  * details for Quota Flags:
    2303             :                  *
    2304             :                  * 0x0020 Log Limit: log if the user exceeds his Hard Quota
    2305             :                  * 0x0010 Log Warn:  log if the user exceeds his Soft Quota
    2306             :                  * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
    2307             :                  * 0x0001 Enable Quotas: enable quota for this fs
    2308             :                  *
    2309             :                  */
    2310             :                 {
    2311             :                         /* we need to fake up a fsp here,
    2312             :                          * because its not send in this call
    2313             :                          */
    2314           0 :                         files_struct fsp;
    2315           0 :                         SMB_NTQUOTA_STRUCT quotas;
    2316             : 
    2317           4 :                         ZERO_STRUCT(fsp);
    2318           4 :                         ZERO_STRUCT(quotas);
    2319             : 
    2320           4 :                         fsp.conn = conn;
    2321           4 :                         fsp.fnum = FNUM_FIELD_INVALID;
    2322             : 
    2323             :                         /* access check */
    2324           4 :                         if (get_current_uid(conn) != 0) {
    2325           4 :                                 DEBUG(0,("get_user_quota: access_denied "
    2326             :                                          "service [%s] user [%s]\n",
    2327             :                                          lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
    2328             :                                          conn->session_info->unix_info->unix_name));
    2329           4 :                                 return NT_STATUS_ACCESS_DENIED;
    2330             :                         }
    2331             : 
    2332           0 :                         status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
    2333             :                                                  NULL, &quotas);
    2334           0 :                         if (!NT_STATUS_IS_OK(status)) {
    2335           0 :                                 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
    2336           0 :                                 return status;
    2337             :                         }
    2338             : 
    2339           0 :                         data_len = 48;
    2340             : 
    2341           0 :                         DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
    2342             :                                   lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
    2343             : 
    2344             :                         /* Unknown1 24 NULL bytes*/
    2345           0 :                         SBIG_UINT(pdata,0,(uint64_t)0);
    2346           0 :                         SBIG_UINT(pdata,8,(uint64_t)0);
    2347           0 :                         SBIG_UINT(pdata,16,(uint64_t)0);
    2348             : 
    2349             :                         /* Default Soft Quota 8 bytes */
    2350           0 :                         SBIG_UINT(pdata,24,quotas.softlim);
    2351             : 
    2352             :                         /* Default Hard Quota 8 bytes */
    2353           0 :                         SBIG_UINT(pdata,32,quotas.hardlim);
    2354             : 
    2355             :                         /* Quota flag 2 bytes */
    2356           0 :                         SSVAL(pdata,40,quotas.qflags);
    2357             : 
    2358             :                         /* Unknown3 6 NULL bytes */
    2359           0 :                         SSVAL(pdata,42,0);
    2360           0 :                         SIVAL(pdata,44,0);
    2361             : 
    2362           0 :                         break;
    2363             :                 }
    2364             : #endif /* HAVE_SYS_QUOTAS */
    2365          40 :                 case SMB_FS_OBJECTID_INFORMATION:
    2366             :                 {
    2367           0 :                         unsigned char objid[16];
    2368           0 :                         struct smb_extended_info extended_info;
    2369          40 :                         memcpy(pdata,create_volume_objectid(conn, objid),16);
    2370          40 :                         samba_extended_info_version (&extended_info);
    2371          40 :                         SIVAL(pdata,16,extended_info.samba_magic);
    2372          40 :                         SIVAL(pdata,20,extended_info.samba_version);
    2373          40 :                         SIVAL(pdata,24,extended_info.samba_subversion);
    2374          40 :                         SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
    2375          40 :                         memcpy(pdata+36,extended_info.samba_version_string,28);
    2376          40 :                         data_len = 64;
    2377          40 :                         break;
    2378             :                 }
    2379             : 
    2380           8 :                 case SMB_FS_SECTOR_SIZE_INFORMATION:
    2381             :                 {
    2382           8 :                         data_len = 28;
    2383             :                         /*
    2384             :                          * These values match a physical Windows Server 2012
    2385             :                          * share backed by NTFS atop spinning rust.
    2386             :                          */
    2387           8 :                         DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
    2388             :                         /* logical_bytes_per_sector */
    2389           8 :                         SIVAL(pdata, 0, bytes_per_sector);
    2390             :                         /* phys_bytes_per_sector_atomic */
    2391           8 :                         SIVAL(pdata, 4, bytes_per_sector);
    2392             :                         /* phys_bytes_per_sector_perf */
    2393           8 :                         SIVAL(pdata, 8, bytes_per_sector);
    2394             :                         /* fs_effective_phys_bytes_per_sector_atomic */
    2395           8 :                         SIVAL(pdata, 12, bytes_per_sector);
    2396             :                         /* flags */
    2397           8 :                         SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
    2398             :                                 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
    2399             :                         /* byte_off_sector_align */
    2400           8 :                         SIVAL(pdata, 20, 0);
    2401             :                         /* byte_off_partition_align */
    2402           8 :                         SIVAL(pdata, 24, 0);
    2403           8 :                         *fixed_portion = 28;
    2404           8 :                         break;
    2405             :                 }
    2406             : 
    2407             : 
    2408             : #if defined(WITH_SMB1SERVER)
    2409             :                 /*
    2410             :                  * Query the version and capabilities of the CIFS UNIX extensions
    2411             :                  * in use.
    2412             :                  */
    2413             : 
    2414         962 :                 case SMB_QUERY_CIFS_UNIX_INFO:
    2415             :                 {
    2416         962 :                         bool large_write = lp_min_receive_file_size() &&
    2417           0 :                                         !smb1_srv_is_signing_active(xconn);
    2418         962 :                         bool large_read = !smb1_srv_is_signing_active(xconn);
    2419         962 :                         int encrypt_caps = 0;
    2420             : 
    2421         962 :                         if (!lp_smb1_unix_extensions()) {
    2422           0 :                                 return NT_STATUS_INVALID_LEVEL;
    2423             :                         }
    2424             : 
    2425         962 :                         switch (conn->encrypt_level) {
    2426           0 :                         case SMB_SIGNING_OFF:
    2427           0 :                                 encrypt_caps = 0;
    2428           0 :                                 break;
    2429         797 :                         case SMB_SIGNING_DESIRED:
    2430             :                         case SMB_SIGNING_IF_REQUIRED:
    2431             :                         case SMB_SIGNING_DEFAULT:
    2432         797 :                                 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
    2433         797 :                                 break;
    2434         165 :                         case SMB_SIGNING_REQUIRED:
    2435         165 :                                 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
    2436             :                                                 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
    2437         165 :                                 large_write = false;
    2438         165 :                                 large_read = false;
    2439         165 :                                 break;
    2440             :                         }
    2441             : 
    2442         962 :                         data_len = 12;
    2443         962 :                         SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
    2444         962 :                         SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
    2445             : 
    2446             :                         /* We have POSIX ACLs, pathname, encryption,
    2447             :                          * large read/write, and locking capability. */
    2448             : 
    2449         962 :                         SBIG_UINT(pdata,4,((uint64_t)(
    2450             :                                         CIFS_UNIX_POSIX_ACLS_CAP|
    2451             :                                         CIFS_UNIX_POSIX_PATHNAMES_CAP|
    2452             :                                         CIFS_UNIX_FCNTL_LOCKS_CAP|
    2453             :                                         CIFS_UNIX_EXTATTR_CAP|
    2454             :                                         CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
    2455             :                                         encrypt_caps|
    2456             :                                         (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
    2457             :                                         (large_write ?
    2458             :                                         CIFS_UNIX_LARGE_WRITE_CAP : 0))));
    2459         962 :                         break;
    2460             :                 }
    2461             : #endif
    2462             : 
    2463           0 :                 case SMB_QUERY_POSIX_FS_INFO:
    2464             :                 case SMB2_FS_POSIX_INFORMATION_INTERNAL:
    2465             :                 {
    2466           0 :                         int rc;
    2467           0 :                         struct vfs_statvfs_struct svfs;
    2468             : 
    2469           0 :                         if (!fsinfo_unix_valid_level(conn, info_level)) {
    2470           0 :                                 return NT_STATUS_INVALID_LEVEL;
    2471             :                         }
    2472             : 
    2473           0 :                         rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
    2474             : 
    2475           0 :                         if (!rc) {
    2476           0 :                                 data_len = 56;
    2477           0 :                                 SIVAL(pdata,0,svfs.OptimalTransferSize);
    2478           0 :                                 SIVAL(pdata,4,svfs.BlockSize);
    2479           0 :                                 SBIG_UINT(pdata,8,svfs.TotalBlocks);
    2480           0 :                                 SBIG_UINT(pdata,16,svfs.BlocksAvail);
    2481           0 :                                 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
    2482           0 :                                 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
    2483           0 :                                 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
    2484           0 :                                 SBIG_UINT(pdata,48,svfs.FsIdentifier);
    2485           0 :                                 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO successful\n"));
    2486             : #ifdef EOPNOTSUPP
    2487           0 :                         } else if (rc == EOPNOTSUPP) {
    2488           0 :                                 return NT_STATUS_INVALID_LEVEL;
    2489             : #endif /* EOPNOTSUPP */
    2490             :                         } else {
    2491           0 :                                 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
    2492           0 :                                 return NT_STATUS_DOS(ERRSRV, ERRerror);
    2493             :                         }
    2494           0 :                         break;
    2495             :                 }
    2496             : 
    2497          42 :                 case SMB_QUERY_POSIX_WHOAMI:
    2498             :                 {
    2499          42 :                         uint32_t flags = 0;
    2500           0 :                         uint32_t sid_bytes;
    2501           0 :                         uint32_t i;
    2502             : 
    2503          42 :                         if (!lp_smb1_unix_extensions()) {
    2504           0 :                                 return NT_STATUS_INVALID_LEVEL;
    2505             :                         }
    2506             : 
    2507          42 :                         if (max_data_bytes < 40) {
    2508           0 :                                 return NT_STATUS_BUFFER_TOO_SMALL;
    2509             :                         }
    2510             : 
    2511          42 :                         if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
    2512           6 :                                 flags |= SMB_WHOAMI_GUEST;
    2513             :                         }
    2514             : 
    2515             :                         /* NOTE: 8 bytes for UID/GID, irrespective of native
    2516             :                          * platform size. This matches
    2517             :                          * SMB_QUERY_FILE_UNIX_BASIC and friends.
    2518             :                          */
    2519          42 :                         data_len = 4 /* flags */
    2520             :                             + 4 /* flag mask */
    2521             :                             + 8 /* uid */
    2522             :                             + 8 /* gid */
    2523             :                             + 4 /* ngroups */
    2524             :                             + 4 /* num_sids */
    2525             :                             + 4 /* SID bytes */
    2526             :                             + 4 /* pad/reserved */
    2527          42 :                             + (conn->session_info->unix_token->ngroups * 8)
    2528             :                                 /* groups list */
    2529          42 :                             + (conn->session_info->security_token->num_sids *
    2530             :                                     SID_MAX_SIZE)
    2531             :                                 /* SID list */;
    2532             : 
    2533          42 :                         SIVAL(pdata, 0, flags);
    2534          42 :                         SIVAL(pdata, 4, SMB_WHOAMI_MASK);
    2535          42 :                         SBIG_UINT(pdata, 8,
    2536             :                                   (uint64_t)conn->session_info->unix_token->uid);
    2537          42 :                         SBIG_UINT(pdata, 16,
    2538             :                                   (uint64_t)conn->session_info->unix_token->gid);
    2539             : 
    2540             : 
    2541          42 :                         if (data_len >= max_data_bytes) {
    2542             :                                 /* Potential overflow, skip the GIDs and SIDs. */
    2543             : 
    2544          14 :                                 SIVAL(pdata, 24, 0); /* num_groups */
    2545          14 :                                 SIVAL(pdata, 28, 0); /* num_sids */
    2546          14 :                                 SIVAL(pdata, 32, 0); /* num_sid_bytes */
    2547          14 :                                 SIVAL(pdata, 36, 0); /* reserved */
    2548             : 
    2549          14 :                                 data_len = 40;
    2550          14 :                                 break;
    2551             :                         }
    2552             : 
    2553          28 :                         SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
    2554          28 :                         SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
    2555             : 
    2556             :                         /* We walk the SID list twice, but this call is fairly
    2557             :                          * infrequent, and I don't expect that it's performance
    2558             :                          * sensitive -- jpeach
    2559             :                          */
    2560          28 :                         for (i = 0, sid_bytes = 0;
    2561         346 :                              i < conn->session_info->security_token->num_sids; ++i) {
    2562         318 :                                 sid_bytes += ndr_size_dom_sid(
    2563         318 :                                         &conn->session_info->security_token->sids[i],
    2564             :                                         0);
    2565             :                         }
    2566             : 
    2567             :                         /* SID list byte count */
    2568          28 :                         SIVAL(pdata, 32, sid_bytes);
    2569             : 
    2570             :                         /* 4 bytes pad/reserved - must be zero */
    2571          28 :                         SIVAL(pdata, 36, 0);
    2572          28 :                         data_len = 40;
    2573             : 
    2574             :                         /* GID list */
    2575         260 :                         for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
    2576         232 :                                 SBIG_UINT(pdata, data_len,
    2577             :                                           (uint64_t)conn->session_info->unix_token->groups[i]);
    2578         232 :                                 data_len += 8;
    2579             :                         }
    2580             : 
    2581             :                         /* SID list */
    2582          28 :                         for (i = 0;
    2583         346 :                             i < conn->session_info->security_token->num_sids; ++i) {
    2584         636 :                                 int sid_len = ndr_size_dom_sid(
    2585         318 :                                         &conn->session_info->security_token->sids[i],
    2586             :                                         0);
    2587             : 
    2588         318 :                                 sid_linearize((uint8_t *)(pdata + data_len),
    2589             :                                               sid_len,
    2590         318 :                                     &conn->session_info->security_token->sids[i]);
    2591         318 :                                 data_len += sid_len;
    2592             :                         }
    2593             : 
    2594          28 :                         break;
    2595             :                 }
    2596             : 
    2597           0 :                 case SMB_MAC_QUERY_FS_INFO:
    2598             :                         /*
    2599             :                          * Thursby MAC extension... ONLY on NTFS filesystems
    2600             :                          * once we do streams then we don't need this
    2601             :                          */
    2602           0 :                         if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
    2603           0 :                                 data_len = 88;
    2604           0 :                                 SIVAL(pdata,84,0x100); /* Don't support mac... */
    2605           0 :                                 break;
    2606             :                         }
    2607             : 
    2608           0 :                         FALL_THROUGH;
    2609             :                 default:
    2610           0 :                         return NT_STATUS_INVALID_LEVEL;
    2611             :         }
    2612             : 
    2613        3420 :         *ret_data_len = data_len;
    2614        3420 :         return status;
    2615             : }
    2616             : 
    2617           0 : NTSTATUS smb_set_fsquota(connection_struct *conn,
    2618             :                          struct smb_request *req,
    2619             :                          files_struct *fsp,
    2620             :                          const DATA_BLOB *qdata)
    2621             : {
    2622           0 :         const struct loadparm_substitution *lp_sub =
    2623           0 :                 loadparm_s3_global_substitution();
    2624           0 :         NTSTATUS status;
    2625           0 :         SMB_NTQUOTA_STRUCT quotas;
    2626             : 
    2627           0 :         ZERO_STRUCT(quotas);
    2628             : 
    2629             :         /* access check */
    2630           0 :         if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
    2631           0 :                 DBG_NOTICE("access_denied service [%s] user [%s]\n",
    2632             :                            lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
    2633             :                            conn->session_info->unix_info->unix_name);
    2634           0 :                 return NT_STATUS_ACCESS_DENIED;
    2635             :         }
    2636             : 
    2637           0 :         if (!check_fsp_ntquota_handle(conn, req,
    2638             :                                       fsp)) {
    2639           0 :                 DBG_WARNING("no valid QUOTA HANDLE\n");
    2640           0 :                 return NT_STATUS_INVALID_HANDLE;
    2641             :         }
    2642             : 
    2643             :         /* note: normally there're 48 bytes,
    2644             :          * but we didn't use the last 6 bytes for now
    2645             :          * --metze
    2646             :          */
    2647           0 :         if (qdata->length < 42) {
    2648           0 :                 DBG_ERR("requires total_data(%zu) >= 42 bytes!\n",
    2649             :                         qdata->length);
    2650           0 :                 return NT_STATUS_INVALID_PARAMETER;
    2651             :         }
    2652             : 
    2653             :         /* unknown_1 24 NULL bytes in pdata*/
    2654             : 
    2655             :         /* the soft quotas 8 bytes (uint64_t)*/
    2656           0 :         quotas.softlim = BVAL(qdata->data,24);
    2657             : 
    2658             :         /* the hard quotas 8 bytes (uint64_t)*/
    2659           0 :         quotas.hardlim = BVAL(qdata->data,32);
    2660             : 
    2661             :         /* quota_flags 2 bytes **/
    2662           0 :         quotas.qflags = SVAL(qdata->data,40);
    2663             : 
    2664             :         /* unknown_2 6 NULL bytes follow*/
    2665             : 
    2666             :         /* now set the quotas */
    2667           0 :         if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
    2668           0 :                 DBG_WARNING("vfs_set_ntquota() failed for service [%s]\n",
    2669             :                             lp_servicename(talloc_tos(), lp_sub, SNUM(conn)));
    2670           0 :                 status =  map_nt_error_from_unix(errno);
    2671             :         } else {
    2672           0 :                 status = NT_STATUS_OK;
    2673             :         }
    2674           0 :         return status;
    2675             : }
    2676             : 
    2677           0 : NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
    2678             :                                 struct smb_request *req,
    2679             :                                 TALLOC_CTX *mem_ctx,
    2680             :                                 uint16_t info_level,
    2681             :                                 files_struct *fsp,
    2682             :                                 const DATA_BLOB *pdata)
    2683             : {
    2684           0 :         switch (info_level) {
    2685           0 :                 case SMB_FS_QUOTA_INFORMATION:
    2686             :                 {
    2687           0 :                         return smb_set_fsquota(conn,
    2688             :                                                 req,
    2689             :                                                 fsp,
    2690             :                                                 pdata);
    2691             :                 }
    2692             : 
    2693           0 :                 default:
    2694           0 :                         break;
    2695             :         }
    2696           0 :         return NT_STATUS_INVALID_LEVEL;
    2697             : }
    2698             : 
    2699             : /****************************************************************************
    2700             :  Store the FILE_UNIX_BASIC info.
    2701             : ****************************************************************************/
    2702             : 
    2703         144 : char *store_file_unix_basic(connection_struct *conn,
    2704             :                             char *pdata,
    2705             :                             files_struct *fsp,
    2706             :                             const SMB_STRUCT_STAT *psbuf)
    2707             : {
    2708           0 :         dev_t devno;
    2709             : 
    2710         144 :         DBG_DEBUG("SMB_QUERY_FILE_UNIX_BASIC\n");
    2711         144 :         DBG_NOTICE("st_mode=%o\n", (int)psbuf->st_ex_mode);
    2712             : 
    2713         144 :         SOFF_T(pdata,0,get_file_size_stat(psbuf));             /* File size 64 Bit */
    2714         144 :         pdata += 8;
    2715             : 
    2716         144 :         SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
    2717         144 :         pdata += 8;
    2718             : 
    2719         144 :         put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, &psbuf->st_ex_ctime);       /* Change Time 64 Bit */
    2720         144 :         put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, &psbuf->st_ex_atime);     /* Last access time 64 Bit */
    2721         144 :         put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, &psbuf->st_ex_mtime);    /* Last modification time 64 Bit */
    2722         144 :         pdata += 24;
    2723             : 
    2724         144 :         SIVAL(pdata,0,psbuf->st_ex_uid);               /* user id for the owner */
    2725         144 :         SIVAL(pdata,4,0);
    2726         144 :         pdata += 8;
    2727             : 
    2728         144 :         SIVAL(pdata,0,psbuf->st_ex_gid);               /* group id of owner */
    2729         144 :         SIVAL(pdata,4,0);
    2730         144 :         pdata += 8;
    2731             : 
    2732         144 :         SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
    2733         144 :         pdata += 4;
    2734             : 
    2735         144 :         if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
    2736           0 :                 devno = psbuf->st_ex_rdev;
    2737             :         } else {
    2738         144 :                 devno = psbuf->st_ex_dev;
    2739             :         }
    2740             : 
    2741         144 :         SIVAL(pdata,0,unix_dev_major(devno));   /* Major device number if type is device */
    2742         144 :         SIVAL(pdata,4,0);
    2743         144 :         pdata += 8;
    2744             : 
    2745         144 :         SIVAL(pdata,0,unix_dev_minor(devno));   /* Minor device number if type is device */
    2746         144 :         SIVAL(pdata,4,0);
    2747         144 :         pdata += 8;
    2748             : 
    2749         144 :         SINO_T_VAL(pdata, 0, psbuf->st_ex_ino);   /* inode number */
    2750         144 :         pdata += 8;
    2751             : 
    2752         144 :         SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode));     /* Standard UNIX file permissions */
    2753         144 :         SIVAL(pdata,4,0);
    2754         144 :         pdata += 8;
    2755             : 
    2756         144 :         SIVAL(pdata,0,psbuf->st_ex_nlink);             /* number of hard links */
    2757         144 :         SIVAL(pdata,4,0);
    2758         144 :         pdata += 8;
    2759             : 
    2760         144 :         return pdata;
    2761             : }
    2762             : 
    2763             : /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
    2764             :  * the chflags(2) (or equivalent) flags.
    2765             :  *
    2766             :  * XXX: this really should be behind the VFS interface. To do this, we would
    2767             :  * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
    2768             :  * Each VFS module could then implement its own mapping as appropriate for the
    2769             :  * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
    2770             :  */
    2771             : static const struct {unsigned stat_fflag; unsigned smb_fflag;}
    2772             :         info2_flags_map[] =
    2773             : {
    2774             : #ifdef UF_NODUMP
    2775             :     { UF_NODUMP, EXT_DO_NOT_BACKUP },
    2776             : #endif
    2777             : 
    2778             : #ifdef UF_IMMUTABLE
    2779             :     { UF_IMMUTABLE, EXT_IMMUTABLE },
    2780             : #endif
    2781             : 
    2782             : #ifdef UF_APPEND
    2783             :     { UF_APPEND, EXT_OPEN_APPEND_ONLY },
    2784             : #endif
    2785             : 
    2786             : #ifdef UF_HIDDEN
    2787             :     { UF_HIDDEN, EXT_HIDDEN },
    2788             : #endif
    2789             : 
    2790             :     /* Do not remove. We need to guarantee that this array has at least one
    2791             :      * entry to build on HP-UX.
    2792             :      */
    2793             :     { 0, 0 }
    2794             : 
    2795             : };
    2796             : 
    2797          24 : static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
    2798             :                                 uint32_t *smb_fflags, uint32_t *smb_fmask)
    2799             : {
    2800             :         size_t i;
    2801             : 
    2802          48 :         for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
    2803          24 :             *smb_fmask |= info2_flags_map[i].smb_fflag;
    2804          24 :             if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
    2805           0 :                     *smb_fflags |= info2_flags_map[i].smb_fflag;
    2806             :             }
    2807             :         }
    2808          24 : }
    2809             : 
    2810         128 : bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
    2811             :                              const uint32_t smb_fflags,
    2812             :                              const uint32_t smb_fmask,
    2813             :                              int *stat_fflags)
    2814             : {
    2815         128 :         uint32_t max_fmask = 0;
    2816           0 :         size_t i;
    2817             : 
    2818         128 :         *stat_fflags = psbuf->st_ex_flags;
    2819             : 
    2820             :         /* For each flags requested in smb_fmask, check the state of the
    2821             :          * corresponding flag in smb_fflags and set or clear the matching
    2822             :          * stat flag.
    2823             :          */
    2824             : 
    2825         256 :         for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
    2826         128 :             max_fmask |= info2_flags_map[i].smb_fflag;
    2827         128 :             if (smb_fmask & info2_flags_map[i].smb_fflag) {
    2828           0 :                     if (smb_fflags & info2_flags_map[i].smb_fflag) {
    2829           0 :                             *stat_fflags |= info2_flags_map[i].stat_fflag;
    2830             :                     } else {
    2831           0 :                             *stat_fflags &= ~info2_flags_map[i].stat_fflag;
    2832             :                     }
    2833             :             }
    2834             :         }
    2835             : 
    2836             :         /* If smb_fmask is asking to set any bits that are not supported by
    2837             :          * our flag mappings, we should fail.
    2838             :          */
    2839         128 :         if ((smb_fmask & max_fmask) != smb_fmask) {
    2840         128 :                 return False;
    2841             :         }
    2842             : 
    2843           0 :         return True;
    2844             : }
    2845             : 
    2846             : 
    2847             : /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
    2848             :  * of file flags and birth (create) time.
    2849             :  */
    2850          24 : char *store_file_unix_basic_info2(connection_struct *conn,
    2851             :                                   char *pdata,
    2852             :                                   files_struct *fsp,
    2853             :                                   const SMB_STRUCT_STAT *psbuf)
    2854             : {
    2855          24 :         uint32_t file_flags = 0;
    2856          24 :         uint32_t flags_mask = 0;
    2857             : 
    2858          24 :         pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
    2859             : 
    2860             :         /* Create (birth) time 64 bit */
    2861          24 :         put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, &psbuf->st_ex_btime);
    2862          24 :         pdata += 8;
    2863             : 
    2864          24 :         map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
    2865          24 :         SIVAL(pdata, 0, file_flags); /* flags */
    2866          24 :         SIVAL(pdata, 4, flags_mask); /* mask */
    2867          24 :         pdata += 8;
    2868             : 
    2869          24 :         return pdata;
    2870             : }
    2871             : 
    2872        3598 : static NTSTATUS marshall_stream_info(unsigned int num_streams,
    2873             :                                      const struct stream_struct *streams,
    2874             :                                      char *data,
    2875             :                                      unsigned int max_data_bytes,
    2876             :                                      unsigned int *data_size)
    2877             : {
    2878           0 :         unsigned int i;
    2879        3598 :         unsigned int ofs = 0;
    2880             : 
    2881        3598 :         if (max_data_bytes < 32) {
    2882         128 :                 return NT_STATUS_INFO_LENGTH_MISMATCH;
    2883             :         }
    2884             : 
    2885        7478 :         for (i = 0; i < num_streams; i++) {
    2886           0 :                 unsigned int next_offset;
    2887           0 :                 size_t namelen;
    2888           0 :                 smb_ucs2_t *namebuf;
    2889             : 
    2890        4032 :                 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
    2891        4032 :                                       streams[i].name, &namelen) ||
    2892        4032 :                     namelen <= 2)
    2893             :                 {
    2894           0 :                         return NT_STATUS_INVALID_PARAMETER;
    2895             :                 }
    2896             : 
    2897             :                 /*
    2898             :                  * name_buf is now null-terminated, we need to marshall as not
    2899             :                  * terminated
    2900             :                  */
    2901             : 
    2902        4032 :                 namelen -= 2;
    2903             : 
    2904             :                 /*
    2905             :                  * We cannot overflow ...
    2906             :                  */
    2907        4032 :                 if ((ofs + 24 + namelen) > max_data_bytes) {
    2908          24 :                         DEBUG(10, ("refusing to overflow reply at stream %u\n",
    2909             :                                 i));
    2910          24 :                         TALLOC_FREE(namebuf);
    2911          24 :                         return STATUS_BUFFER_OVERFLOW;
    2912             :                 }
    2913             : 
    2914        4008 :                 SIVAL(data, ofs+4, namelen);
    2915        4008 :                 SOFF_T(data, ofs+8, streams[i].size);
    2916        4008 :                 SOFF_T(data, ofs+16, streams[i].alloc_size);
    2917        4008 :                 memcpy(data+ofs+24, namebuf, namelen);
    2918        4008 :                 TALLOC_FREE(namebuf);
    2919             : 
    2920        4008 :                 next_offset = ofs + 24 + namelen;
    2921             : 
    2922        4008 :                 if (i == num_streams-1) {
    2923        3210 :                         SIVAL(data, ofs, 0);
    2924             :                 }
    2925             :                 else {
    2926         798 :                         unsigned int align = ndr_align_size(next_offset, 8);
    2927             : 
    2928         798 :                         if ((next_offset + align) > max_data_bytes) {
    2929           0 :                                 DEBUG(10, ("refusing to overflow align "
    2930             :                                         "reply at stream %u\n",
    2931             :                                         i));
    2932           0 :                                 TALLOC_FREE(namebuf);
    2933           0 :                                 return STATUS_BUFFER_OVERFLOW;
    2934             :                         }
    2935             : 
    2936         798 :                         memset(data+next_offset, 0, align);
    2937         798 :                         next_offset += align;
    2938             : 
    2939         798 :                         SIVAL(data, ofs, next_offset - ofs);
    2940         798 :                         ofs = next_offset;
    2941             :                 }
    2942             : 
    2943        4008 :                 ofs = next_offset;
    2944             :         }
    2945             : 
    2946        3446 :         DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
    2947             : 
    2948        3446 :         *data_size = ofs;
    2949             : 
    2950        3446 :         return NT_STATUS_OK;
    2951             : }
    2952             : 
    2953       24435 : NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
    2954             :                                TALLOC_CTX *mem_ctx,
    2955             :                                struct smb_request *req,
    2956             :                                uint16_t info_level,
    2957             :                                files_struct *fsp,
    2958             :                                struct smb_filename *smb_fname,
    2959             :                                bool delete_pending,
    2960             :                                struct timespec write_time_ts,
    2961             :                                struct ea_list *ea_list,
    2962             :                                uint16_t flags2,
    2963             :                                unsigned int max_data_bytes,
    2964             :                                size_t *fixed_portion,
    2965             :                                char **ppdata,
    2966             :                                unsigned int *pdata_size)
    2967             : {
    2968       24435 :         char *pdata = *ppdata;
    2969         743 :         char *dstart, *dend;
    2970         743 :         unsigned int data_size;
    2971         743 :         struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
    2972         743 :         time_t create_time, mtime, atime, c_time;
    2973       24435 :         SMB_STRUCT_STAT *psbuf = NULL;
    2974       24435 :         SMB_STRUCT_STAT *base_sp = NULL;
    2975         743 :         char *p;
    2976         743 :         char *base_name;
    2977         743 :         char *dos_fname;
    2978         743 :         int mode;
    2979         743 :         int nlink;
    2980         743 :         NTSTATUS status;
    2981       24435 :         uint64_t file_size = 0;
    2982       24435 :         uint64_t pos = 0;
    2983       24435 :         uint64_t allocation_size = 0;
    2984       24435 :         uint64_t file_id = 0;
    2985       24435 :         uint32_t access_mask = 0;
    2986       24435 :         size_t len = 0;
    2987             : 
    2988       24435 :         if (INFO_LEVEL_IS_UNIX(info_level)) {
    2989           8 :                 bool ok = false;
    2990             : 
    2991           8 :                 if (lp_smb1_unix_extensions() && req->posix_pathnames) {
    2992           8 :                         DBG_DEBUG("SMB1 unix extensions activated\n");
    2993           8 :                         ok = true;
    2994             :                 }
    2995             : 
    2996           8 :                 if ((fsp != NULL) &&
    2997           8 :                     (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN)) {
    2998           0 :                         DBG_DEBUG("SMB2 posix open\n");
    2999           0 :                         ok = true;
    3000             :                 }
    3001             : 
    3002           8 :                 if (!ok) {
    3003           0 :                         return NT_STATUS_INVALID_LEVEL;
    3004             :                 }
    3005             :         }
    3006             : 
    3007       24435 :         DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
    3008             :                  smb_fname_str_dbg(smb_fname),
    3009             :                  fsp_fnum_dbg(fsp),
    3010             :                  info_level, max_data_bytes));
    3011             : 
    3012             :         /*
    3013             :          * In case of querying a symlink in POSIX context,
    3014             :          * fsp will be NULL. fdos_mode() deals with it.
    3015             :          */
    3016       24435 :         if (fsp != NULL) {
    3017       24435 :                 smb_fname = fsp->fsp_name;
    3018             :         }
    3019       24435 :         mode = fdos_mode(fsp);
    3020       24435 :         psbuf = &smb_fname->st;
    3021             : 
    3022       24435 :         if (fsp != NULL) {
    3023       24435 :                 base_sp = fsp->base_fsp ?
    3024       24435 :                         &fsp->base_fsp->fsp_name->st :
    3025       23867 :                         &fsp->fsp_name->st;
    3026             :         } else {
    3027           0 :                 base_sp = &smb_fname->st;
    3028             :         }
    3029             : 
    3030       24435 :         nlink = psbuf->st_ex_nlink;
    3031             : 
    3032       24435 :         if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
    3033        2724 :                 nlink = 1;
    3034             :         }
    3035             : 
    3036       24435 :         if ((nlink > 0) && delete_pending) {
    3037         233 :                 nlink -= 1;
    3038             :         }
    3039             : 
    3040       24435 :         if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
    3041           0 :                 return NT_STATUS_INVALID_PARAMETER;
    3042             :         }
    3043             : 
    3044       24435 :         data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
    3045       24435 :         *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
    3046       24435 :         if (*ppdata == NULL) {
    3047           0 :                 return NT_STATUS_NO_MEMORY;
    3048             :         }
    3049       24435 :         pdata = *ppdata;
    3050       24435 :         dstart = pdata;
    3051       24435 :         dend = dstart + data_size - 1;
    3052             : 
    3053       24435 :         if (!is_omit_timespec(&write_time_ts) &&
    3054       16858 :             !INFO_LEVEL_IS_UNIX(info_level))
    3055             :         {
    3056       16858 :                 update_stat_ex_mtime(psbuf, write_time_ts);
    3057             :         }
    3058             : 
    3059       24435 :         create_time_ts = get_create_timespec(conn, fsp, smb_fname);
    3060       24435 :         mtime_ts = psbuf->st_ex_mtime;
    3061       24435 :         atime_ts = psbuf->st_ex_atime;
    3062       24435 :         ctime_ts = get_change_timespec(conn, fsp, smb_fname);
    3063             : 
    3064       24435 :         if (lp_dos_filetime_resolution(SNUM(conn))) {
    3065           0 :                 dos_filetime_timespec(&create_time_ts);
    3066           0 :                 dos_filetime_timespec(&mtime_ts);
    3067           0 :                 dos_filetime_timespec(&atime_ts);
    3068           0 :                 dos_filetime_timespec(&ctime_ts);
    3069             :         }
    3070             : 
    3071       24435 :         create_time = convert_timespec_to_time_t(create_time_ts);
    3072       24435 :         mtime = convert_timespec_to_time_t(mtime_ts);
    3073       24435 :         atime = convert_timespec_to_time_t(atime_ts);
    3074       24435 :         c_time = convert_timespec_to_time_t(ctime_ts);
    3075             : 
    3076       24435 :         p = strrchr_m(smb_fname->base_name,'/');
    3077       24435 :         if (!p)
    3078       12748 :                 base_name = smb_fname->base_name;
    3079             :         else
    3080       11687 :                 base_name = p+1;
    3081             : 
    3082             :         /* NT expects the name to be in an exact form of the *full*
    3083             :            filename. See the trans2 torture test */
    3084       24435 :         if (ISDOT(base_name)) {
    3085         390 :                 dos_fname = talloc_strdup(mem_ctx, "\\");
    3086         390 :                 if (!dos_fname) {
    3087           0 :                         return NT_STATUS_NO_MEMORY;
    3088             :                 }
    3089             :         } else {
    3090       24045 :                 dos_fname = talloc_asprintf(mem_ctx,
    3091             :                                 "\\%s",
    3092             :                                 smb_fname->base_name);
    3093       24045 :                 if (!dos_fname) {
    3094           0 :                         return NT_STATUS_NO_MEMORY;
    3095             :                 }
    3096       24045 :                 if (is_named_stream(smb_fname)) {
    3097         568 :                         dos_fname = talloc_asprintf(dos_fname, "%s",
    3098             :                                                     smb_fname->stream_name);
    3099         568 :                         if (!dos_fname) {
    3100           0 :                                 return NT_STATUS_NO_MEMORY;
    3101             :                         }
    3102             :                 }
    3103             : 
    3104       24045 :                 string_replace(dos_fname, '/', '\\');
    3105             :         }
    3106             : 
    3107       24435 :         allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
    3108             : 
    3109       24435 :         if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
    3110             :                 /* Do we have this path open ? */
    3111        7712 :                 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
    3112        7712 :                 files_struct *fsp1 = file_find_di_first(
    3113             :                         conn->sconn, fileid, true);
    3114        7712 :                 if (fsp1 && fsp1->initial_allocation_size) {
    3115         105 :                         allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
    3116             :                 }
    3117             :         }
    3118             : 
    3119       24435 :         if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
    3120       21711 :                 file_size = get_file_size_stat(psbuf);
    3121             :         }
    3122             : 
    3123       24435 :         if (fsp) {
    3124       24435 :                 pos = fh_get_position_information(fsp->fh);
    3125             :         }
    3126             : 
    3127       24435 :         if (fsp) {
    3128       24435 :                 access_mask = fsp->access_mask;
    3129             :         } else {
    3130             :                 /* GENERIC_EXECUTE mapping from Windows */
    3131           0 :                 access_mask = 0x12019F;
    3132             :         }
    3133             : 
    3134             :         /* This should be an index number - looks like
    3135             :            dev/ino to me :-)
    3136             : 
    3137             :            I think this causes us to fail the IFSKIT
    3138             :            BasicFileInformationTest. -tpot */
    3139       24435 :         file_id = SMB_VFS_FS_FILE_ID(conn, base_sp);
    3140             : 
    3141       24435 :         *fixed_portion = 0;
    3142             : 
    3143       24435 :         switch (info_level) {
    3144         411 :                 case SMB_INFO_STANDARD:
    3145         411 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
    3146         411 :                         data_size = 22;
    3147         411 :                         srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
    3148         411 :                         srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
    3149         411 :                         srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
    3150         411 :                         SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
    3151         411 :                         SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
    3152         411 :                         SSVAL(pdata,l1_attrFile,mode);
    3153         411 :                         break;
    3154             : 
    3155           8 :                 case SMB_INFO_QUERY_EA_SIZE:
    3156             :                 {
    3157           0 :                         unsigned int ea_size =
    3158           8 :                             estimate_ea_size(smb_fname->fsp);
    3159           8 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
    3160           8 :                         data_size = 26;
    3161           8 :                         srv_put_dos_date2(pdata,0,create_time);
    3162           8 :                         srv_put_dos_date2(pdata,4,atime);
    3163           8 :                         srv_put_dos_date2(pdata,8,mtime); /* write time */
    3164           8 :                         SIVAL(pdata,12,(uint32_t)file_size);
    3165           8 :                         SIVAL(pdata,16,(uint32_t)allocation_size);
    3166           8 :                         SSVAL(pdata,20,mode);
    3167           8 :                         SIVAL(pdata,22,ea_size);
    3168           8 :                         break;
    3169             :                 }
    3170             : 
    3171           8 :                 case SMB_INFO_IS_NAME_VALID:
    3172           8 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
    3173           8 :                         if (fsp) {
    3174             :                                 /* os/2 needs this ? really ?*/
    3175           8 :                                 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
    3176             :                         }
    3177             :                         /* This is only reached for qpathinfo */
    3178           0 :                         data_size = 0;
    3179           0 :                         break;
    3180             : 
    3181         152 :                 case SMB_INFO_QUERY_EAS_FROM_LIST:
    3182             :                 {
    3183         152 :                         size_t total_ea_len = 0;
    3184         152 :                         struct ea_list *ea_file_list = NULL;
    3185         152 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
    3186             : 
    3187          28 :                         status =
    3188         180 :                             get_ea_list_from_fsp(mem_ctx,
    3189         152 :                                                   smb_fname->fsp,
    3190             :                                                   &total_ea_len, &ea_file_list);
    3191         152 :                         if (!NT_STATUS_IS_OK(status)) {
    3192           4 :                                 return status;
    3193             :                         }
    3194             : 
    3195         148 :                         ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
    3196             : 
    3197         148 :                         if (!ea_list || (total_ea_len > data_size)) {
    3198           0 :                                 data_size = 4;
    3199           0 :                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
    3200         148 :                                 break;
    3201             :                         }
    3202             : 
    3203         148 :                         data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
    3204         148 :                         break;
    3205             :                 }
    3206             : 
    3207          20 :                 case SMB_INFO_QUERY_ALL_EAS:
    3208             :                 {
    3209             :                         /* We have data_size bytes to put EA's into. */
    3210          20 :                         size_t total_ea_len = 0;
    3211          20 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
    3212             : 
    3213          20 :                         status = get_ea_list_from_fsp(mem_ctx,
    3214          20 :                                                         smb_fname->fsp,
    3215             :                                                         &total_ea_len, &ea_list);
    3216          20 :                         if (!NT_STATUS_IS_OK(status)) {
    3217           4 :                                 return status;
    3218             :                         }
    3219             : 
    3220          16 :                         if (!ea_list || (total_ea_len > data_size)) {
    3221          12 :                                 data_size = 4;
    3222          12 :                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
    3223          16 :                                 break;
    3224             :                         }
    3225             : 
    3226           4 :                         data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
    3227           4 :                         break;
    3228             :                 }
    3229             : 
    3230          22 :                 case SMB2_FILE_FULL_EA_INFORMATION:
    3231             :                 {
    3232             :                         /* We have data_size bytes to put EA's into. */
    3233          22 :                         size_t total_ea_len = 0;
    3234          22 :                         struct ea_list *ea_file_list = NULL;
    3235             : 
    3236          22 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
    3237             : 
    3238             :                         /*TODO: add filtering and index handling */
    3239             : 
    3240           0 :                         status  =
    3241          22 :                                 get_ea_list_from_fsp(mem_ctx,
    3242          22 :                                                   smb_fname->fsp,
    3243             :                                                   &total_ea_len, &ea_file_list);
    3244          22 :                         if (!NT_STATUS_IS_OK(status)) {
    3245          12 :                                 return status;
    3246             :                         }
    3247          22 :                         if (!ea_file_list) {
    3248          12 :                                 return NT_STATUS_NO_EAS_ON_FILE;
    3249             :                         }
    3250             : 
    3251          10 :                         status = fill_ea_chained_buffer(mem_ctx,
    3252             :                                                         pdata,
    3253             :                                                         data_size,
    3254             :                                                         &data_size,
    3255             :                                                         conn, ea_file_list);
    3256          10 :                         if (!NT_STATUS_IS_OK(status)) {
    3257           0 :                                 return status;
    3258             :                         }
    3259          10 :                         break;
    3260             :                 }
    3261             : 
    3262        4287 :                 case SMB_FILE_BASIC_INFORMATION:
    3263             :                 case SMB_QUERY_FILE_BASIC_INFO:
    3264             : 
    3265        4287 :                         if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
    3266        3731 :                                 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
    3267        3731 :                                 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
    3268             :                         } else {
    3269         556 :                                 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
    3270         556 :                                 data_size = 40;
    3271         556 :                                 SIVAL(pdata,36,0);
    3272             :                         }
    3273        4287 :                         put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
    3274        4287 :                         put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
    3275        4287 :                         put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
    3276        4287 :                         put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
    3277        4287 :                         SIVAL(pdata,32,mode);
    3278             : 
    3279        4287 :                         DEBUG(5,("SMB_QFBI - "));
    3280        4287 :                         DEBUG(5,("create: %s ", ctime(&create_time)));
    3281        4287 :                         DEBUG(5,("access: %s ", ctime(&atime)));
    3282        4287 :                         DEBUG(5,("write: %s ", ctime(&mtime)));
    3283        4287 :                         DEBUG(5,("change: %s ", ctime(&c_time)));
    3284        4287 :                         DEBUG(5,("mode: %x\n", mode));
    3285        4287 :                         *fixed_portion = data_size;
    3286        4287 :                         break;
    3287             : 
    3288        2659 :                 case SMB_FILE_STANDARD_INFORMATION:
    3289             :                 case SMB_QUERY_FILE_STANDARD_INFO:
    3290             : 
    3291        2659 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
    3292        2659 :                         data_size = 24;
    3293        2659 :                         SOFF_T(pdata,0,allocation_size);
    3294        2659 :                         SOFF_T(pdata,8,file_size);
    3295        2659 :                         SIVAL(pdata,16,nlink);
    3296        2659 :                         SCVAL(pdata,20,delete_pending?1:0);
    3297        2659 :                         SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
    3298        2659 :                         SSVAL(pdata,22,0); /* Padding. */
    3299        2659 :                         *fixed_portion = 24;
    3300        2659 :                         break;
    3301             : 
    3302          40 :                 case SMB_FILE_EA_INFORMATION:
    3303             :                 case SMB_QUERY_FILE_EA_INFO:
    3304             :                 {
    3305           0 :                         unsigned int ea_size =
    3306          40 :                             estimate_ea_size(smb_fname->fsp);
    3307          40 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
    3308          40 :                         data_size = 4;
    3309          40 :                         *fixed_portion = 4;
    3310          40 :                         SIVAL(pdata,0,ea_size);
    3311          40 :                         break;
    3312             :                 }
    3313             : 
    3314             :                 /* Get the 8.3 name - used if NT SMB was negotiated. */
    3315        1730 :                 case SMB_QUERY_FILE_ALT_NAME_INFO:
    3316             :                 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
    3317             :                 {
    3318           0 :                         char mangled_name[13];
    3319        1730 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
    3320        1730 :                         if (!name_to_8_3(base_name,mangled_name,
    3321        1730 :                                                 True,conn->params)) {
    3322           0 :                                 return NT_STATUS_NO_MEMORY;
    3323             :                         }
    3324        1730 :                         status = srvstr_push(dstart, flags2,
    3325             :                                           pdata+4, mangled_name,
    3326             :                                           PTR_DIFF(dend, pdata+4),
    3327             :                                           STR_UNICODE, &len);
    3328        1730 :                         if (!NT_STATUS_IS_OK(status)) {
    3329           0 :                                 return status;
    3330             :                         }
    3331        1730 :                         data_size = 4 + len;
    3332        1730 :                         SIVAL(pdata,0,len);
    3333        1730 :                         *fixed_portion = 8;
    3334        1730 :                         break;
    3335             :                 }
    3336             : 
    3337          79 :                 case SMB_QUERY_FILE_NAME_INFO:
    3338             :                 {
    3339             :                         /*
    3340             :                           this must be *exactly* right for ACLs on mapped drives to work
    3341             :                          */
    3342          79 :                         status = srvstr_push(dstart, flags2,
    3343             :                                           pdata+4, dos_fname,
    3344             :                                           PTR_DIFF(dend, pdata+4),
    3345             :                                           STR_UNICODE, &len);
    3346          79 :                         if (!NT_STATUS_IS_OK(status)) {
    3347           0 :                                 return status;
    3348             :                         }
    3349          79 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
    3350          79 :                         data_size = 4 + len;
    3351          79 :                         SIVAL(pdata,0,len);
    3352          79 :                         break;
    3353             :                 }
    3354             : 
    3355         104 :                 case SMB_FILE_NORMALIZED_NAME_INFORMATION:
    3356             :                 {
    3357         104 :                         char *nfname = NULL;
    3358             : 
    3359         104 :                         if (fsp == NULL || !fsp->conn->sconn->using_smb2) {
    3360           8 :                                 return NT_STATUS_INVALID_LEVEL;
    3361             :                         }
    3362             : 
    3363          96 :                         nfname = talloc_strdup(mem_ctx, smb_fname->base_name);
    3364          96 :                         if (nfname == NULL) {
    3365           0 :                                 return NT_STATUS_NO_MEMORY;
    3366             :                         }
    3367             : 
    3368          96 :                         if (ISDOT(nfname)) {
    3369           4 :                                 nfname[0] = '\0';
    3370             :                         }
    3371          96 :                         string_replace(nfname, '/', '\\');
    3372             : 
    3373          96 :                         if (fsp_is_alternate_stream(fsp)) {
    3374          32 :                                 const char *s = smb_fname->stream_name;
    3375          32 :                                 const char *e = NULL;
    3376           0 :                                 size_t n;
    3377             : 
    3378          32 :                                 SMB_ASSERT(s[0] != '\0');
    3379             : 
    3380             :                                 /*
    3381             :                                  * smb_fname->stream_name is in form
    3382             :                                  * of ':StrEam:$DATA', but we should only
    3383             :                                  * append ':StrEam' here.
    3384             :                                  */
    3385             : 
    3386          32 :                                 e = strchr(&s[1], ':');
    3387          32 :                                 if (e == NULL) {
    3388           8 :                                         n = strlen(s);
    3389             :                                 } else {
    3390          24 :                                         n = PTR_DIFF(e, s);
    3391             :                                 }
    3392          32 :                                 nfname = talloc_strndup_append(nfname, s, n);
    3393          32 :                                 if (nfname == NULL) {
    3394           0 :                                         return NT_STATUS_NO_MEMORY;
    3395             :                                 }
    3396             :                         }
    3397             : 
    3398          96 :                         status = srvstr_push(dstart, flags2,
    3399             :                                           pdata+4, nfname,
    3400             :                                           PTR_DIFF(dend, pdata+4),
    3401             :                                           STR_UNICODE, &len);
    3402          96 :                         if (!NT_STATUS_IS_OK(status)) {
    3403           0 :                                 return status;
    3404             :                         }
    3405          96 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NORMALIZED_NAME_INFORMATION\n"));
    3406          96 :                         data_size = 4 + len;
    3407          96 :                         SIVAL(pdata,0,len);
    3408          96 :                         *fixed_portion = 8;
    3409          96 :                         break;
    3410             :                 }
    3411             : 
    3412           8 :                 case SMB_FILE_ALLOCATION_INFORMATION:
    3413             :                 case SMB_QUERY_FILE_ALLOCATION_INFO:
    3414           8 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
    3415           8 :                         data_size = 8;
    3416           8 :                         SOFF_T(pdata,0,allocation_size);
    3417           8 :                         break;
    3418             : 
    3419           8 :                 case SMB_FILE_END_OF_FILE_INFORMATION:
    3420             :                 case SMB_QUERY_FILE_END_OF_FILEINFO:
    3421           8 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
    3422           8 :                         data_size = 8;
    3423           8 :                         SOFF_T(pdata,0,file_size);
    3424           8 :                         break;
    3425             : 
    3426        1922 :                 case SMB_QUERY_FILE_ALL_INFO:
    3427             :                 case SMB_FILE_ALL_INFORMATION:
    3428             :                 {
    3429         252 :                         unsigned int ea_size =
    3430        1922 :                             estimate_ea_size(smb_fname->fsp);
    3431        1922 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
    3432        1922 :                         put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
    3433        1922 :                         put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
    3434        1922 :                         put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
    3435        1922 :                         put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
    3436        1922 :                         SIVAL(pdata,32,mode);
    3437        1922 :                         SIVAL(pdata,36,0); /* padding. */
    3438        1922 :                         pdata += 40;
    3439        1922 :                         SOFF_T(pdata,0,allocation_size);
    3440        1922 :                         SOFF_T(pdata,8,file_size);
    3441        1922 :                         SIVAL(pdata,16,nlink);
    3442        1922 :                         SCVAL(pdata,20,delete_pending);
    3443        1922 :                         SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
    3444        1922 :                         SSVAL(pdata,22,0);
    3445        1922 :                         pdata += 24;
    3446        1922 :                         SIVAL(pdata,0,ea_size);
    3447        1922 :                         pdata += 4; /* EA info */
    3448        1922 :                         status = srvstr_push(dstart, flags2,
    3449             :                                           pdata+4, dos_fname,
    3450             :                                           PTR_DIFF(dend, pdata+4),
    3451             :                                           STR_UNICODE, &len);
    3452        1922 :                         if (!NT_STATUS_IS_OK(status)) {
    3453           0 :                                 return status;
    3454             :                         }
    3455        1922 :                         SIVAL(pdata,0,len);
    3456        1922 :                         pdata += 4 + len;
    3457        1922 :                         data_size = PTR_DIFF(pdata,(*ppdata));
    3458        1922 :                         *fixed_portion = 10;
    3459        1922 :                         break;
    3460             :                 }
    3461             : 
    3462        5590 :                 case SMB2_FILE_ALL_INFORMATION:
    3463             :                 {
    3464           0 :                         unsigned int ea_size =
    3465        5590 :                             estimate_ea_size(smb_fname->fsp);
    3466        5590 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
    3467        5590 :                         put_long_date_full_timespec(conn->ts_res,pdata+0x00,&create_time_ts);
    3468        5590 :                         put_long_date_full_timespec(conn->ts_res,pdata+0x08,&atime_ts);
    3469        5590 :                         put_long_date_full_timespec(conn->ts_res,pdata+0x10,&mtime_ts); /* write time */
    3470        5590 :                         put_long_date_full_timespec(conn->ts_res,pdata+0x18,&ctime_ts); /* change time */
    3471        5590 :                         SIVAL(pdata,    0x20, mode);
    3472        5590 :                         SIVAL(pdata,    0x24, 0); /* padding. */
    3473        5590 :                         SBVAL(pdata,    0x28, allocation_size);
    3474        5590 :                         SBVAL(pdata,    0x30, file_size);
    3475        5590 :                         SIVAL(pdata,    0x38, nlink);
    3476        5590 :                         SCVAL(pdata,    0x3C, delete_pending);
    3477        5590 :                         SCVAL(pdata,    0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
    3478        5590 :                         SSVAL(pdata,    0x3E, 0); /* padding */
    3479        5590 :                         SBVAL(pdata,    0x40, file_id);
    3480        5590 :                         SIVAL(pdata,    0x48, ea_size);
    3481        5590 :                         SIVAL(pdata,    0x4C, access_mask);
    3482        5590 :                         SBVAL(pdata,    0x50, pos);
    3483        5590 :                         SIVAL(pdata,    0x58, mode); /*TODO: mode != mode fix this!!! */
    3484        5590 :                         SIVAL(pdata,    0x5C, 0); /* No alignment needed. */
    3485             : 
    3486        5590 :                         pdata += 0x60;
    3487             : 
    3488        5590 :                         status = srvstr_push(dstart, flags2,
    3489             :                                           pdata+4, dos_fname,
    3490             :                                           PTR_DIFF(dend, pdata+4),
    3491             :                                           STR_UNICODE, &len);
    3492        5590 :                         if (!NT_STATUS_IS_OK(status)) {
    3493           0 :                                 return status;
    3494             :                         }
    3495        5590 :                         SIVAL(pdata,0,len);
    3496        5590 :                         pdata += 4 + len;
    3497        5590 :                         data_size = PTR_DIFF(pdata,(*ppdata));
    3498        5590 :                         *fixed_portion = 104;
    3499        5590 :                         break;
    3500             :                 }
    3501          62 :                 case SMB_FILE_INTERNAL_INFORMATION:
    3502             : 
    3503          62 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
    3504          62 :                         SBVAL(pdata, 0, file_id);
    3505          62 :                         data_size = 8;
    3506          62 :                         *fixed_portion = 8;
    3507          62 :                         break;
    3508             : 
    3509        1072 :                 case SMB_FILE_ACCESS_INFORMATION:
    3510        1072 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
    3511        1072 :                         SIVAL(pdata, 0, access_mask);
    3512        1072 :                         data_size = 4;
    3513        1072 :                         *fixed_portion = 4;
    3514        1072 :                         break;
    3515             : 
    3516           8 :                 case SMB_FILE_NAME_INFORMATION:
    3517             :                         /* Pathname with leading '\'. */
    3518             :                         {
    3519           0 :                                 size_t byte_len;
    3520           8 :                                 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
    3521           8 :                                 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
    3522           8 :                                 SIVAL(pdata,0,byte_len);
    3523           8 :                                 data_size = 4 + byte_len;
    3524           8 :                                 break;
    3525             :                         }
    3526             : 
    3527           8 :                 case SMB_FILE_DISPOSITION_INFORMATION:
    3528           8 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
    3529           8 :                         data_size = 1;
    3530           8 :                         SCVAL(pdata,0,delete_pending);
    3531           8 :                         *fixed_portion = 1;
    3532           8 :                         break;
    3533             : 
    3534        2103 :                 case SMB_FILE_POSITION_INFORMATION:
    3535        2103 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
    3536        2103 :                         data_size = 8;
    3537        2103 :                         SOFF_T(pdata,0,pos);
    3538        2103 :                         *fixed_portion = 8;
    3539        2103 :                         break;
    3540             : 
    3541          40 :                 case SMB_FILE_MODE_INFORMATION:
    3542          40 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
    3543          40 :                         SIVAL(pdata,0,mode);
    3544          40 :                         data_size = 4;
    3545          40 :                         *fixed_portion = 4;
    3546          40 :                         break;
    3547             : 
    3548          40 :                 case SMB_FILE_ALIGNMENT_INFORMATION:
    3549          40 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
    3550          40 :                         SIVAL(pdata,0,0); /* No alignment needed. */
    3551          40 :                         data_size = 4;
    3552          40 :                         *fixed_portion = 4;
    3553          40 :                         break;
    3554             : 
    3555             :                 /*
    3556             :                  * NT4 server just returns "invalid query" to this - if we try
    3557             :                  * to answer it then NTws gets a BSOD! (tridge).  W2K seems to
    3558             :                  * want this. JRA.
    3559             :                  */
    3560             :                 /* The first statement above is false - verified using Thursby
    3561             :                  * client against NT4 -- gcolley.
    3562             :                  */
    3563        3662 :                 case SMB_QUERY_FILE_STREAM_INFO:
    3564             :                 case SMB_FILE_STREAM_INFORMATION: {
    3565        3662 :                         unsigned int num_streams = 0;
    3566        3662 :                         struct stream_struct *streams = NULL;
    3567             : 
    3568        3662 :                         DEBUG(10,("smbd_do_qfilepathinfo: "
    3569             :                                   "SMB_FILE_STREAM_INFORMATION\n"));
    3570             : 
    3571        3662 :                         if (is_ntfs_stream_smb_fname(smb_fname)) {
    3572          64 :                                 return NT_STATUS_INVALID_PARAMETER;
    3573             :                         }
    3574             : 
    3575        3598 :                         status = vfs_fstreaminfo(fsp,
    3576             :                                                 mem_ctx,
    3577             :                                                 &num_streams,
    3578             :                                                 &streams);
    3579             : 
    3580        3598 :                         if (!NT_STATUS_IS_OK(status)) {
    3581           0 :                                 DEBUG(10, ("could not get stream info: %s\n",
    3582             :                                            nt_errstr(status)));
    3583           0 :                                 return status;
    3584             :                         }
    3585             : 
    3586        3598 :                         status = marshall_stream_info(num_streams, streams,
    3587             :                                                       pdata, max_data_bytes,
    3588             :                                                       &data_size);
    3589             : 
    3590        3598 :                         if (!NT_STATUS_IS_OK(status)) {
    3591         152 :                                 DEBUG(10, ("marshall_stream_info failed: %s\n",
    3592             :                                            nt_errstr(status)));
    3593         152 :                                 TALLOC_FREE(streams);
    3594         152 :                                 return status;
    3595             :                         }
    3596             : 
    3597        3446 :                         TALLOC_FREE(streams);
    3598             : 
    3599        3446 :                         *fixed_portion = 32;
    3600             : 
    3601        3446 :                         break;
    3602             :                 }
    3603          88 :                 case SMB_QUERY_COMPRESSION_INFO:
    3604             :                 case SMB_FILE_COMPRESSION_INFORMATION:
    3605          88 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
    3606          88 :                         SOFF_T(pdata,0,file_size);
    3607          88 :                         SIVAL(pdata,8,0); /* ??? */
    3608          88 :                         SIVAL(pdata,12,0); /* ??? */
    3609          88 :                         data_size = 16;
    3610          88 :                         *fixed_portion = 16;
    3611          88 :                         break;
    3612             : 
    3613         244 :                 case SMB_FILE_NETWORK_OPEN_INFORMATION:
    3614         244 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
    3615         244 :                         put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
    3616         244 :                         put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
    3617         244 :                         put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
    3618         244 :                         put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
    3619         244 :                         SOFF_T(pdata,32,allocation_size);
    3620         244 :                         SOFF_T(pdata,40,file_size);
    3621         244 :                         SIVAL(pdata,48,mode);
    3622         244 :                         SIVAL(pdata,52,0); /* ??? */
    3623         244 :                         data_size = 56;
    3624         244 :                         *fixed_portion = 56;
    3625         244 :                         break;
    3626             : 
    3627          52 :                 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
    3628          52 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
    3629          52 :                         SIVAL(pdata,0,mode);
    3630          52 :                         SIVAL(pdata,4,0);
    3631          52 :                         data_size = 8;
    3632          52 :                         *fixed_portion = 8;
    3633          52 :                         break;
    3634             : 
    3635             :                 /*
    3636             :                  * SMB2 UNIX Extensions.
    3637             :                  */
    3638           0 :                 case SMB2_FILE_POSIX_INFORMATION_INTERNAL:
    3639             :                 {
    3640           0 :                         struct smb3_file_posix_information info = {};
    3641           0 :                         uint8_t buf[sizeof(info)];
    3642           0 :                         struct ndr_push ndr = {
    3643             :                                 .data = buf,
    3644             :                                 .alloc_size = sizeof(buf),
    3645             :                                 .fixed_buf_size = true,
    3646             :                         };
    3647           0 :                         enum ndr_err_code ndr_err;
    3648             : 
    3649           0 :                         if (!(conn->sconn->using_smb2)) {
    3650           0 :                                 return NT_STATUS_INVALID_LEVEL;
    3651             :                         }
    3652           0 :                         if (fsp == NULL) {
    3653           0 :                                 return NT_STATUS_INVALID_HANDLE;
    3654             :                         }
    3655           0 :                         if (!(fsp->posix_flags & FSP_POSIX_FLAGS_OPEN)) {
    3656           0 :                                 return NT_STATUS_INVALID_LEVEL;
    3657             :                         }
    3658             : 
    3659           0 :                         smb3_file_posix_information_init(
    3660           0 :                                 conn, &smb_fname->st, 0, mode, &info);
    3661             : 
    3662           0 :                         ndr_err = ndr_push_smb3_file_posix_information(
    3663             :                                 &ndr, NDR_SCALARS|NDR_BUFFERS, &info);
    3664           0 :                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    3665           0 :                                 return NT_STATUS_INSUFFICIENT_RESOURCES;
    3666             :                         }
    3667             : 
    3668           0 :                         memcpy(pdata, buf, ndr.offset);
    3669           0 :                         data_size = ndr.offset;
    3670           0 :                         break;
    3671             :                 }
    3672             : 
    3673           8 :                 default:
    3674           8 :                         return NT_STATUS_INVALID_LEVEL;
    3675             :         }
    3676             : 
    3677       24175 :         *pdata_size = data_size;
    3678       24175 :         return NT_STATUS_OK;
    3679             : }
    3680             : 
    3681             : /****************************************************************************
    3682             :  Set a hard link (called by UNIX extensions and by NT rename with HARD link
    3683             :  code.
    3684             : ****************************************************************************/
    3685             : 
    3686          51 : NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
    3687             :                 connection_struct *conn,
    3688             :                 struct smb_request *req,
    3689             :                 bool overwrite_if_exists,
    3690             :                 const struct smb_filename *smb_fname_old,
    3691             :                 struct smb_filename *smb_fname_new)
    3692             : {
    3693          51 :         NTSTATUS status = NT_STATUS_OK;
    3694           1 :         int ret;
    3695           1 :         bool ok;
    3696          51 :         struct smb_filename *parent_fname_old = NULL;
    3697          51 :         struct smb_filename *base_name_old = NULL;
    3698          51 :         struct smb_filename *parent_fname_new = NULL;
    3699          51 :         struct smb_filename *base_name_new = NULL;
    3700             : 
    3701             :         /* source must already exist. */
    3702          51 :         if (!VALID_STAT(smb_fname_old->st)) {
    3703           0 :                 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
    3704           0 :                 goto out;
    3705             :         }
    3706             : 
    3707             :         /* No links from a directory. */
    3708          51 :         if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
    3709           8 :                 status = NT_STATUS_FILE_IS_A_DIRECTORY;
    3710           8 :                 goto out;
    3711             :         }
    3712             : 
    3713             :         /* Setting a hardlink to/from a stream isn't currently supported. */
    3714          43 :         ok = is_ntfs_stream_smb_fname(smb_fname_old);
    3715          43 :         if (ok) {
    3716           0 :                 DBG_DEBUG("Old name has streams\n");
    3717           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    3718           0 :                 goto out;
    3719             :         }
    3720          43 :         ok = is_ntfs_stream_smb_fname(smb_fname_new);
    3721          43 :         if (ok) {
    3722           0 :                 DBG_DEBUG("New name has streams\n");
    3723           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    3724           0 :                 goto out;
    3725             :         }
    3726             : 
    3727          43 :         status = parent_pathref(talloc_tos(),
    3728             :                                 conn->cwd_fsp,
    3729             :                                 smb_fname_old,
    3730             :                                 &parent_fname_old,
    3731             :                                 &base_name_old);
    3732          43 :         if (!NT_STATUS_IS_OK(status)) {
    3733           0 :                 goto out;
    3734             :         }
    3735             : 
    3736          43 :         status = parent_pathref(talloc_tos(),
    3737             :                                 conn->cwd_fsp,
    3738             :                                 smb_fname_new,
    3739             :                                 &parent_fname_new,
    3740             :                                 &base_name_new);
    3741          43 :         if (!NT_STATUS_IS_OK(status)) {
    3742           0 :                 goto out;
    3743             :         }
    3744             : 
    3745          43 :         if (VALID_STAT(smb_fname_new->st)) {
    3746           0 :                 if (overwrite_if_exists) {
    3747           0 :                         if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
    3748           0 :                                 status = NT_STATUS_FILE_IS_A_DIRECTORY;
    3749           0 :                                 goto out;
    3750             :                         }
    3751           0 :                         status = unlink_internals(conn,
    3752             :                                                 req,
    3753             :                                                 FILE_ATTRIBUTE_NORMAL,
    3754             :                                                 NULL, /* new_dirfsp */
    3755             :                                                 smb_fname_new);
    3756           0 :                         if (!NT_STATUS_IS_OK(status)) {
    3757           0 :                                 goto out;
    3758             :                         }
    3759             :                 } else {
    3760             :                         /* Disallow if newname already exists. */
    3761           0 :                         status = NT_STATUS_OBJECT_NAME_COLLISION;
    3762           0 :                         goto out;
    3763             :                 }
    3764             :         }
    3765             : 
    3766          43 :         DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
    3767             :                   smb_fname_old->base_name, smb_fname_new->base_name));
    3768             : 
    3769          43 :         ret = SMB_VFS_LINKAT(conn,
    3770             :                         parent_fname_old->fsp,
    3771             :                         base_name_old,
    3772             :                         parent_fname_new->fsp,
    3773             :                         base_name_new,
    3774             :                         0);
    3775             : 
    3776          43 :         if (ret != 0) {
    3777           0 :                 status = map_nt_error_from_unix(errno);
    3778           0 :                 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
    3779             :                          nt_errstr(status), smb_fname_old->base_name,
    3780             :                          smb_fname_new->base_name));
    3781             :         }
    3782             : 
    3783          43 :   out:
    3784             : 
    3785          51 :         TALLOC_FREE(parent_fname_old);
    3786          51 :         TALLOC_FREE(parent_fname_new);
    3787          51 :         return status;
    3788             : }
    3789             : 
    3790             : /****************************************************************************
    3791             :  Deal with setting the time from any of the setfilepathinfo functions.
    3792             :  NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
    3793             :  calling this function.
    3794             : ****************************************************************************/
    3795             : 
    3796       11038 : NTSTATUS smb_set_file_time(connection_struct *conn,
    3797             :                            files_struct *fsp,
    3798             :                            struct smb_filename *smb_fname,
    3799             :                            struct smb_file_time *ft,
    3800             :                            bool setting_write_time)
    3801             : {
    3802       11038 :         struct files_struct *set_fsp = NULL;
    3803         115 :         struct timeval_buf tbuf[4];
    3804       11038 :         uint32_t action =
    3805             :                 FILE_NOTIFY_CHANGE_LAST_ACCESS
    3806             :                 |FILE_NOTIFY_CHANGE_LAST_WRITE
    3807             :                 |FILE_NOTIFY_CHANGE_CREATION;
    3808         115 :         int ret;
    3809             : 
    3810       11038 :         if (!VALID_STAT(smb_fname->st)) {
    3811           0 :                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
    3812             :         }
    3813             : 
    3814       11038 :         if (fsp == NULL) {
    3815             :                 /* A symlink */
    3816           0 :                 return NT_STATUS_OK;
    3817             :         }
    3818             : 
    3819       11038 :         set_fsp = metadata_fsp(fsp);
    3820             : 
    3821             :         /* get some defaults (no modifications) if any info is zero or -1. */
    3822       11038 :         if (is_omit_timespec(&ft->create_time)) {
    3823       10194 :                 action &= ~FILE_NOTIFY_CHANGE_CREATION;
    3824             :         }
    3825             : 
    3826       11038 :         if (is_omit_timespec(&ft->atime)) {
    3827       10139 :                 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
    3828             :         }
    3829             : 
    3830       11038 :         if (is_omit_timespec(&ft->mtime)) {
    3831        3120 :                 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
    3832             :         }
    3833             : 
    3834       11038 :         if (!setting_write_time) {
    3835             :                 /* ft->mtime comes from change time, not write time. */
    3836        6705 :                 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
    3837             :         }
    3838             : 
    3839             :         /* Ensure the resolution is the correct for
    3840             :          * what we can store on this filesystem. */
    3841             : 
    3842       11038 :         round_timespec(conn->ts_res, &ft->create_time);
    3843       11038 :         round_timespec(conn->ts_res, &ft->ctime);
    3844       11038 :         round_timespec(conn->ts_res, &ft->atime);
    3845       11038 :         round_timespec(conn->ts_res, &ft->mtime);
    3846             : 
    3847       11038 :         DBG_DEBUG("smb_set_filetime: actime: %s\n ",
    3848             :                   timespec_string_buf(&ft->atime, true, &tbuf[0]));
    3849       11038 :         DBG_DEBUG("smb_set_filetime: modtime: %s\n ",
    3850             :                   timespec_string_buf(&ft->mtime, true, &tbuf[1]));
    3851       11038 :         DBG_DEBUG("smb_set_filetime: ctime: %s\n ",
    3852             :                   timespec_string_buf(&ft->ctime, true, &tbuf[2]));
    3853       11038 :         DBG_DEBUG("smb_set_file_time: createtime: %s\n ",
    3854             :                   timespec_string_buf(&ft->create_time, true, &tbuf[3]));
    3855             : 
    3856       11038 :         if (setting_write_time) {
    3857             :                 /*
    3858             :                  * This was a Windows setfileinfo on an open file.
    3859             :                  * NT does this a lot. We also need to
    3860             :                  * set the time here, as it can be read by
    3861             :                  * FindFirst/FindNext and with the patch for bug #2045
    3862             :                  * in smbd/fileio.c it ensures that this timestamp is
    3863             :                  * kept sticky even after a write. We save the request
    3864             :                  * away and will set it on file close and after a write. JRA.
    3865             :                  */
    3866             : 
    3867        4333 :                 DBG_DEBUG("setting pending modtime to %s\n",
    3868             :                           timespec_string_buf(&ft->mtime, true, &tbuf[0]));
    3869             : 
    3870        4333 :                 if (set_fsp != NULL) {
    3871        4333 :                         set_sticky_write_time_fsp(set_fsp, ft->mtime);
    3872             :                 } else {
    3873           0 :                         set_sticky_write_time_path(
    3874           0 :                                 vfs_file_id_from_sbuf(conn, &smb_fname->st),
    3875             :                                 ft->mtime);
    3876             :                 }
    3877             :         }
    3878             : 
    3879       11038 :         DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
    3880             : 
    3881       11038 :         ret = file_ntimes(conn, set_fsp, ft);
    3882       11038 :         if (ret != 0) {
    3883           2 :                 return map_nt_error_from_unix(errno);
    3884             :         }
    3885             : 
    3886       11036 :         notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
    3887       11036 :                      smb_fname->base_name);
    3888       11036 :         return NT_STATUS_OK;
    3889             : }
    3890             : 
    3891             : /****************************************************************************
    3892             :  Deal with setting the dosmode from any of the setfilepathinfo functions.
    3893             :  NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
    3894             :  done before calling this function.
    3895             : ****************************************************************************/
    3896             : 
    3897        2812 : static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
    3898             :                                      struct files_struct *fsp,
    3899             :                                      uint32_t dosmode)
    3900             : {
    3901        2812 :         struct files_struct *dos_fsp = NULL;
    3902          31 :         uint32_t current_dosmode;
    3903          31 :         int ret;
    3904             : 
    3905        2812 :         if (!VALID_STAT(fsp->fsp_name->st)) {
    3906           0 :                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
    3907             :         }
    3908             : 
    3909        2812 :         dos_fsp = metadata_fsp(fsp);
    3910             : 
    3911        2812 :         if (dosmode != 0) {
    3912        1275 :                 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
    3913         183 :                         dosmode |= FILE_ATTRIBUTE_DIRECTORY;
    3914             :                 } else {
    3915        1092 :                         dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
    3916             :                 }
    3917             :         }
    3918             : 
    3919        2812 :         DBG_DEBUG("dosmode: 0x%" PRIx32 "\n", dosmode);
    3920             : 
    3921             :         /* check the mode isn't different, before changing it */
    3922        2812 :         if (dosmode == 0) {
    3923        1537 :                 return NT_STATUS_OK;
    3924             :         }
    3925        1275 :         current_dosmode = fdos_mode(dos_fsp);
    3926        1275 :         if (dosmode == current_dosmode) {
    3927         292 :                 return NT_STATUS_OK;
    3928             :         }
    3929             : 
    3930         983 :         DBG_DEBUG("file %s : setting dos mode 0x%" PRIx32 "\n",
    3931             :                   fsp_str_dbg(dos_fsp), dosmode);
    3932             : 
    3933         983 :         ret = file_set_dosmode(conn, dos_fsp->fsp_name, dosmode, NULL, false);
    3934         983 :         if (ret != 0) {
    3935           5 :                 DBG_WARNING("file_set_dosmode of %s failed: %s\n",
    3936             :                             fsp_str_dbg(dos_fsp), strerror(errno));
    3937           5 :                 return map_nt_error_from_unix(errno);
    3938             :         }
    3939             : 
    3940         978 :         return NT_STATUS_OK;
    3941             : }
    3942             : 
    3943             : /****************************************************************************
    3944             :  Deal with setting the size from any of the setfilepathinfo functions.
    3945             : ****************************************************************************/
    3946             : 
    3947         471 : NTSTATUS smb_set_file_size(connection_struct *conn,
    3948             :                            struct smb_request *req,
    3949             :                            files_struct *fsp,
    3950             :                            struct smb_filename *smb_fname,
    3951             :                            const SMB_STRUCT_STAT *psbuf,
    3952             :                            off_t size,
    3953             :                            bool fail_after_createfile)
    3954             : {
    3955         471 :         NTSTATUS status = NT_STATUS_OK;
    3956         471 :         files_struct *new_fsp = NULL;
    3957             : 
    3958         471 :         if (!VALID_STAT(*psbuf)) {
    3959           0 :                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
    3960             :         }
    3961             : 
    3962         471 :         DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
    3963             :                  (uint64_t)size,
    3964             :                  get_file_size_stat(psbuf));
    3965             : 
    3966         471 :         if (size == get_file_size_stat(psbuf)) {
    3967         148 :                 if (fsp == NULL) {
    3968           0 :                         return NT_STATUS_OK;
    3969             :                 }
    3970         148 :                 if (!fsp->fsp_flags.modified) {
    3971         144 :                         return NT_STATUS_OK;
    3972             :                 }
    3973           4 :                 trigger_write_time_update_immediate(fsp);
    3974           4 :                 return NT_STATUS_OK;
    3975             :         }
    3976             : 
    3977         323 :         DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
    3978             :                   smb_fname_str_dbg(smb_fname), (double)size));
    3979             : 
    3980         323 :         if (fsp &&
    3981         606 :             !fsp->fsp_flags.is_pathref &&
    3982         283 :             fsp_get_io_fd(fsp) != -1)
    3983             :         {
    3984             :                 /* Handle based call. */
    3985         283 :                 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
    3986           0 :                         return NT_STATUS_ACCESS_DENIED;
    3987             :                 }
    3988             : 
    3989         283 :                 if (vfs_set_filelen(fsp, size) == -1) {
    3990           8 :                         return map_nt_error_from_unix(errno);
    3991             :                 }
    3992         275 :                 trigger_write_time_update_immediate(fsp);
    3993         275 :                 return NT_STATUS_OK;
    3994             :         }
    3995             : 
    3996          40 :         status = SMB_VFS_CREATE_FILE(
    3997             :                 conn,                                   /* conn */
    3998             :                 req,                                    /* req */
    3999             :                 NULL,                                   /* dirfsp */
    4000             :                 smb_fname,                              /* fname */
    4001             :                 FILE_WRITE_DATA,                        /* access_mask */
    4002             :                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
    4003             :                     FILE_SHARE_DELETE),
    4004             :                 FILE_OPEN,                              /* create_disposition*/
    4005             :                 0,                                      /* create_options */
    4006             :                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
    4007             :                 0,                                      /* oplock_request */
    4008             :                 NULL,                                   /* lease */
    4009             :                 0,                                      /* allocation_size */
    4010             :                 0,                                      /* private_flags */
    4011             :                 NULL,                                   /* sd */
    4012             :                 NULL,                                   /* ea_list */
    4013             :                 &new_fsp,                           /* result */
    4014             :                 NULL,                                   /* pinfo */
    4015             :                 NULL, NULL);                            /* create context */
    4016             : 
    4017          40 :         if (!NT_STATUS_IS_OK(status)) {
    4018             :                 /* NB. We check for open_was_deferred in the caller. */
    4019          28 :                 return status;
    4020             :         }
    4021             : 
    4022             :         /* See RAW-SFILEINFO-END-OF-FILE */
    4023          12 :         if (fail_after_createfile) {
    4024           4 :                 close_file_free(req, &new_fsp, NORMAL_CLOSE);
    4025           4 :                 return NT_STATUS_INVALID_LEVEL;
    4026             :         }
    4027             : 
    4028           8 :         if (vfs_set_filelen(new_fsp, size) == -1) {
    4029           0 :                 status = map_nt_error_from_unix(errno);
    4030           0 :                 close_file_free(req, &new_fsp, NORMAL_CLOSE);
    4031           0 :                 return status;
    4032             :         }
    4033             : 
    4034           8 :         trigger_write_time_update_immediate(new_fsp);
    4035           8 :         close_file_free(req, &new_fsp, NORMAL_CLOSE);
    4036           8 :         return NT_STATUS_OK;
    4037             : }
    4038             : 
    4039             : /****************************************************************************
    4040             :  Deal with SMB_INFO_SET_EA.
    4041             : ****************************************************************************/
    4042             : 
    4043        2931 : static NTSTATUS smb_info_set_ea(connection_struct *conn,
    4044             :                                 const char *pdata,
    4045             :                                 int total_data,
    4046             :                                 files_struct *fsp,
    4047             :                                 struct smb_filename *smb_fname)
    4048             : {
    4049        2931 :         struct ea_list *ea_list = NULL;
    4050        2931 :         TALLOC_CTX *ctx = NULL;
    4051        2931 :         NTSTATUS status = NT_STATUS_OK;
    4052             : 
    4053        2931 :         if (total_data < 10) {
    4054             : 
    4055             :                 /* OS/2 workplace shell seems to send SET_EA requests of "null"
    4056             :                    length. They seem to have no effect. Bug #3212. JRA */
    4057             : 
    4058           0 :                 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
    4059             :                         /* We're done. We only get EA info in this call. */
    4060           0 :                         return NT_STATUS_OK;
    4061             :                 }
    4062             : 
    4063           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4064             :         }
    4065             : 
    4066        2931 :         if (IVAL(pdata,0) > total_data) {
    4067           0 :                 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
    4068             :                         IVAL(pdata,0), (unsigned int)total_data));
    4069           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4070             :         }
    4071             : 
    4072        2931 :         ctx = talloc_tos();
    4073        2931 :         ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
    4074        2931 :         if (!ea_list) {
    4075           8 :                 return NT_STATUS_INVALID_PARAMETER;
    4076             :         }
    4077             : 
    4078        2923 :         if (fsp == NULL) {
    4079             :                 /*
    4080             :                  * The only way fsp can be NULL here is if
    4081             :                  * smb_fname points at a symlink and
    4082             :                  * and we're in POSIX context.
    4083             :                  * Ensure this is the case.
    4084             :                  *
    4085             :                  * In this case we cannot set the EA.
    4086             :                  */
    4087           0 :                 SMB_ASSERT(smb_fname->flags & SMB_FILENAME_POSIX_PATH);
    4088           0 :                 return NT_STATUS_ACCESS_DENIED;
    4089             :         }
    4090             : 
    4091        2923 :         status = set_ea(conn, fsp, ea_list);
    4092             : 
    4093        2923 :         return status;
    4094             : }
    4095             : 
    4096             : /****************************************************************************
    4097             :  Deal with SMB_FILE_FULL_EA_INFORMATION set.
    4098             : ****************************************************************************/
    4099             : 
    4100          12 : static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
    4101             :                                 const char *pdata,
    4102             :                                 int total_data,
    4103             :                                 files_struct *fsp)
    4104             : {
    4105          12 :         struct ea_list *ea_list = NULL;
    4106           0 :         NTSTATUS status;
    4107             : 
    4108          12 :         if (fsp == NULL) {
    4109           0 :                 return NT_STATUS_INVALID_HANDLE;
    4110             :         }
    4111             : 
    4112          12 :         if (!lp_ea_support(SNUM(conn))) {
    4113           0 :                 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
    4114             :                         "EA's not supported.\n",
    4115             :                         (unsigned int)total_data));
    4116           0 :                 return NT_STATUS_EAS_NOT_SUPPORTED;
    4117             :         }
    4118             : 
    4119          12 :         if (total_data < 10) {
    4120           0 :                 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
    4121             :                         "too small.\n",
    4122             :                         (unsigned int)total_data));
    4123           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4124             :         }
    4125             : 
    4126          12 :         ea_list = read_nttrans_ea_list(talloc_tos(),
    4127             :                                 pdata,
    4128             :                                 total_data);
    4129             : 
    4130          12 :         if (!ea_list) {
    4131           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4132             :         }
    4133             : 
    4134          12 :         status = set_ea(conn, fsp, ea_list);
    4135             : 
    4136          12 :         DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
    4137             :                 smb_fname_str_dbg(fsp->fsp_name),
    4138             :                 nt_errstr(status) ));
    4139             : 
    4140          12 :         return status;
    4141             : }
    4142             : 
    4143             : 
    4144             : /****************************************************************************
    4145             :  Deal with SMB_SET_FILE_DISPOSITION_INFO.
    4146             : ****************************************************************************/
    4147             : 
    4148        3878 : NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
    4149             :                                        const char *pdata,
    4150             :                                        int total_data,
    4151             :                                        files_struct *fsp,
    4152             :                                        struct smb_filename *smb_fname)
    4153             : {
    4154        3878 :         NTSTATUS status = NT_STATUS_OK;
    4155          21 :         bool delete_on_close;
    4156        3878 :         uint32_t dosmode = 0;
    4157             : 
    4158        3878 :         if (total_data < 1) {
    4159           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4160             :         }
    4161             : 
    4162        3878 :         if (fsp == NULL) {
    4163           0 :                 return NT_STATUS_INVALID_HANDLE;
    4164             :         }
    4165             : 
    4166        3878 :         delete_on_close = (CVAL(pdata,0) ? True : False);
    4167        3878 :         dosmode = fdos_mode(fsp);
    4168             : 
    4169        3878 :         DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
    4170             :                 "delete_on_close = %u\n",
    4171             :                 smb_fname_str_dbg(smb_fname),
    4172             :                 (unsigned int)dosmode,
    4173             :                 (unsigned int)delete_on_close ));
    4174             : 
    4175        3878 :         if (delete_on_close) {
    4176        3823 :                 status = can_set_delete_on_close(fsp, dosmode);
    4177        3823 :                 if (!NT_STATUS_IS_OK(status)) {
    4178          88 :                         return status;
    4179             :                 }
    4180             :         }
    4181             : 
    4182             :         /* The set is across all open files on this dev/inode pair. */
    4183        3790 :         if (!set_delete_on_close(fsp, delete_on_close,
    4184        3790 :                                  conn->session_info->security_token,
    4185        3790 :                                  conn->session_info->unix_token)) {
    4186           8 :                 return NT_STATUS_ACCESS_DENIED;
    4187             :         }
    4188        3782 :         return NT_STATUS_OK;
    4189             : }
    4190             : 
    4191             : /****************************************************************************
    4192             :  Deal with SMB_FILE_POSITION_INFORMATION.
    4193             : ****************************************************************************/
    4194             : 
    4195          94 : static NTSTATUS smb_file_position_information(connection_struct *conn,
    4196             :                                 const char *pdata,
    4197             :                                 int total_data,
    4198             :                                 files_struct *fsp)
    4199             : {
    4200           2 :         uint64_t position_information;
    4201             : 
    4202          94 :         if (total_data < 8) {
    4203           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4204             :         }
    4205             : 
    4206          94 :         if (fsp == NULL) {
    4207             :                 /* Ignore on pathname based set. */
    4208           0 :                 return NT_STATUS_OK;
    4209             :         }
    4210             : 
    4211          94 :         position_information = (uint64_t)IVAL(pdata,0);
    4212          94 :         position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
    4213             : 
    4214          94 :         DEBUG(10,("smb_file_position_information: Set file position "
    4215             :                   "information for file %s to %.0f\n", fsp_str_dbg(fsp),
    4216             :                   (double)position_information));
    4217          94 :         fh_set_position_information(fsp->fh, position_information);
    4218          94 :         return NT_STATUS_OK;
    4219             : }
    4220             : 
    4221             : /****************************************************************************
    4222             :  Deal with SMB_FILE_MODE_INFORMATION.
    4223             : ****************************************************************************/
    4224             : 
    4225           8 : static NTSTATUS smb_file_mode_information(connection_struct *conn,
    4226             :                                 const char *pdata,
    4227             :                                 int total_data)
    4228             : {
    4229           0 :         uint32_t mode;
    4230             : 
    4231           8 :         if (total_data < 4) {
    4232           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4233             :         }
    4234           8 :         mode = IVAL(pdata,0);
    4235           8 :         if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
    4236           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4237             :         }
    4238           8 :         return NT_STATUS_OK;
    4239             : }
    4240             : 
    4241             : /****************************************************************************
    4242             :  Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
    4243             : ****************************************************************************/
    4244             : 
    4245         791 : static NTSTATUS smb2_file_rename_information(connection_struct *conn,
    4246             :                                             struct smb_request *req,
    4247             :                                             const char *pdata,
    4248             :                                             int total_data,
    4249             :                                             files_struct *fsp,
    4250             :                                             struct smb_filename *smb_fname_src)
    4251             : {
    4252           0 :         bool overwrite;
    4253           0 :         uint32_t len;
    4254         791 :         char *newname = NULL;
    4255         791 :         struct files_struct *dst_dirfsp = NULL;
    4256         791 :         struct smb_filename *smb_fname_dst = NULL;
    4257         791 :         const char *dst_original_lcomp = NULL;
    4258         791 :         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
    4259         791 :         NTSTATUS status = NT_STATUS_OK;
    4260         791 :         TALLOC_CTX *ctx = talloc_tos();
    4261             : 
    4262         791 :         if (!fsp) {
    4263           0 :                 return NT_STATUS_INVALID_HANDLE;
    4264             :         }
    4265             : 
    4266         791 :         if (total_data < 20) {
    4267           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4268             :         }
    4269             : 
    4270         791 :         overwrite = (CVAL(pdata,0) ? True : False);
    4271         791 :         len = IVAL(pdata,16);
    4272             : 
    4273         791 :         if (len > (total_data - 20) || (len == 0)) {
    4274           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4275             :         }
    4276             : 
    4277         791 :         (void)srvstr_pull_talloc(ctx,
    4278             :                                  pdata,
    4279             :                                  req->flags2,
    4280             :                                  &newname,
    4281             :                                  &pdata[20],
    4282             :                                  len,
    4283             :                                  STR_TERMINATE);
    4284             : 
    4285         791 :         if (newname == NULL) {
    4286           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4287             :         }
    4288             : 
    4289             :         /* SMB2 rename paths are never DFS. */
    4290         791 :         req->flags2 &= ~FLAGS2_DFS_PATHNAMES;
    4291         791 :         ucf_flags &= ~UCF_DFS_PATHNAME;
    4292             : 
    4293         791 :         status = check_path_syntax(newname,
    4294         791 :                         fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
    4295         791 :         if (!NT_STATUS_IS_OK(status)) {
    4296           0 :                 return status;
    4297             :         }
    4298             : 
    4299         791 :         DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
    4300             :                                 newname));
    4301             : 
    4302         791 :         if (newname[0] == ':') {
    4303             :                 /* Create an smb_fname to call rename_internals_fsp() with. */
    4304          16 :                 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
    4305          16 :                                         fsp->base_fsp->fsp_name->base_name,
    4306             :                                         newname,
    4307             :                                         NULL,
    4308          16 :                                         fsp->base_fsp->fsp_name->twrp,
    4309          16 :                                         fsp->base_fsp->fsp_name->flags);
    4310          16 :                 if (smb_fname_dst == NULL) {
    4311           0 :                         status = NT_STATUS_NO_MEMORY;
    4312           0 :                         goto out;
    4313             :                 }
    4314             :         } else {
    4315         775 :                 status = filename_convert_dirfsp(ctx,
    4316             :                                                  conn,
    4317             :                                                  newname,
    4318             :                                                  ucf_flags,
    4319             :                                                  0, /* Never a TWRP. */
    4320             :                                                  &dst_dirfsp,
    4321             :                                                  &smb_fname_dst);
    4322         775 :                 if (!NT_STATUS_IS_OK(status)) {
    4323         130 :                         goto out;
    4324             :                 }
    4325             :         }
    4326             : 
    4327             :         /*
    4328             :          * Set the original last component, since
    4329             :          * rename_internals_fsp() requires it.
    4330             :          */
    4331         661 :         dst_original_lcomp = get_original_lcomp(smb_fname_dst,
    4332             :                                         conn,
    4333             :                                         newname,
    4334             :                                         ucf_flags);
    4335         661 :         if (dst_original_lcomp == NULL) {
    4336           0 :                 status = NT_STATUS_NO_MEMORY;
    4337           0 :                 goto out;
    4338             :         }
    4339             : 
    4340         661 :         DEBUG(10,("smb2_file_rename_information: "
    4341             :                   "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
    4342             :                   fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
    4343             :                   smb_fname_str_dbg(smb_fname_dst)));
    4344         661 :         status = rename_internals_fsp(conn,
    4345             :                                 fsp,
    4346             :                                 smb_fname_dst,
    4347             :                                 dst_original_lcomp,
    4348             :                                 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
    4349             :                                 overwrite);
    4350             : 
    4351         791 :  out:
    4352         791 :         TALLOC_FREE(smb_fname_dst);
    4353         791 :         return status;
    4354             : }
    4355             : 
    4356          18 : static NTSTATUS smb2_file_link_information(connection_struct *conn,
    4357             :                                             struct smb_request *req,
    4358             :                                             const char *pdata,
    4359             :                                             int total_data,
    4360             :                                             files_struct *fsp,
    4361             :                                             struct smb_filename *smb_fname_src)
    4362             : {
    4363           0 :         bool overwrite;
    4364           0 :         uint32_t len;
    4365          18 :         char *newname = NULL;
    4366          18 :         struct files_struct *dst_dirfsp = NULL;
    4367          18 :         struct smb_filename *smb_fname_dst = NULL;
    4368          18 :         NTSTATUS status = NT_STATUS_OK;
    4369          18 :         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
    4370           0 :         size_t ret;
    4371          18 :         TALLOC_CTX *ctx = talloc_tos();
    4372             : 
    4373          18 :         if (!fsp) {
    4374           0 :                 return NT_STATUS_INVALID_HANDLE;
    4375             :         }
    4376             : 
    4377          18 :         if (total_data < 20) {
    4378           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4379             :         }
    4380             : 
    4381          18 :         overwrite = (CVAL(pdata,0) ? true : false);
    4382          18 :         len = IVAL(pdata,16);
    4383             : 
    4384          18 :         if (len > (total_data - 20) || (len == 0)) {
    4385           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4386             :         }
    4387             : 
    4388          18 :         ret = srvstr_pull_talloc(ctx,
    4389             :                                  pdata,
    4390             :                                  req->flags2,
    4391             :                                  &newname,
    4392             :                                  &pdata[20],
    4393             :                                  len,
    4394             :                                  STR_TERMINATE);
    4395             : 
    4396          18 :         if (ret == (size_t)-1 || newname == NULL) {
    4397           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4398             :         }
    4399             : 
    4400             :         /* SMB2 hardlink paths are never DFS. */
    4401          18 :         req->flags2 &= ~FLAGS2_DFS_PATHNAMES;
    4402          18 :         ucf_flags &= ~UCF_DFS_PATHNAME;
    4403             : 
    4404          18 :         status = check_path_syntax(newname,
    4405          18 :                         fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
    4406          18 :         if (!NT_STATUS_IS_OK(status)) {
    4407           0 :                 return status;
    4408             :         }
    4409             : 
    4410          18 :         DBG_DEBUG("got name |%s|\n", newname);
    4411             : 
    4412          18 :         status = filename_convert_dirfsp(ctx,
    4413             :                                          conn,
    4414             :                                          newname,
    4415             :                                          ucf_flags,
    4416             :                                          0, /* No TWRP. */
    4417             :                                          &dst_dirfsp,
    4418             :                                          &smb_fname_dst);
    4419          18 :         if (!NT_STATUS_IS_OK(status)) {
    4420           2 :                 return status;
    4421             :         }
    4422             : 
    4423          16 :         if (fsp->base_fsp) {
    4424             :                 /* No stream names. */
    4425           0 :                 return NT_STATUS_NOT_SUPPORTED;
    4426             :         }
    4427             : 
    4428          16 :         DBG_DEBUG("SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
    4429             :                   fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
    4430             :                   smb_fname_str_dbg(smb_fname_dst));
    4431          16 :         status = hardlink_internals(ctx,
    4432             :                                 conn,
    4433             :                                 req,
    4434             :                                 overwrite,
    4435          16 :                                 fsp->fsp_name,
    4436             :                                 smb_fname_dst);
    4437             : 
    4438          16 :         TALLOC_FREE(smb_fname_dst);
    4439          16 :         return status;
    4440             : }
    4441             : 
    4442           8 : static NTSTATUS smb_file_link_information(connection_struct *conn,
    4443             :                                             struct smb_request *req,
    4444             :                                             const char *pdata,
    4445             :                                             int total_data,
    4446             :                                             files_struct *fsp,
    4447             :                                             struct smb_filename *smb_fname_src)
    4448             : {
    4449           0 :         bool overwrite;
    4450           0 :         uint32_t len;
    4451           8 :         char *newname = NULL;
    4452           8 :         struct files_struct *dst_dirfsp = NULL;
    4453           8 :         struct smb_filename *smb_fname_dst = NULL;
    4454           8 :         NTSTATUS status = NT_STATUS_OK;
    4455           8 :         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
    4456           8 :         NTTIME dst_twrp = 0;
    4457           8 :         TALLOC_CTX *ctx = talloc_tos();
    4458             : 
    4459           8 :         if (!fsp) {
    4460           0 :                 return NT_STATUS_INVALID_HANDLE;
    4461             :         }
    4462             : 
    4463           8 :         if (total_data < 20) {
    4464           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4465             :         }
    4466             : 
    4467           8 :         overwrite = (CVAL(pdata,0) ? true : false);
    4468           8 :         len = IVAL(pdata,16);
    4469             : 
    4470           8 :         if (len > (total_data - 20) || (len == 0)) {
    4471           8 :                 return NT_STATUS_INVALID_PARAMETER;
    4472             :         }
    4473             : 
    4474           0 :         if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) {
    4475           0 :                 srvstr_get_path_posix(ctx,
    4476             :                                 pdata,
    4477           0 :                                 req->flags2,
    4478             :                                 &newname,
    4479             :                                 &pdata[20],
    4480             :                                 len,
    4481             :                                 STR_TERMINATE,
    4482             :                                 &status);
    4483           0 :                 ucf_flags |= UCF_POSIX_PATHNAMES;
    4484             :         } else {
    4485           0 :                 srvstr_get_path(ctx,
    4486             :                                 pdata,
    4487           0 :                                 req->flags2,
    4488             :                                 &newname,
    4489             :                                 &pdata[20],
    4490             :                                 len,
    4491             :                                 STR_TERMINATE,
    4492             :                                 &status);
    4493             :         }
    4494           0 :         if (!NT_STATUS_IS_OK(status)) {
    4495           0 :                 return status;
    4496             :         }
    4497             : 
    4498           0 :         DEBUG(10,("smb_file_link_information: got name |%s|\n",
    4499             :                                 newname));
    4500             : 
    4501           0 :         if (ucf_flags & UCF_GMT_PATHNAME) {
    4502           0 :                 extract_snapshot_token(newname, &dst_twrp);
    4503             :         }
    4504             :         /* hardlink paths are never DFS. */
    4505           0 :         ucf_flags &= ~UCF_DFS_PATHNAME;
    4506             : 
    4507           0 :         status = filename_convert_dirfsp(ctx,
    4508             :                                          conn,
    4509             :                                          newname,
    4510             :                                          ucf_flags,
    4511             :                                          dst_twrp,
    4512             :                                          &dst_dirfsp,
    4513             :                                          &smb_fname_dst);
    4514           0 :         if (!NT_STATUS_IS_OK(status)) {
    4515           0 :                 return status;
    4516             :         }
    4517             : 
    4518           0 :         if (fsp->base_fsp) {
    4519             :                 /* No stream names. */
    4520           0 :                 return NT_STATUS_NOT_SUPPORTED;
    4521             :         }
    4522             : 
    4523           0 :         DEBUG(10,("smb_file_link_information: "
    4524             :                   "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
    4525             :                   fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
    4526             :                   smb_fname_str_dbg(smb_fname_dst)));
    4527           0 :         status = hardlink_internals(ctx,
    4528             :                                 conn,
    4529             :                                 req,
    4530             :                                 overwrite,
    4531           0 :                                 fsp->fsp_name,
    4532             :                                 smb_fname_dst);
    4533             : 
    4534           0 :         TALLOC_FREE(smb_fname_dst);
    4535           0 :         return status;
    4536             : }
    4537             : 
    4538             : 
    4539             : /****************************************************************************
    4540             :  Deal with SMB_FILE_RENAME_INFORMATION.
    4541             : ****************************************************************************/
    4542             : 
    4543         139 : static NTSTATUS smb_file_rename_information(connection_struct *conn,
    4544             :                                             struct smb_request *req,
    4545             :                                             const char *pdata,
    4546             :                                             int total_data,
    4547             :                                             files_struct *fsp,
    4548             :                                             struct smb_filename *smb_fname_src)
    4549             : {
    4550           3 :         bool overwrite;
    4551           3 :         uint32_t root_fid;
    4552           3 :         uint32_t len;
    4553         139 :         char *newname = NULL;
    4554         139 :         struct files_struct *dst_dirfsp = NULL;
    4555         139 :         struct smb_filename *smb_fname_dst = NULL;
    4556         139 :         const char *dst_original_lcomp = NULL;
    4557         139 :         NTSTATUS status = NT_STATUS_OK;
    4558           3 :         char *p;
    4559         139 :         TALLOC_CTX *ctx = talloc_tos();
    4560             : 
    4561         139 :         if (total_data < 13) {
    4562           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4563             :         }
    4564             : 
    4565         139 :         overwrite = (CVAL(pdata,0) != 0);
    4566         139 :         root_fid = IVAL(pdata,4);
    4567         139 :         len = IVAL(pdata,8);
    4568             : 
    4569         139 :         if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
    4570          12 :                 return NT_STATUS_INVALID_PARAMETER;
    4571             :         }
    4572             : 
    4573         127 :         if (req->posix_pathnames) {
    4574           0 :                 srvstr_get_path_posix(ctx,
    4575             :                                 pdata,
    4576           0 :                                 req->flags2,
    4577             :                                 &newname,
    4578             :                                 &pdata[12],
    4579             :                                 len,
    4580             :                                 0,
    4581             :                                 &status);
    4582             :         } else {
    4583         127 :                 srvstr_get_path(ctx,
    4584             :                                 pdata,
    4585         127 :                                 req->flags2,
    4586             :                                 &newname,
    4587             :                                 &pdata[12],
    4588             :                                 len,
    4589             :                                 0,
    4590             :                                 &status);
    4591             :         }
    4592         127 :         if (!NT_STATUS_IS_OK(status)) {
    4593           0 :                 return status;
    4594             :         }
    4595             : 
    4596         127 :         DEBUG(10,("smb_file_rename_information: got name |%s|\n",
    4597             :                                 newname));
    4598             : 
    4599             :         /* Check the new name has no '/' characters. */
    4600         127 :         if (strchr_m(newname, '/')) {
    4601           8 :                 return NT_STATUS_NOT_SUPPORTED;
    4602             :         }
    4603             : 
    4604         119 :         if (fsp && fsp->base_fsp) {
    4605             :                 /* newname must be a stream name. */
    4606          28 :                 if (newname[0] != ':') {
    4607           0 :                         return NT_STATUS_NOT_SUPPORTED;
    4608             :                 }
    4609             : 
    4610             :                 /* Create an smb_fname to call rename_internals_fsp() with. */
    4611          28 :                 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
    4612          28 :                                         fsp->base_fsp->fsp_name->base_name,
    4613             :                                         newname,
    4614             :                                         NULL,
    4615          28 :                                         fsp->base_fsp->fsp_name->twrp,
    4616          28 :                                         fsp->base_fsp->fsp_name->flags);
    4617          28 :                 if (smb_fname_dst == NULL) {
    4618           0 :                         status = NT_STATUS_NO_MEMORY;
    4619           0 :                         goto out;
    4620             :                 }
    4621             : 
    4622             :                 /*
    4623             :                  * Get the original last component, since
    4624             :                  * rename_internals_fsp() requires it.
    4625             :                  */
    4626          28 :                 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
    4627             :                                         conn,
    4628             :                                         newname,
    4629             :                                         0);
    4630          28 :                 if (dst_original_lcomp == NULL) {
    4631           0 :                         status = NT_STATUS_NO_MEMORY;
    4632           0 :                         goto out;
    4633             :                 }
    4634             : 
    4635             :         } else {
    4636             :                 /*
    4637             :                  * Build up an smb_fname_dst based on the filename passed in.
    4638             :                  * We basically just strip off the last component, and put on
    4639             :                  * the newname instead.
    4640             :                  */
    4641          91 :                 char *base_name = NULL;
    4642          91 :                 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
    4643          91 :                 NTTIME dst_twrp = 0;
    4644             : 
    4645             :                 /* newname must *not* be a stream name. */
    4646          91 :                 if (newname[0] == ':') {
    4647           0 :                         return NT_STATUS_NOT_SUPPORTED;
    4648             :                 }
    4649             : 
    4650             :                 /*
    4651             :                  * Strip off the last component (filename) of the path passed
    4652             :                  * in.
    4653             :                  */
    4654          91 :                 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
    4655          91 :                 if (!base_name) {
    4656           0 :                         return NT_STATUS_NO_MEMORY;
    4657             :                 }
    4658          91 :                 p = strrchr_m(base_name, '/');
    4659          91 :                 if (p) {
    4660          80 :                         p[1] = '\0';
    4661             :                 } else {
    4662          11 :                         base_name = talloc_strdup(ctx, "");
    4663          11 :                         if (!base_name) {
    4664           0 :                                 return NT_STATUS_NO_MEMORY;
    4665             :                         }
    4666             :                 }
    4667             :                 /* Append the new name. */
    4668          91 :                 base_name = talloc_asprintf_append(base_name,
    4669             :                                 "%s",
    4670             :                                 newname);
    4671          91 :                 if (!base_name) {
    4672           0 :                         return NT_STATUS_NO_MEMORY;
    4673             :                 }
    4674             : 
    4675          91 :                 if (ucf_flags & UCF_GMT_PATHNAME) {
    4676           0 :                         extract_snapshot_token(base_name, &dst_twrp);
    4677             :                 }
    4678             : 
    4679             :                 /* The newname is *not* a DFS path. */
    4680          91 :                 ucf_flags &= ~UCF_DFS_PATHNAME;
    4681             : 
    4682          91 :                 status = filename_convert_dirfsp(ctx,
    4683             :                                          conn,
    4684             :                                          base_name,
    4685             :                                          ucf_flags,
    4686             :                                          dst_twrp,
    4687             :                                          &dst_dirfsp,
    4688             :                                          &smb_fname_dst);
    4689             : 
    4690          91 :                 if (!NT_STATUS_IS_OK(status)) {
    4691           0 :                         goto out;
    4692             :                 }
    4693          91 :                 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
    4694             :                                         conn,
    4695             :                                         newname,
    4696             :                                         ucf_flags);
    4697          91 :                 if (dst_original_lcomp == NULL) {
    4698           0 :                         status = NT_STATUS_NO_MEMORY;
    4699           0 :                         goto out;
    4700             :                 }
    4701             :         }
    4702             : 
    4703         119 :         if (fsp != NULL && fsp->fsp_flags.is_fsa) {
    4704          80 :                 DEBUG(10,("smb_file_rename_information: "
    4705             :                           "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
    4706             :                           fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
    4707             :                           smb_fname_str_dbg(smb_fname_dst)));
    4708          80 :                 status = rename_internals_fsp(conn,
    4709             :                                         fsp,
    4710             :                                         smb_fname_dst,
    4711             :                                         dst_original_lcomp,
    4712             :                                         0,
    4713             :                                         overwrite);
    4714             :         } else {
    4715          39 :                 DEBUG(10,("smb_file_rename_information: "
    4716             :                           "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
    4717             :                           smb_fname_str_dbg(smb_fname_src),
    4718             :                           smb_fname_str_dbg(smb_fname_dst)));
    4719          39 :                 status = rename_internals(ctx,
    4720             :                                         conn,
    4721             :                                         req,
    4722             :                                         NULL, /* src_dirfsp */
    4723             :                                         smb_fname_src,
    4724             :                                         smb_fname_dst,
    4725             :                                         dst_original_lcomp,
    4726             :                                         0,
    4727             :                                         overwrite,
    4728             :                                         FILE_WRITE_ATTRIBUTES);
    4729             :         }
    4730         119 :  out:
    4731         119 :         TALLOC_FREE(smb_fname_dst);
    4732         119 :         return status;
    4733             : }
    4734             : 
    4735             : /****************************************************************************
    4736             :  Deal with SMB_SET_FILE_BASIC_INFO.
    4737             : ****************************************************************************/
    4738             : 
    4739        2816 : static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
    4740             :                                         const char *pdata,
    4741             :                                         int total_data,
    4742             :                                         files_struct *fsp,
    4743             :                                         struct smb_filename *smb_fname)
    4744             : {
    4745             :         /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
    4746          31 :         struct smb_file_time ft;
    4747        2816 :         uint32_t dosmode = 0;
    4748        2816 :         NTSTATUS status = NT_STATUS_OK;
    4749             : 
    4750        2816 :         init_smb_file_time(&ft);
    4751             : 
    4752        2816 :         if (total_data < 36) {
    4753           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4754             :         }
    4755             : 
    4756        2816 :         if (fsp == NULL) {
    4757           0 :                 return NT_STATUS_INVALID_HANDLE;
    4758             :         }
    4759             : 
    4760        2816 :         status = check_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
    4761        2816 :         if (!NT_STATUS_IS_OK(status)) {
    4762           4 :                 return status;
    4763             :         }
    4764             : 
    4765             :         /* Set the attributes */
    4766        2812 :         dosmode = IVAL(pdata,32);
    4767        2812 :         status = smb_set_file_dosmode(conn, fsp, dosmode);
    4768        2812 :         if (!NT_STATUS_IS_OK(status)) {
    4769           5 :                 return status;
    4770             :         }
    4771             : 
    4772             :         /* create time */
    4773        2807 :         ft.create_time = pull_long_date_full_timespec(pdata);
    4774             : 
    4775             :         /* access time */
    4776        2807 :         ft.atime = pull_long_date_full_timespec(pdata+8);
    4777             : 
    4778             :         /* write time. */
    4779        2807 :         ft.mtime = pull_long_date_full_timespec(pdata+16);
    4780             : 
    4781             :         /* change time. */
    4782        2807 :         ft.ctime = pull_long_date_full_timespec(pdata+24);
    4783             : 
    4784        2807 :         DEBUG(10, ("smb_set_file_basic_info: file %s\n",
    4785             :                    smb_fname_str_dbg(smb_fname)));
    4786             : 
    4787        2807 :         status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
    4788        2807 :         if (!NT_STATUS_IS_OK(status)) {
    4789           0 :                 return status;
    4790             :         }
    4791             : 
    4792        2807 :         if (fsp->fsp_flags.modified) {
    4793        1068 :                 trigger_write_time_update_immediate(fsp);
    4794             :         }
    4795        2807 :         return NT_STATUS_OK;
    4796             : }
    4797             : 
    4798             : /****************************************************************************
    4799             :  Deal with SMB_INFO_STANDARD.
    4800             : ****************************************************************************/
    4801             : 
    4802           8 : static NTSTATUS smb_set_info_standard(connection_struct *conn,
    4803             :                                         const char *pdata,
    4804             :                                         int total_data,
    4805             :                                         files_struct *fsp,
    4806             :                                         struct smb_filename *smb_fname)
    4807             : {
    4808           0 :         NTSTATUS status;
    4809           0 :         struct smb_file_time ft;
    4810             : 
    4811           8 :         init_smb_file_time(&ft);
    4812             : 
    4813           8 :         if (total_data < 12) {
    4814           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4815             :         }
    4816             : 
    4817           8 :         if (fsp == NULL) {
    4818           0 :                 return NT_STATUS_INVALID_HANDLE;
    4819             :         }
    4820             : 
    4821             :         /* create time */
    4822           8 :         ft.create_time = time_t_to_full_timespec(srv_make_unix_date2(pdata));
    4823             :         /* access time */
    4824           8 :         ft.atime = time_t_to_full_timespec(srv_make_unix_date2(pdata+4));
    4825             :         /* write time */
    4826           8 :         ft.mtime = time_t_to_full_timespec(srv_make_unix_date2(pdata+8));
    4827             : 
    4828           8 :         DEBUG(10,("smb_set_info_standard: file %s\n",
    4829             :                 smb_fname_str_dbg(smb_fname)));
    4830             : 
    4831           8 :         status = check_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
    4832           8 :         if (!NT_STATUS_IS_OK(status)) {
    4833           4 :                 return status;
    4834             :         }
    4835             : 
    4836           4 :         status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
    4837           4 :         if (!NT_STATUS_IS_OK(status)) {
    4838           0 :                 return status;
    4839             :         }
    4840             : 
    4841           4 :         if (fsp->fsp_flags.modified) {
    4842           0 :                 trigger_write_time_update_immediate(fsp);
    4843             :         }
    4844           4 :         return NT_STATUS_OK;
    4845             : }
    4846             : 
    4847             : /****************************************************************************
    4848             :  Deal with SMB_SET_FILE_ALLOCATION_INFO.
    4849             : ****************************************************************************/
    4850             : 
    4851          16 : static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
    4852             :                                              struct smb_request *req,
    4853             :                                         const char *pdata,
    4854             :                                         int total_data,
    4855             :                                         files_struct *fsp,
    4856             :                                         struct smb_filename *smb_fname)
    4857             : {
    4858          16 :         uint64_t allocation_size = 0;
    4859          16 :         NTSTATUS status = NT_STATUS_OK;
    4860          16 :         files_struct *new_fsp = NULL;
    4861             : 
    4862          16 :         if (!VALID_STAT(smb_fname->st)) {
    4863           0 :                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
    4864             :         }
    4865             : 
    4866          16 :         if (total_data < 8) {
    4867           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4868             :         }
    4869             : 
    4870          16 :         allocation_size = (uint64_t)IVAL(pdata,0);
    4871          16 :         allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
    4872          16 :         DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
    4873             :                   "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
    4874             :                   (double)allocation_size));
    4875             : 
    4876          16 :         if (allocation_size) {
    4877           6 :                 allocation_size = smb_roundup(conn, allocation_size);
    4878             :         }
    4879             : 
    4880          16 :         DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
    4881             :                   "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
    4882             :                   (double)allocation_size));
    4883             : 
    4884          16 :         if (fsp &&
    4885          20 :             !fsp->fsp_flags.is_pathref &&
    4886           4 :             fsp_get_io_fd(fsp) != -1)
    4887             :         {
    4888             :                 /* Open file handle. */
    4889           4 :                 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
    4890           0 :                         return NT_STATUS_ACCESS_DENIED;
    4891             :                 }
    4892             : 
    4893             :                 /* Only change if needed. */
    4894           4 :                 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
    4895           4 :                         if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
    4896           0 :                                 return map_nt_error_from_unix(errno);
    4897             :                         }
    4898             :                 }
    4899             :                 /* But always update the time. */
    4900             :                 /*
    4901             :                  * This is equivalent to a write. Ensure it's seen immediately
    4902             :                  * if there are no pending writes.
    4903             :                  */
    4904           4 :                 trigger_write_time_update_immediate(fsp);
    4905           4 :                 return NT_STATUS_OK;
    4906             :         }
    4907             : 
    4908             :         /* Pathname or stat or directory file. */
    4909          12 :         status = SMB_VFS_CREATE_FILE(
    4910             :                 conn,                                   /* conn */
    4911             :                 req,                                    /* req */
    4912             :                 NULL,                                   /* dirfsp */
    4913             :                 smb_fname,                              /* fname */
    4914             :                 FILE_WRITE_DATA,                        /* access_mask */
    4915             :                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
    4916             :                     FILE_SHARE_DELETE),
    4917             :                 FILE_OPEN,                              /* create_disposition*/
    4918             :                 0,                                      /* create_options */
    4919             :                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
    4920             :                 0,                                      /* oplock_request */
    4921             :                 NULL,                                   /* lease */
    4922             :                 0,                                      /* allocation_size */
    4923             :                 0,                                      /* private_flags */
    4924             :                 NULL,                                   /* sd */
    4925             :                 NULL,                                   /* ea_list */
    4926             :                 &new_fsp,                           /* result */
    4927             :                 NULL,                                   /* pinfo */
    4928             :                 NULL, NULL);                            /* create context */
    4929             : 
    4930          12 :         if (!NT_STATUS_IS_OK(status)) {
    4931             :                 /* NB. We check for open_was_deferred in the caller. */
    4932          10 :                 return status;
    4933             :         }
    4934             : 
    4935             :         /* Only change if needed. */
    4936           2 :         if (allocation_size != get_file_size_stat(&smb_fname->st)) {
    4937           2 :                 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
    4938           0 :                         status = map_nt_error_from_unix(errno);
    4939           0 :                         close_file_free(req, &new_fsp, NORMAL_CLOSE);
    4940           0 :                         return status;
    4941             :                 }
    4942             :         }
    4943             : 
    4944             :         /* Changing the allocation size should set the last mod time. */
    4945             :         /*
    4946             :          * This is equivalent to a write. Ensure it's seen immediately
    4947             :          * if there are no pending writes.
    4948             :          */
    4949           2 :         trigger_write_time_update_immediate(new_fsp);
    4950           2 :         close_file_free(req, &new_fsp, NORMAL_CLOSE);
    4951           2 :         return NT_STATUS_OK;
    4952             : }
    4953             : 
    4954             : /****************************************************************************
    4955             :  Deal with SMB_SET_FILE_END_OF_FILE_INFO.
    4956             : ****************************************************************************/
    4957             : 
    4958         331 : static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
    4959             :                                               struct smb_request *req,
    4960             :                                         const char *pdata,
    4961             :                                         int total_data,
    4962             :                                         files_struct *fsp,
    4963             :                                         struct smb_filename *smb_fname,
    4964             :                                         bool fail_after_createfile)
    4965             : {
    4966           1 :         off_t size;
    4967             : 
    4968         331 :         if (total_data < 8) {
    4969           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4970             :         }
    4971             : 
    4972         331 :         size = IVAL(pdata,0);
    4973         331 :         size |= (((off_t)IVAL(pdata,4)) << 32);
    4974         331 :         DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
    4975             :                   "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
    4976             :                   (double)size));
    4977             : 
    4978         331 :         return smb_set_file_size(conn, req,
    4979             :                                 fsp,
    4980             :                                 smb_fname,
    4981         331 :                                 &smb_fname->st,
    4982             :                                 size,
    4983             :                                 fail_after_createfile);
    4984             : }
    4985             : 
    4986       10826 : NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
    4987             :                                 struct smb_request *req,
    4988             :                                 TALLOC_CTX *mem_ctx,
    4989             :                                 uint16_t info_level,
    4990             :                                 files_struct *fsp,
    4991             :                                 struct smb_filename *smb_fname,
    4992             :                                 char **ppdata, int total_data,
    4993             :                                 int *ret_data_size)
    4994             : {
    4995       10826 :         char *pdata = *ppdata;
    4996       10826 :         NTSTATUS status = NT_STATUS_OK;
    4997       10826 :         int data_return_size = 0;
    4998             : 
    4999       10826 :         *ret_data_size = 0;
    5000             : 
    5001       10826 :         DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
    5002             :                  "totdata=%d\n", smb_fname_str_dbg(smb_fname),
    5003             :                  fsp_fnum_dbg(fsp),
    5004             :                  info_level, total_data));
    5005             : 
    5006       10826 :         switch (info_level) {
    5007             : 
    5008           8 :                 case SMB_INFO_STANDARD:
    5009             :                 {
    5010           8 :                         status = smb_set_info_standard(conn,
    5011             :                                         pdata,
    5012             :                                         total_data,
    5013             :                                         fsp,
    5014             :                                         smb_fname);
    5015           8 :                         break;
    5016             :                 }
    5017             : 
    5018        2931 :                 case SMB_INFO_SET_EA:
    5019             :                 {
    5020        2931 :                         status = smb_info_set_ea(conn,
    5021             :                                                 pdata,
    5022             :                                                 total_data,
    5023             :                                                 fsp,
    5024             :                                                 smb_fname);
    5025        2931 :                         break;
    5026             :                 }
    5027             : 
    5028        2816 :                 case SMB_SET_FILE_BASIC_INFO:
    5029             :                 case SMB_FILE_BASIC_INFORMATION:
    5030             :                 {
    5031        2816 :                         status = smb_set_file_basic_info(conn,
    5032             :                                                         pdata,
    5033             :                                                         total_data,
    5034             :                                                         fsp,
    5035             :                                                         smb_fname);
    5036        2816 :                         break;
    5037             :                 }
    5038             : 
    5039          16 :                 case SMB_FILE_ALLOCATION_INFORMATION:
    5040             :                 case SMB_SET_FILE_ALLOCATION_INFO:
    5041             :                 {
    5042          16 :                         status = smb_set_file_allocation_info(conn, req,
    5043             :                                                                 pdata,
    5044             :                                                                 total_data,
    5045             :                                                                 fsp,
    5046             :                                                                 smb_fname);
    5047          16 :                         break;
    5048             :                 }
    5049             : 
    5050         331 :                 case SMB_FILE_END_OF_FILE_INFORMATION:
    5051             :                 case SMB_SET_FILE_END_OF_FILE_INFO:
    5052             :                 {
    5053             :                         /*
    5054             :                          * XP/Win7 both fail after the createfile with
    5055             :                          * SMB_SET_FILE_END_OF_FILE_INFO but not
    5056             :                          * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
    5057             :                          * The level is known here, so pass it down
    5058             :                          * appropriately.
    5059             :                          */
    5060         331 :                         bool should_fail =
    5061             :                             (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
    5062             : 
    5063         331 :                         status = smb_set_file_end_of_file_info(conn, req,
    5064             :                                                                 pdata,
    5065             :                                                                 total_data,
    5066             :                                                                 fsp,
    5067             :                                                                 smb_fname,
    5068             :                                                                 should_fail);
    5069         331 :                         break;
    5070             :                 }
    5071             : 
    5072        3638 :                 case SMB_FILE_DISPOSITION_INFORMATION:
    5073             :                 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
    5074             :                 {
    5075             : #if 0
    5076             :                         /* JRA - We used to just ignore this on a path ?
    5077             :                          * Shouldn't this be invalid level on a pathname
    5078             :                          * based call ?
    5079             :                          */
    5080             :                         if (tran_call != TRANSACT2_SETFILEINFO) {
    5081             :                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
    5082             :                         }
    5083             : #endif
    5084        3638 :                         status = smb_set_file_disposition_info(conn,
    5085             :                                                 pdata,
    5086             :                                                 total_data,
    5087             :                                                 fsp,
    5088             :                                                 smb_fname);
    5089        3638 :                         break;
    5090             :                 }
    5091             : 
    5092          94 :                 case SMB_FILE_POSITION_INFORMATION:
    5093             :                 {
    5094          94 :                         status = smb_file_position_information(conn,
    5095             :                                                 pdata,
    5096             :                                                 total_data,
    5097             :                                                 fsp);
    5098          94 :                         break;
    5099             :                 }
    5100             : 
    5101          12 :                 case SMB_FILE_FULL_EA_INFORMATION:
    5102             :                 {
    5103          12 :                         status = smb_set_file_full_ea_info(conn,
    5104             :                                                 pdata,
    5105             :                                                 total_data,
    5106             :                                                 fsp);
    5107          12 :                         break;
    5108             :                 }
    5109             : 
    5110             :                 /* From tridge Samba4 :
    5111             :                  * MODE_INFORMATION in setfileinfo (I have no
    5112             :                  * idea what "mode information" on a file is - it takes a value of 0,
    5113             :                  * 2, 4 or 6. What could it be?).
    5114             :                  */
    5115             : 
    5116           8 :                 case SMB_FILE_MODE_INFORMATION:
    5117             :                 {
    5118           8 :                         status = smb_file_mode_information(conn,
    5119             :                                                 pdata,
    5120             :                                                 total_data);
    5121           8 :                         break;
    5122             :                 }
    5123             : 
    5124             :                 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
    5125           8 :                 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
    5126             :                 case SMB_FILE_SHORT_NAME_INFORMATION:
    5127          16 :                         return NT_STATUS_NOT_SUPPORTED;
    5128             : 
    5129         139 :                 case SMB_FILE_RENAME_INFORMATION:
    5130             :                 {
    5131         139 :                         status = smb_file_rename_information(conn, req,
    5132             :                                                              pdata, total_data,
    5133             :                                                              fsp, smb_fname);
    5134         139 :                         break;
    5135             :                 }
    5136             : 
    5137         791 :                 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
    5138             :                 {
    5139             :                         /* SMB2 rename information. */
    5140         791 :                         status = smb2_file_rename_information(conn, req,
    5141             :                                                              pdata, total_data,
    5142             :                                                              fsp, smb_fname);
    5143         791 :                         break;
    5144             :                 }
    5145             : 
    5146          26 :                 case SMB_FILE_LINK_INFORMATION:
    5147             :                 {
    5148          26 :                         if (conn->sconn->using_smb2) {
    5149          18 :                                 status = smb2_file_link_information(conn,
    5150             :                                                         req,
    5151             :                                                         pdata,
    5152             :                                                         total_data,
    5153             :                                                         fsp,
    5154             :                                                         smb_fname);
    5155             :                         } else {
    5156           8 :                                 status = smb_file_link_information(conn,
    5157             :                                                         req,
    5158             :                                                         pdata,
    5159             :                                                         total_data,
    5160             :                                                         fsp,
    5161             :                                                         smb_fname);
    5162             :                         }
    5163          26 :                         break;
    5164             :                 }
    5165             : 
    5166           8 :                 default:
    5167           8 :                         return NT_STATUS_INVALID_LEVEL;
    5168             :         }
    5169             : 
    5170       10810 :         if (!NT_STATUS_IS_OK(status)) {
    5171         663 :                 return status;
    5172             :         }
    5173             : 
    5174       10147 :         *ret_data_size = data_return_size;
    5175       10147 :         return NT_STATUS_OK;
    5176             : }
    5177             : 
    5178         130 : static uint32_t generate_volume_serial_number(
    5179             :                         const struct loadparm_substitution *lp_sub,
    5180             :                         int snum)
    5181             : {
    5182         130 :         int serial = lp_volume_serial_number(snum);
    5183         258 :         return serial != -1 ? serial:
    5184         128 :                 str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^
    5185         128 :                 (str_checksum(get_local_machine_name())<<16);
    5186             : }

Generated by: LCOV version 1.14