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

Generated by: LCOV version 1.14