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

Generated by: LCOV version 1.14