LCOV - code coverage report
Current view: top level - source3/modules - vfs_default.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 1137 1588 71.6 %
Date: 2021-09-23 10:06:22 Functions: 100 121 82.6 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    Wrap disk only vfs functions to sidestep dodgy compilers.
       4             :    Copyright (C) Tim Potter 1998
       5             :    Copyright (C) Jeremy Allison 2007
       6             : 
       7             :    This program is free software; you can redistribute it and/or modify
       8             :    it under the terms of the GNU General Public License as published by
       9             :    the Free Software Foundation; either version 3 of the License, or
      10             :    (at your option) any later version.
      11             : 
      12             :    This program is distributed in the hope that it will be useful,
      13             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :    GNU General Public License for more details.
      16             : 
      17             :    You should have received a copy of the GNU General Public License
      18             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      19             : */
      20             : 
      21             : #include "includes.h"
      22             : #include "system/time.h"
      23             : #include "system/filesys.h"
      24             : #include "smbd/smbd.h"
      25             : #include "smbd/globals.h"
      26             : #include "ntioctl.h"
      27             : #include "smbprofile.h"
      28             : #include "../libcli/security/security.h"
      29             : #include "passdb/lookup_sid.h"
      30             : #include "source3/include/msdfs.h"
      31             : #include "librpc/gen_ndr/ndr_dfsblobs.h"
      32             : #include "lib/util/tevent_unix.h"
      33             : #include "lib/util/tevent_ntstatus.h"
      34             : #include "lib/util/sys_rw.h"
      35             : #include "lib/pthreadpool/pthreadpool_tevent.h"
      36             : #include "librpc/gen_ndr/ndr_ioctl.h"
      37             : #include "offload_token.h"
      38             : #include "util_reparse.h"
      39             : #include "lib/util/string_wrappers.h"
      40             : 
      41             : #undef DBGC_CLASS
      42             : #define DBGC_CLASS DBGC_VFS
      43             : 
      44             : /* Check for NULL pointer parameters in vfswrap_* functions */
      45             : 
      46             : /* We don't want to have NULL function pointers lying around.  Someone
      47             :    is sure to try and execute them.  These stubs are used to prevent
      48             :    this possibility. */
      49             : 
      50       46583 : static int vfswrap_connect(vfs_handle_struct *handle, const char *service, const char *user)
      51             : {
      52       46583 :         handle->conn->have_proc_fds = sys_have_proc_fds();
      53       46583 :         return 0;    /* Return >= 0 for success */
      54             : }
      55             : 
      56       46512 : static void vfswrap_disconnect(vfs_handle_struct *handle)
      57             : {
      58       46512 : }
      59             : 
      60             : /* Disk operations */
      61             : 
      62        1377 : static uint64_t vfswrap_disk_free(vfs_handle_struct *handle,
      63             :                                 const struct smb_filename *smb_fname,
      64             :                                 uint64_t *bsize,
      65             :                                 uint64_t *dfree,
      66             :                                 uint64_t *dsize)
      67             : {
      68        1377 :         if (sys_fsusage(smb_fname->base_name, dfree, dsize) != 0) {
      69           0 :                 return (uint64_t)-1;
      70             :         }
      71             : 
      72        1377 :         *bsize = 512;
      73        1377 :         return *dfree / 2;
      74             : }
      75             : 
      76        2818 : static int vfswrap_get_quota(struct vfs_handle_struct *handle,
      77             :                                 const struct smb_filename *smb_fname,
      78             :                                 enum SMB_QUOTA_TYPE qtype,
      79             :                                 unid_t id,
      80             :                                 SMB_DISK_QUOTA *qt)
      81             : {
      82             : #ifdef HAVE_SYS_QUOTAS
      83             :         int result;
      84             : 
      85        2818 :         START_PROFILE(syscall_get_quota);
      86        2818 :         result = sys_get_quota(smb_fname->base_name, qtype, id, qt);
      87        2818 :         END_PROFILE(syscall_get_quota);
      88        2818 :         return result;
      89             : #else
      90             :         errno = ENOSYS;
      91             :         return -1;
      92             : #endif
      93             : }
      94             : 
      95           4 : static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
      96             : {
      97             : #ifdef HAVE_SYS_QUOTAS
      98             :         int result;
      99             : 
     100           4 :         START_PROFILE(syscall_set_quota);
     101           4 :         result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
     102           4 :         END_PROFILE(syscall_set_quota);
     103           4 :         return result;
     104             : #else
     105             :         errno = ENOSYS;
     106             :         return -1;
     107             : #endif
     108             : }
     109             : 
     110         232 : static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
     111             :                                         struct files_struct *fsp,
     112             :                                         struct shadow_copy_data *shadow_copy_data,
     113             :                                         bool labels)
     114             : {
     115         232 :         errno = ENOSYS;
     116         232 :         return -1;  /* Not implemented. */
     117             : }
     118             : 
     119       46549 : static int vfswrap_statvfs(struct vfs_handle_struct *handle,
     120             :                                 const struct smb_filename *smb_fname,
     121             :                                 vfs_statvfs_struct *statbuf)
     122             : {
     123       46549 :         return sys_statvfs(smb_fname->base_name, statbuf);
     124             : }
     125             : 
     126       46549 : static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
     127             :                 enum timestamp_set_resolution *p_ts_res)
     128             : {
     129       41721 :         const struct loadparm_substitution *lp_sub =
     130        4828 :                 loadparm_s3_global_substitution();
     131       46549 :         connection_struct *conn = handle->conn;
     132       46549 :         uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
     133       46549 :         struct smb_filename *smb_fname_cpath = NULL;
     134             :         struct vfs_statvfs_struct statbuf;
     135             :         int ret;
     136             : 
     137       46549 :         smb_fname_cpath = synthetic_smb_fname(talloc_tos(),
     138       46549 :                                               conn->connectpath,
     139             :                                               NULL,
     140             :                                               NULL,
     141             :                                               0,
     142             :                                               0);
     143       46549 :         if (smb_fname_cpath == NULL) {
     144           0 :                 return caps;
     145             :         }
     146             : 
     147       46549 :         ZERO_STRUCT(statbuf);
     148       46549 :         ret = SMB_VFS_STATVFS(conn, smb_fname_cpath, &statbuf);
     149       46549 :         if (ret == 0) {
     150       46549 :                 caps = statbuf.FsCapabilities;
     151             :         }
     152             : 
     153       46549 :         *p_ts_res = TIMESTAMP_SET_SECONDS;
     154             : 
     155             :         /* Work out what timestamp resolution we can
     156             :          * use when setting a timestamp. */
     157             : 
     158       46549 :         ret = SMB_VFS_STAT(conn, smb_fname_cpath);
     159       46549 :         if (ret == -1) {
     160           0 :                 TALLOC_FREE(smb_fname_cpath);
     161           0 :                 return caps;
     162             :         }
     163             : 
     164       46549 :         if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
     165           0 :                         smb_fname_cpath->st.st_ex_atime.tv_nsec ||
     166           0 :                         smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
     167             :                 /* If any of the normal UNIX directory timestamps
     168             :                  * have a non-zero tv_nsec component assume
     169             :                  * we might be able to set sub-second timestamps.
     170             :                  * See what filetime set primitives we have.
     171             :                  */
     172             : #if defined(HAVE_UTIMENSAT)
     173       46549 :                 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
     174             : #elif defined(HAVE_UTIMES)
     175             :                 /* utimes allows msec timestamps to be set. */
     176             :                 *p_ts_res = TIMESTAMP_SET_MSEC;
     177             : #elif defined(HAVE_UTIME)
     178             :                 /* utime only allows sec timestamps to be set. */
     179             :                 *p_ts_res = TIMESTAMP_SET_SECONDS;
     180             : #endif
     181             : 
     182       46549 :                 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
     183             :                         "resolution of %s "
     184             :                         "available on share %s, directory %s\n",
     185             :                         *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
     186             :                         lp_servicename(talloc_tos(), lp_sub, conn->params->service),
     187             :                         conn->connectpath ));
     188             :         }
     189       46549 :         TALLOC_FREE(smb_fname_cpath);
     190       46549 :         return caps;
     191             : }
     192             : 
     193        9052 : static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
     194             :                                           struct dfs_GetDFSReferral *r)
     195             : {
     196        9052 :         struct junction_map *junction = NULL;
     197        9052 :         int consumedcnt = 0;
     198        9052 :         bool self_referral = false;
     199        9052 :         char *pathnamep = NULL;
     200        9052 :         char *local_dfs_path = NULL;
     201             :         NTSTATUS status;
     202             :         size_t i;
     203        9052 :         uint16_t max_referral_level = r->in.req.max_referral_level;
     204             : 
     205        9052 :         if (DEBUGLVL(10)) {
     206           0 :                 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
     207             :         }
     208             : 
     209             :         /* get the junction entry */
     210        9052 :         if (r->in.req.servername == NULL) {
     211           0 :                 return NT_STATUS_NOT_FOUND;
     212             :         }
     213             : 
     214             :         /*
     215             :          * Trim pathname sent by client so it begins with only one backslash.
     216             :          * Two backslashes confuse some dfs clients
     217             :          */
     218             : 
     219        9052 :         local_dfs_path = talloc_strdup(r, r->in.req.servername);
     220        9052 :         if (local_dfs_path == NULL) {
     221           0 :                 return NT_STATUS_NO_MEMORY;
     222             :         }
     223        9052 :         pathnamep = local_dfs_path;
     224       26369 :         while (IS_DIRECTORY_SEP(pathnamep[0]) &&
     225       17708 :                IS_DIRECTORY_SEP(pathnamep[1])) {
     226           0 :                 pathnamep++;
     227             :         }
     228             : 
     229        9052 :         junction = talloc_zero(r, struct junction_map);
     230        9052 :         if (junction == NULL) {
     231           0 :                 return NT_STATUS_NO_MEMORY;
     232             :         }
     233             : 
     234             :         /* The following call can change cwd. */
     235       35029 :         status = get_referred_path(r,
     236        9052 :                                    handle->conn->session_info,
     237             :                                    pathnamep,
     238        9052 :                                    handle->conn->sconn->remote_address,
     239        9052 :                                    handle->conn->sconn->local_address,
     240       17711 :                                    !handle->conn->sconn->using_smb2,
     241        9052 :                                    junction, &consumedcnt, &self_referral);
     242        9052 :         if (!NT_STATUS_IS_OK(status)) {
     243       14125 :                 struct smb_filename connectpath_fname = {
     244        7246 :                         .base_name = handle->conn->connectpath
     245             :                 };
     246        7246 :                 vfs_ChDir(handle->conn, &connectpath_fname);
     247        7246 :                 return status;
     248             :         }
     249             :         {
     250        3586 :                 struct smb_filename connectpath_fname = {
     251        1806 :                         .base_name = handle->conn->connectpath
     252             :                 };
     253        1806 :                 vfs_ChDir(handle->conn, &connectpath_fname);
     254             :         }
     255             : 
     256        1806 :         if (!self_referral) {
     257         512 :                 pathnamep[consumedcnt] = '\0';
     258             : 
     259         512 :                 if (DEBUGLVL(3)) {
     260           0 :                         dbgtext("Path %s to alternate path(s):",
     261             :                                 pathnamep);
     262           0 :                         for (i=0; i < junction->referral_count; i++) {
     263           0 :                                 dbgtext(" %s",
     264           0 :                                 junction->referral_list[i].alternate_path);
     265             :                         }
     266           0 :                         dbgtext(".\n");
     267             :                 }
     268             :         }
     269             : 
     270        1806 :         if (r->in.req.max_referral_level <= 2) {
     271           0 :                 max_referral_level = 2;
     272             :         }
     273        1806 :         if (r->in.req.max_referral_level >= 3) {
     274        1806 :                 max_referral_level = 3;
     275             :         }
     276             : 
     277        1806 :         r->out.resp = talloc_zero(r, struct dfs_referral_resp);
     278        1806 :         if (r->out.resp == NULL) {
     279           0 :                 return NT_STATUS_NO_MEMORY;
     280             :         }
     281             : 
     282        1806 :         r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
     283        1806 :         r->out.resp->nb_referrals = junction->referral_count;
     284             : 
     285        1806 :         r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
     286        1806 :         if (self_referral) {
     287        1294 :                 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
     288             :         }
     289             : 
     290        1806 :         r->out.resp->referral_entries = talloc_zero_array(r,
     291             :                                 struct dfs_referral_type,
     292             :                                 r->out.resp->nb_referrals);
     293        1806 :         if (r->out.resp->referral_entries == NULL) {
     294           0 :                 return NT_STATUS_NO_MEMORY;
     295             :         }
     296             : 
     297        1806 :         switch (max_referral_level) {
     298           0 :         case 2:
     299           0 :                 for(i=0; i < junction->referral_count; i++) {
     300           0 :                         struct referral *ref = &junction->referral_list[i];
     301           0 :                         TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
     302           0 :                         struct dfs_referral_type *t =
     303           0 :                                 &r->out.resp->referral_entries[i];
     304           0 :                         struct dfs_referral_v2 *v2 = &t->referral.v2;
     305             : 
     306           0 :                         t->version = 2;
     307           0 :                         v2->size = VERSION2_REFERRAL_SIZE;
     308           0 :                         if (self_referral) {
     309           0 :                                 v2->server_type = DFS_SERVER_ROOT;
     310             :                         } else {
     311           0 :                                 v2->server_type = DFS_SERVER_NON_ROOT;
     312             :                         }
     313           0 :                         v2->entry_flags = 0;
     314           0 :                         v2->proximity = ref->proximity;
     315           0 :                         v2->ttl = ref->ttl;
     316           0 :                         v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
     317           0 :                         if (v2->DFS_path == NULL) {
     318           0 :                                 return NT_STATUS_NO_MEMORY;
     319             :                         }
     320           0 :                         v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
     321           0 :                         if (v2->DFS_alt_path == NULL) {
     322           0 :                                 return NT_STATUS_NO_MEMORY;
     323             :                         }
     324           0 :                         v2->netw_address = talloc_strdup(mem_ctx,
     325           0 :                                                          ref->alternate_path);
     326           0 :                         if (v2->netw_address == NULL) {
     327           0 :                                 return NT_STATUS_NO_MEMORY;
     328             :                         }
     329             :                 }
     330             : 
     331           0 :                 break;
     332        1806 :         case 3:
     333        3754 :                 for(i=0; i < junction->referral_count; i++) {
     334        1948 :                         struct referral *ref = &junction->referral_list[i];
     335        1948 :                         TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
     336        1948 :                         struct dfs_referral_type *t =
     337        1948 :                                 &r->out.resp->referral_entries[i];
     338        1948 :                         struct dfs_referral_v3 *v3 = &t->referral.v3;
     339        1948 :                         struct dfs_normal_referral *r1 = &v3->referrals.r1;
     340             : 
     341        1948 :                         t->version = 3;
     342        1948 :                         v3->size = VERSION3_REFERRAL_SIZE;
     343        1948 :                         if (self_referral) {
     344        1294 :                                 v3->server_type = DFS_SERVER_ROOT;
     345             :                         } else {
     346         654 :                                 v3->server_type = DFS_SERVER_NON_ROOT;
     347             :                         }
     348        1948 :                         v3->entry_flags = 0;
     349        1948 :                         v3->ttl = ref->ttl;
     350        1948 :                         r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
     351        1948 :                         if (r1->DFS_path == NULL) {
     352           0 :                                 return NT_STATUS_NO_MEMORY;
     353             :                         }
     354        1948 :                         r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
     355        1948 :                         if (r1->DFS_alt_path == NULL) {
     356           0 :                                 return NT_STATUS_NO_MEMORY;
     357             :                         }
     358        1984 :                         r1->netw_address = talloc_strdup(mem_ctx,
     359        1948 :                                                          ref->alternate_path);
     360        1948 :                         if (r1->netw_address == NULL) {
     361           0 :                                 return NT_STATUS_NO_MEMORY;
     362             :                         }
     363             :                 }
     364        1806 :                 break;
     365           0 :         default:
     366           0 :                 DEBUG(0,("Invalid dfs referral version: %d\n",
     367             :                         max_referral_level));
     368           0 :                 return NT_STATUS_INVALID_LEVEL;
     369             :         }
     370             : 
     371        1806 :         if (DEBUGLVL(10)) {
     372           0 :                 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
     373             :         }
     374             : 
     375        1806 :         return NT_STATUS_OK;
     376             : }
     377             : 
     378           0 : static NTSTATUS vfswrap_create_dfs_pathat(struct vfs_handle_struct *handle,
     379             :                                 struct files_struct *dirfsp,
     380             :                                 const struct smb_filename *smb_fname,
     381             :                                 const struct referral *reflist,
     382             :                                 size_t referral_count)
     383             : {
     384           0 :         TALLOC_CTX *frame = talloc_stackframe();
     385           0 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
     386             :         int ret;
     387           0 :         char *msdfs_link = NULL;
     388             : 
     389             :         /* Form the msdfs_link contents */
     390           0 :         msdfs_link = msdfs_link_string(frame,
     391             :                                         reflist,
     392             :                                         referral_count);
     393           0 :         if (msdfs_link == NULL) {
     394           0 :                 goto out;
     395             :         }
     396             : 
     397           0 :         ret = symlinkat(msdfs_link,
     398             :                         fsp_get_pathref_fd(dirfsp),
     399           0 :                         smb_fname->base_name);
     400           0 :         if (ret == 0) {
     401           0 :                 status = NT_STATUS_OK;
     402             :         } else {
     403           0 :                 status = map_nt_error_from_unix(errno);
     404             :         }
     405             : 
     406           0 :   out:
     407             : 
     408           0 :         TALLOC_FREE(frame);
     409           0 :         return status;
     410             : }
     411             : 
     412             : /*
     413             :  * Read and return the contents of a DFS redirect given a
     414             :  * pathname. A caller can pass in NULL for ppreflist and
     415             :  * preferral_count but still determine if this was a
     416             :  * DFS redirect point by getting NT_STATUS_OK back
     417             :  * without incurring the overhead of reading and parsing
     418             :  * the referral contents.
     419             :  */
     420             : 
     421       16674 : static NTSTATUS vfswrap_read_dfs_pathat(struct vfs_handle_struct *handle,
     422             :                                 TALLOC_CTX *mem_ctx,
     423             :                                 struct files_struct *dirfsp,
     424             :                                 struct smb_filename *smb_fname,
     425             :                                 struct referral **ppreflist,
     426             :                                 size_t *preferral_count)
     427             : {
     428       16674 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
     429             :         size_t bufsize;
     430       16674 :         char *link_target = NULL;
     431             :         int referral_len;
     432             :         bool ok;
     433             : #if defined(HAVE_BROKEN_READLINK)
     434             :         char link_target_buf[PATH_MAX];
     435             : #else
     436             :         char link_target_buf[7];
     437             : #endif
     438             :         int ret;
     439             : 
     440       16674 :         if (is_named_stream(smb_fname)) {
     441           0 :                 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
     442           0 :                 goto err;
     443             :         }
     444             : 
     445       16674 :         if (ppreflist == NULL && preferral_count == NULL) {
     446             :                 /*
     447             :                  * We're only checking if this is a DFS
     448             :                  * redirect. We don't need to return data.
     449             :                  */
     450       16162 :                 bufsize = sizeof(link_target_buf);
     451       16162 :                 link_target = link_target_buf;
     452             :         } else {
     453         512 :                 bufsize = PATH_MAX;
     454         512 :                 link_target = talloc_array(mem_ctx, char, bufsize);
     455         512 :                 if (!link_target) {
     456           0 :                         goto err;
     457             :                 }
     458             :         }
     459             : 
     460       33290 :         referral_len = readlinkat(fsp_get_pathref_fd(dirfsp),
     461       16674 :                                 smb_fname->base_name,
     462             :                                 link_target,
     463             :                                 bufsize - 1);
     464       16674 :         if (referral_len == -1) {
     465       15388 :                 if (errno == EINVAL) {
     466             :                         /*
     467             :                          * If the path isn't a link, readlinkat
     468             :                          * returns EINVAL. Allow the caller to
     469             :                          * detect this.
     470             :                          */
     471       14232 :                         DBG_INFO("%s is not a link.\n", smb_fname->base_name);
     472       14232 :                         status = NT_STATUS_OBJECT_TYPE_MISMATCH;
     473             :                 } else {
     474        1156 :                         status = map_nt_error_from_unix(errno);
     475        1156 :                         if (errno == ENOENT) {
     476        1156 :                                 DBG_NOTICE("Error reading "
     477             :                                          "msdfs link %s: %s\n",
     478             :                                          smb_fname->base_name,
     479             :                                          strerror(errno));
     480             :                         } else {
     481           0 :                                 DBG_ERR("Error reading "
     482             :                                         "msdfs link %s: %s\n",
     483             :                                         smb_fname->base_name,
     484             :                                         strerror(errno));
     485             :                         }
     486             :                 }
     487       15388 :                 goto err;
     488             :         }
     489        1286 :         link_target[referral_len] = '\0';
     490             : 
     491        1286 :         DBG_INFO("%s -> %s\n",
     492             :                         smb_fname->base_name,
     493             :                         link_target);
     494             : 
     495        1286 :         if (!strnequal(link_target, "msdfs:", 6)) {
     496           0 :                 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
     497           0 :                 goto err;
     498             :         }
     499             : 
     500        2518 :        ret = sys_fstatat(fsp_get_pathref_fd(dirfsp),
     501        1286 :                          smb_fname->base_name,
     502             :                          &smb_fname->st,
     503             :                          AT_SYMLINK_NOFOLLOW,
     504        1286 :                          lp_fake_directory_create_times(SNUM(handle->conn)));
     505        1286 :         if (ret < 0) {
     506           0 :                 status = map_nt_error_from_unix(errno);
     507           0 :                 goto err;
     508             :         }
     509             : 
     510        1286 :         if (ppreflist == NULL && preferral_count == NULL) {
     511             :                 /* Early return for checking if this is a DFS link. */
     512         774 :                 return NT_STATUS_OK;
     513             :         }
     514             : 
     515         512 :         ok = parse_msdfs_symlink(mem_ctx,
     516         512 :                         lp_msdfs_shuffle_referrals(SNUM(handle->conn)),
     517             :                         link_target,
     518             :                         ppreflist,
     519             :                         preferral_count);
     520             : 
     521         512 :         if (ok) {
     522         512 :                 status = NT_STATUS_OK;
     523             :         } else {
     524           0 :                 status = NT_STATUS_NO_MEMORY;
     525             :         }
     526             : 
     527       15900 :   err:
     528             : 
     529       15900 :         if (link_target != link_target_buf) {
     530         512 :                 TALLOC_FREE(link_target);
     531             :         }
     532       15900 :         return status;
     533             : }
     534             : 
     535           0 : static NTSTATUS vfswrap_snap_check_path(struct vfs_handle_struct *handle,
     536             :                                         TALLOC_CTX *mem_ctx,
     537             :                                         const char *service_path,
     538             :                                         char **base_volume)
     539             : {
     540           0 :         return NT_STATUS_NOT_SUPPORTED;
     541             : }
     542             : 
     543           0 : static NTSTATUS vfswrap_snap_create(struct vfs_handle_struct *handle,
     544             :                                     TALLOC_CTX *mem_ctx,
     545             :                                     const char *base_volume,
     546             :                                     time_t *tstamp,
     547             :                                     bool rw,
     548             :                                     char **base_path,
     549             :                                     char **snap_path)
     550             : {
     551           0 :         return NT_STATUS_NOT_SUPPORTED;
     552             : }
     553             : 
     554           0 : static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle,
     555             :                                     TALLOC_CTX *mem_ctx,
     556             :                                     char *base_path,
     557             :                                     char *snap_path)
     558             : {
     559           0 :         return NT_STATUS_NOT_SUPPORTED;
     560             : }
     561             : 
     562             : /* Directory operations */
     563             : 
     564      316595 : static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
     565             :                         files_struct *fsp,
     566             :                         const char *mask,
     567             :                         uint32_t attr)
     568             : {
     569             :         DIR *result;
     570             : 
     571      316595 :         START_PROFILE(syscall_fdopendir);
     572      316595 :         result = sys_fdopendir(fsp_get_io_fd(fsp));
     573      316595 :         END_PROFILE(syscall_fdopendir);
     574      316595 :         return result;
     575             : }
     576             : 
     577             : 
     578   208610119 : static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
     579             :                                       struct files_struct *dirfsp,
     580             :                                       DIR *dirp,
     581             :                                       SMB_STRUCT_STAT *sbuf)
     582             : {
     583             :         struct dirent *result;
     584   208610119 :         bool fake_ctime = lp_fake_directory_create_times(SNUM(handle->conn));
     585   208610119 :         int flags = AT_SYMLINK_NOFOLLOW;
     586             :         SMB_STRUCT_STAT st;
     587             :         int ret;
     588             : 
     589   208610119 :         START_PROFILE(syscall_readdir);
     590             : 
     591   208610119 :         result = readdir(dirp);
     592   208610119 :         END_PROFILE(syscall_readdir);
     593             : 
     594   208610119 :         if (sbuf == NULL) {
     595   208054084 :                 return result;
     596             :         }
     597      549528 :         if (result == NULL) {
     598       27804 :                 return NULL;
     599             :         }
     600             : 
     601             :         /*
     602             :          * Default Posix readdir() does not give us stat info.
     603             :          * Set to invalid to indicate we didn't return this info.
     604             :          */
     605      521572 :         SET_STAT_INVALID(*sbuf);
     606             : 
     607      952058 :         ret = sys_fstatat(dirfd(dirp),
     608      521572 :                       result->d_name,
     609             :                       &st,
     610             :                       flags,
     611             :                       fake_ctime);
     612      521572 :         if (ret != 0) {
     613           2 :                 return result;
     614             :         }
     615             : 
     616             :         /*
     617             :          * As this is an optimization, ignore it if we stat'ed a
     618             :          * symlink for non-POSIX context. Make the caller do it again
     619             :          * as we don't know if they wanted the link info, or its
     620             :          * target info.
     621             :          */
     622      522330 :         if (S_ISLNK(st.st_ex_mode) &&
     623         782 :             !(dirfsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH))
     624             :         {
     625         734 :                 return result;
     626             :         }
     627      520836 :         *sbuf = st;
     628             : 
     629      520836 :         return result;
     630             : }
     631             : 
     632      492784 : static NTSTATUS vfswrap_freaddir_attr(struct vfs_handle_struct *handle,
     633             :                                       struct files_struct *fsp,
     634             :                                       TALLOC_CTX *mem_ctx,
     635             :                                       struct readdir_attr_data **attr_data)
     636             : {
     637      492784 :         return NT_STATUS_NOT_SUPPORTED;
     638             : }
     639             : 
     640        2636 : static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
     641             : {
     642        2636 :         START_PROFILE(syscall_seekdir);
     643        2636 :         seekdir(dirp, offset);
     644        2636 :         END_PROFILE(syscall_seekdir);
     645        2636 : }
     646             : 
     647   205279445 : static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
     648             : {
     649             :         long result;
     650   205279445 :         START_PROFILE(syscall_telldir);
     651   205279445 :         result = telldir(dirp);
     652   205279445 :         END_PROFILE(syscall_telldir);
     653   205279445 :         return result;
     654             : }
     655             : 
     656        1960 : static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
     657             : {
     658        1960 :         START_PROFILE(syscall_rewinddir);
     659        1960 :         rewinddir(dirp);
     660        1960 :         END_PROFILE(syscall_rewinddir);
     661        1960 : }
     662             : 
     663       12098 : static int vfswrap_mkdirat(vfs_handle_struct *handle,
     664             :                         struct files_struct *dirfsp,
     665             :                         const struct smb_filename *smb_fname,
     666             :                         mode_t mode)
     667             : {
     668             :         int result;
     669             : 
     670       12098 :         START_PROFILE(syscall_mkdirat);
     671             : 
     672       12098 :         result = mkdirat(fsp_get_pathref_fd(dirfsp), smb_fname->base_name, mode);
     673             : 
     674       12098 :         END_PROFILE(syscall_mkdirat);
     675       12098 :         return result;
     676             : }
     677             : 
     678      316595 : static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
     679             : {
     680             :         int result;
     681             : 
     682      316595 :         START_PROFILE(syscall_closedir);
     683      316595 :         result = closedir(dirp);
     684      316595 :         END_PROFILE(syscall_closedir);
     685      316595 :         return result;
     686             : }
     687             : 
     688             : /* File operations */
     689             : 
     690    10103459 : static int vfswrap_openat(vfs_handle_struct *handle,
     691             :                           const struct files_struct *dirfsp,
     692             :                           const struct smb_filename *smb_fname,
     693             :                           files_struct *fsp,
     694             :                           int flags,
     695             :                           mode_t mode)
     696             : {
     697    10103459 :         bool have_opath = false;
     698    10103459 :         bool became_root = false;
     699             :         int result;
     700             : 
     701    10103459 :         START_PROFILE(syscall_openat);
     702             : 
     703    10103459 :         if (is_named_stream(smb_fname)) {
     704           0 :                 errno = ENOENT;
     705           0 :                 result = -1;
     706           0 :                 goto out;
     707             :         }
     708             : 
     709             : #ifdef O_PATH
     710     7066542 :         have_opath = true;
     711     7066542 :         if (fsp->fsp_flags.is_pathref) {
     712     6754109 :                 flags |= O_PATH;
     713             :         }
     714             : #endif
     715             : 
     716    10017711 :         if (fsp->fsp_flags.is_pathref && !have_opath) {
     717     2899853 :                 become_root();
     718     2899853 :                 became_root = true;
     719             :         }
     720             : 
     721    10189207 :         result = openat(fsp_get_pathref_fd(dirfsp),
     722    10103459 :                         smb_fname->base_name,
     723             :                         flags,
     724             :                         mode);
     725             : 
     726    10017711 :         if (became_root) {
     727     2899853 :                 unbecome_root();
     728             :         }
     729             : 
     730    10103459 :         fsp->fsp_flags.have_proc_fds = fsp->conn->have_proc_fds;
     731             : 
     732    10103459 : out:
     733    10103459 :         END_PROFILE(syscall_openat);
     734    10103459 :         return result;
     735             : }
     736      539861 : static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
     737             :                                     struct smb_request *req,
     738             :                                     struct smb_filename *smb_fname,
     739             :                                     uint32_t access_mask,
     740             :                                     uint32_t share_access,
     741             :                                     uint32_t create_disposition,
     742             :                                     uint32_t create_options,
     743             :                                     uint32_t file_attributes,
     744             :                                     uint32_t oplock_request,
     745             :                                     const struct smb2_lease *lease,
     746             :                                     uint64_t allocation_size,
     747             :                                     uint32_t private_flags,
     748             :                                     struct security_descriptor *sd,
     749             :                                     struct ea_list *ea_list,
     750             :                                     files_struct **result,
     751             :                                     int *pinfo,
     752             :                                     const struct smb2_create_blobs *in_context_blobs,
     753             :                                     struct smb2_create_blobs *out_context_blobs)
     754             : {
     755      539861 :         return create_file_default(handle->conn, req, smb_fname,
     756             :                                    access_mask, share_access,
     757             :                                    create_disposition, create_options,
     758             :                                    file_attributes, oplock_request, lease,
     759             :                                    allocation_size, private_flags,
     760             :                                    sd, ea_list, result,
     761             :                                    pinfo, in_context_blobs, out_context_blobs);
     762             : }
     763             : 
     764    10111816 : static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
     765             : {
     766             :         int result;
     767             : 
     768    10111816 :         START_PROFILE(syscall_close);
     769    10111816 :         result = fd_close_posix(fsp);
     770    10111816 :         END_PROFILE(syscall_close);
     771    10111816 :         return result;
     772             : }
     773             : 
     774        5248 : static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
     775             :                         size_t n, off_t offset)
     776             : {
     777             :         ssize_t result;
     778             : 
     779             : #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
     780        5248 :         START_PROFILE_BYTES(syscall_pread, n);
     781        5248 :         result = sys_pread_full(fsp_get_io_fd(fsp), data, n, offset);
     782        5248 :         END_PROFILE_BYTES(syscall_pread);
     783             : 
     784        5248 :         if (result == -1 && errno == ESPIPE) {
     785             :                 /* Maintain the fiction that pipes can be seeked (sought?) on. */
     786           0 :                 result = sys_read(fsp_get_io_fd(fsp), data, n);
     787           0 :                 fh_set_pos(fsp->fh, 0);
     788             :         }
     789             : 
     790             : #else /* HAVE_PREAD */
     791             :         errno = ENOSYS;
     792             :         result = -1;
     793             : #endif /* HAVE_PREAD */
     794             : 
     795        5248 :         return result;
     796             : }
     797             : 
     798         978 : static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
     799             :                         size_t n, off_t offset)
     800             : {
     801             :         ssize_t result;
     802             : 
     803             : #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
     804         978 :         START_PROFILE_BYTES(syscall_pwrite, n);
     805         978 :         result = sys_pwrite_full(fsp_get_io_fd(fsp), data, n, offset);
     806         978 :         END_PROFILE_BYTES(syscall_pwrite);
     807             : 
     808         978 :         if (result == -1 && errno == ESPIPE) {
     809             :                 /* Maintain the fiction that pipes can be sought on. */
     810           0 :                 result = sys_write(fsp_get_io_fd(fsp), data, n);
     811             :         }
     812             : 
     813             : #else /* HAVE_PWRITE */
     814             :         errno = ENOSYS;
     815             :         result = -1;
     816             : #endif /* HAVE_PWRITE */
     817             : 
     818         978 :         return result;
     819             : }
     820             : 
     821             : struct vfswrap_pread_state {
     822             :         ssize_t ret;
     823             :         int fd;
     824             :         void *buf;
     825             :         size_t count;
     826             :         off_t offset;
     827             : 
     828             :         struct vfs_aio_state vfs_aio_state;
     829             :         SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
     830             : };
     831             : 
     832             : static void vfs_pread_do(void *private_data);
     833             : static void vfs_pread_done(struct tevent_req *subreq);
     834             : static int vfs_pread_state_destructor(struct vfswrap_pread_state *state);
     835             : 
     836       11881 : static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
     837             :                                              TALLOC_CTX *mem_ctx,
     838             :                                              struct tevent_context *ev,
     839             :                                              struct files_struct *fsp,
     840             :                                              void *data,
     841             :                                              size_t n, off_t offset)
     842             : {
     843             :         struct tevent_req *req, *subreq;
     844             :         struct vfswrap_pread_state *state;
     845             : 
     846       11881 :         req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
     847       11881 :         if (req == NULL) {
     848           0 :                 return NULL;
     849             :         }
     850             : 
     851       11881 :         state->ret = -1;
     852       11881 :         state->fd = fsp_get_io_fd(fsp);
     853       11881 :         state->buf = data;
     854       11881 :         state->count = n;
     855       11881 :         state->offset = offset;
     856             : 
     857       11881 :         SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
     858             :                                      state->profile_bytes, n);
     859       11881 :         SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
     860             : 
     861       22951 :         subreq = pthreadpool_tevent_job_send(
     862       11881 :                 state, ev, handle->conn->sconn->pool,
     863             :                 vfs_pread_do, state);
     864       11881 :         if (tevent_req_nomem(subreq, req)) {
     865           0 :                 return tevent_req_post(req, ev);
     866             :         }
     867       11881 :         tevent_req_set_callback(subreq, vfs_pread_done, req);
     868             : 
     869       11881 :         talloc_set_destructor(state, vfs_pread_state_destructor);
     870             : 
     871       11881 :         return req;
     872             : }
     873             : 
     874       11881 : static void vfs_pread_do(void *private_data)
     875             : {
     876       11881 :         struct vfswrap_pread_state *state = talloc_get_type_abort(
     877             :                 private_data, struct vfswrap_pread_state);
     878             :         struct timespec start_time;
     879             :         struct timespec end_time;
     880             : 
     881       11881 :         SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
     882             : 
     883       11881 :         PROFILE_TIMESTAMP(&start_time);
     884             : 
     885       11881 :         state->ret = sys_pread_full(state->fd,
     886             :                                     state->buf,
     887             :                                     state->count,
     888             :                                     state->offset);
     889             : 
     890       11881 :         if (state->ret == -1) {
     891           0 :                 state->vfs_aio_state.error = errno;
     892             :         }
     893             : 
     894       11881 :         PROFILE_TIMESTAMP(&end_time);
     895             : 
     896       11881 :         state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
     897             : 
     898       11881 :         SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
     899       11881 : }
     900             : 
     901           0 : static int vfs_pread_state_destructor(struct vfswrap_pread_state *state)
     902             : {
     903           0 :         return -1;
     904             : }
     905             : 
     906       11881 : static void vfs_pread_done(struct tevent_req *subreq)
     907             : {
     908       11881 :         struct tevent_req *req = tevent_req_callback_data(
     909             :                 subreq, struct tevent_req);
     910       11881 :         struct vfswrap_pread_state *state = tevent_req_data(
     911             :                 req, struct vfswrap_pread_state);
     912             :         int ret;
     913             : 
     914       11881 :         ret = pthreadpool_tevent_job_recv(subreq);
     915       11881 :         TALLOC_FREE(subreq);
     916       11881 :         SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
     917       11881 :         talloc_set_destructor(state, NULL);
     918       11881 :         if (ret != 0) {
     919           0 :                 if (ret != EAGAIN) {
     920           0 :                         tevent_req_error(req, ret);
     921           0 :                         return;
     922             :                 }
     923             :                 /*
     924             :                  * If we get EAGAIN from pthreadpool_tevent_job_recv() this
     925             :                  * means the lower level pthreadpool failed to create a new
     926             :                  * thread. Fallback to sync processing in that case to allow
     927             :                  * some progress for the client.
     928             :                  */
     929           0 :                 vfs_pread_do(state);
     930             :         }
     931             : 
     932       11881 :         tevent_req_done(req);
     933             : }
     934             : 
     935       11881 : static ssize_t vfswrap_pread_recv(struct tevent_req *req,
     936             :                                   struct vfs_aio_state *vfs_aio_state)
     937             : {
     938       11881 :         struct vfswrap_pread_state *state = tevent_req_data(
     939             :                 req, struct vfswrap_pread_state);
     940             : 
     941       11881 :         if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
     942           0 :                 return -1;
     943             :         }
     944             : 
     945       11881 :         *vfs_aio_state = state->vfs_aio_state;
     946       11881 :         return state->ret;
     947             : }
     948             : 
     949             : struct vfswrap_pwrite_state {
     950             :         ssize_t ret;
     951             :         int fd;
     952             :         const void *buf;
     953             :         size_t count;
     954             :         off_t offset;
     955             : 
     956             :         struct vfs_aio_state vfs_aio_state;
     957             :         SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
     958             : };
     959             : 
     960             : static void vfs_pwrite_do(void *private_data);
     961             : static void vfs_pwrite_done(struct tevent_req *subreq);
     962             : static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state);
     963             : 
     964      143025 : static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
     965             :                                               TALLOC_CTX *mem_ctx,
     966             :                                               struct tevent_context *ev,
     967             :                                               struct files_struct *fsp,
     968             :                                               const void *data,
     969             :                                               size_t n, off_t offset)
     970             : {
     971             :         struct tevent_req *req, *subreq;
     972             :         struct vfswrap_pwrite_state *state;
     973             : 
     974      143025 :         req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
     975      143025 :         if (req == NULL) {
     976           0 :                 return NULL;
     977             :         }
     978             : 
     979      143025 :         state->ret = -1;
     980      143025 :         state->fd = fsp_get_io_fd(fsp);
     981      143025 :         state->buf = data;
     982      143025 :         state->count = n;
     983      143025 :         state->offset = offset;
     984             : 
     985      143025 :         SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
     986             :                                      state->profile_bytes, n);
     987      143025 :         SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
     988             : 
     989      277025 :         subreq = pthreadpool_tevent_job_send(
     990      143025 :                 state, ev, handle->conn->sconn->pool,
     991             :                 vfs_pwrite_do, state);
     992      143025 :         if (tevent_req_nomem(subreq, req)) {
     993           0 :                 return tevent_req_post(req, ev);
     994             :         }
     995      143025 :         tevent_req_set_callback(subreq, vfs_pwrite_done, req);
     996             : 
     997      143025 :         talloc_set_destructor(state, vfs_pwrite_state_destructor);
     998             : 
     999      143025 :         return req;
    1000             : }
    1001             : 
    1002      143025 : static void vfs_pwrite_do(void *private_data)
    1003             : {
    1004      143025 :         struct vfswrap_pwrite_state *state = talloc_get_type_abort(
    1005             :                 private_data, struct vfswrap_pwrite_state);
    1006             :         struct timespec start_time;
    1007             :         struct timespec end_time;
    1008             : 
    1009      143025 :         SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
    1010             : 
    1011      143025 :         PROFILE_TIMESTAMP(&start_time);
    1012             : 
    1013      143025 :         state->ret = sys_pwrite_full(state->fd,
    1014             :                                      state->buf,
    1015             :                                      state->count,
    1016             :                                      state->offset);
    1017             : 
    1018      143025 :         if (state->ret == -1) {
    1019           0 :                 state->vfs_aio_state.error = errno;
    1020             :         }
    1021             : 
    1022      143025 :         PROFILE_TIMESTAMP(&end_time);
    1023             : 
    1024      143025 :         state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
    1025             : 
    1026      143025 :         SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
    1027      143025 : }
    1028             : 
    1029           0 : static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state)
    1030             : {
    1031           0 :         return -1;
    1032             : }
    1033             : 
    1034      143025 : static void vfs_pwrite_done(struct tevent_req *subreq)
    1035             : {
    1036      143025 :         struct tevent_req *req = tevent_req_callback_data(
    1037             :                 subreq, struct tevent_req);
    1038      143025 :         struct vfswrap_pwrite_state *state = tevent_req_data(
    1039             :                 req, struct vfswrap_pwrite_state);
    1040             :         int ret;
    1041             : 
    1042      143025 :         ret = pthreadpool_tevent_job_recv(subreq);
    1043      143025 :         TALLOC_FREE(subreq);
    1044      143025 :         SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
    1045      143025 :         talloc_set_destructor(state, NULL);
    1046      143025 :         if (ret != 0) {
    1047           0 :                 if (ret != EAGAIN) {
    1048           0 :                         tevent_req_error(req, ret);
    1049           0 :                         return;
    1050             :                 }
    1051             :                 /*
    1052             :                  * If we get EAGAIN from pthreadpool_tevent_job_recv() this
    1053             :                  * means the lower level pthreadpool failed to create a new
    1054             :                  * thread. Fallback to sync processing in that case to allow
    1055             :                  * some progress for the client.
    1056             :                  */
    1057           0 :                 vfs_pwrite_do(state);
    1058             :         }
    1059             : 
    1060      143025 :         tevent_req_done(req);
    1061             : }
    1062             : 
    1063      143025 : static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
    1064             :                                    struct vfs_aio_state *vfs_aio_state)
    1065             : {
    1066      143025 :         struct vfswrap_pwrite_state *state = tevent_req_data(
    1067             :                 req, struct vfswrap_pwrite_state);
    1068             : 
    1069      143025 :         if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
    1070           0 :                 return -1;
    1071             :         }
    1072             : 
    1073      143025 :         *vfs_aio_state = state->vfs_aio_state;
    1074      143025 :         return state->ret;
    1075             : }
    1076             : 
    1077             : struct vfswrap_fsync_state {
    1078             :         ssize_t ret;
    1079             :         int fd;
    1080             : 
    1081             :         struct vfs_aio_state vfs_aio_state;
    1082             :         SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
    1083             : };
    1084             : 
    1085             : static void vfs_fsync_do(void *private_data);
    1086             : static void vfs_fsync_done(struct tevent_req *subreq);
    1087             : static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state);
    1088             : 
    1089         138 : static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
    1090             :                                              TALLOC_CTX *mem_ctx,
    1091             :                                              struct tevent_context *ev,
    1092             :                                              struct files_struct *fsp)
    1093             : {
    1094             :         struct tevent_req *req, *subreq;
    1095             :         struct vfswrap_fsync_state *state;
    1096             : 
    1097         138 :         req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
    1098         138 :         if (req == NULL) {
    1099           0 :                 return NULL;
    1100             :         }
    1101             : 
    1102         138 :         state->ret = -1;
    1103         138 :         state->fd = fsp_get_io_fd(fsp);
    1104             : 
    1105         138 :         SMBPROFILE_BYTES_ASYNC_START(syscall_asys_fsync, profile_p,
    1106             :                                      state->profile_bytes, 0);
    1107         138 :         SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
    1108             : 
    1109         271 :         subreq = pthreadpool_tevent_job_send(
    1110         138 :                 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
    1111         138 :         if (tevent_req_nomem(subreq, req)) {
    1112           0 :                 return tevent_req_post(req, ev);
    1113             :         }
    1114         138 :         tevent_req_set_callback(subreq, vfs_fsync_done, req);
    1115             : 
    1116         138 :         talloc_set_destructor(state, vfs_fsync_state_destructor);
    1117             : 
    1118         138 :         return req;
    1119             : }
    1120             : 
    1121         138 : static void vfs_fsync_do(void *private_data)
    1122             : {
    1123         138 :         struct vfswrap_fsync_state *state = talloc_get_type_abort(
    1124             :                 private_data, struct vfswrap_fsync_state);
    1125             :         struct timespec start_time;
    1126             :         struct timespec end_time;
    1127             : 
    1128         138 :         SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
    1129             : 
    1130         138 :         PROFILE_TIMESTAMP(&start_time);
    1131             : 
    1132             :         do {
    1133         138 :                 state->ret = fsync(state->fd);
    1134         138 :         } while ((state->ret == -1) && (errno == EINTR));
    1135             : 
    1136         138 :         if (state->ret == -1) {
    1137           0 :                 state->vfs_aio_state.error = errno;
    1138             :         }
    1139             : 
    1140         138 :         PROFILE_TIMESTAMP(&end_time);
    1141             : 
    1142         138 :         state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
    1143             : 
    1144         138 :         SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
    1145         138 : }
    1146             : 
    1147           0 : static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state)
    1148             : {
    1149           0 :         return -1;
    1150             : }
    1151             : 
    1152         138 : static void vfs_fsync_done(struct tevent_req *subreq)
    1153             : {
    1154         138 :         struct tevent_req *req = tevent_req_callback_data(
    1155             :                 subreq, struct tevent_req);
    1156         138 :         struct vfswrap_fsync_state *state = tevent_req_data(
    1157             :                 req, struct vfswrap_fsync_state);
    1158             :         int ret;
    1159             : 
    1160         138 :         ret = pthreadpool_tevent_job_recv(subreq);
    1161         138 :         TALLOC_FREE(subreq);
    1162         138 :         SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
    1163         138 :         talloc_set_destructor(state, NULL);
    1164         138 :         if (ret != 0) {
    1165           0 :                 if (ret != EAGAIN) {
    1166           0 :                         tevent_req_error(req, ret);
    1167           0 :                         return;
    1168             :                 }
    1169             :                 /*
    1170             :                  * If we get EAGAIN from pthreadpool_tevent_job_recv() this
    1171             :                  * means the lower level pthreadpool failed to create a new
    1172             :                  * thread. Fallback to sync processing in that case to allow
    1173             :                  * some progress for the client.
    1174             :                  */
    1175           0 :                 vfs_fsync_do(state);
    1176             :         }
    1177             : 
    1178         138 :         tevent_req_done(req);
    1179             : }
    1180             : 
    1181         138 : static int vfswrap_fsync_recv(struct tevent_req *req,
    1182             :                               struct vfs_aio_state *vfs_aio_state)
    1183             : {
    1184         138 :         struct vfswrap_fsync_state *state = tevent_req_data(
    1185             :                 req, struct vfswrap_fsync_state);
    1186             : 
    1187         138 :         if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
    1188           0 :                 return -1;
    1189             :         }
    1190             : 
    1191         138 :         *vfs_aio_state = state->vfs_aio_state;
    1192         138 :         return state->ret;
    1193             : }
    1194             : 
    1195         335 : static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
    1196             : {
    1197         335 :         off_t result = 0;
    1198             : 
    1199         335 :         START_PROFILE(syscall_lseek);
    1200             : 
    1201         335 :         result = lseek(fsp_get_io_fd(fsp), offset, whence);
    1202             :         /*
    1203             :          * We want to maintain the fiction that we can seek
    1204             :          * on a fifo for file system purposes. This allows
    1205             :          * people to set up UNIX fifo's that feed data to Windows
    1206             :          * applications. JRA.
    1207             :          */
    1208             : 
    1209         335 :         if((result == -1) && (errno == ESPIPE)) {
    1210           0 :                 result = 0;
    1211           0 :                 errno = 0;
    1212             :         }
    1213             : 
    1214         335 :         END_PROFILE(syscall_lseek);
    1215         335 :         return result;
    1216             : }
    1217             : 
    1218           0 : static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
    1219             :                         off_t offset, size_t n)
    1220             : {
    1221             :         ssize_t result;
    1222             : 
    1223           0 :         START_PROFILE_BYTES(syscall_sendfile, n);
    1224           0 :         result = sys_sendfile(tofd, fsp_get_io_fd(fromfsp), hdr, offset, n);
    1225           0 :         END_PROFILE_BYTES(syscall_sendfile);
    1226           0 :         return result;
    1227             : }
    1228             : 
    1229           0 : static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
    1230             :                         int fromfd,
    1231             :                         files_struct *tofsp,
    1232             :                         off_t offset,
    1233             :                         size_t n)
    1234             : {
    1235             :         ssize_t result;
    1236             : 
    1237           0 :         START_PROFILE_BYTES(syscall_recvfile, n);
    1238           0 :         result = sys_recvfile(fromfd, fsp_get_io_fd(tofsp), offset, n);
    1239           0 :         END_PROFILE_BYTES(syscall_recvfile);
    1240           0 :         return result;
    1241             : }
    1242             : 
    1243         585 : static int vfswrap_renameat(vfs_handle_struct *handle,
    1244             :                           files_struct *srcfsp,
    1245             :                           const struct smb_filename *smb_fname_src,
    1246             :                           files_struct *dstfsp,
    1247             :                           const struct smb_filename *smb_fname_dst)
    1248             : {
    1249         585 :         int result = -1;
    1250             : 
    1251         585 :         START_PROFILE(syscall_renameat);
    1252             : 
    1253         585 :         if (is_named_stream(smb_fname_src) || is_named_stream(smb_fname_dst)) {
    1254           0 :                 errno = ENOENT;
    1255           0 :                 goto out;
    1256             :         }
    1257             : 
    1258        1092 :         result = renameat(fsp_get_pathref_fd(srcfsp),
    1259         585 :                         smb_fname_src->base_name,
    1260             :                         fsp_get_pathref_fd(dstfsp),
    1261         585 :                         smb_fname_dst->base_name);
    1262             : 
    1263         585 :  out:
    1264         585 :         END_PROFILE(syscall_renameat);
    1265         585 :         return result;
    1266             : }
    1267             : 
    1268    31432654 : static int vfswrap_stat(vfs_handle_struct *handle,
    1269             :                         struct smb_filename *smb_fname)
    1270             : {
    1271    31432654 :         int result = -1;
    1272             : 
    1273    31432654 :         START_PROFILE(syscall_stat);
    1274             : 
    1275    31432654 :         if (is_named_stream(smb_fname)) {
    1276           0 :                 errno = ENOENT;
    1277           0 :                 goto out;
    1278             :         }
    1279             : 
    1280    31432654 :         result = sys_stat(smb_fname->base_name, &smb_fname->st,
    1281    31432654 :                           lp_fake_directory_create_times(SNUM(handle->conn)));
    1282    31432654 :  out:
    1283    31432654 :         END_PROFILE(syscall_stat);
    1284    31432654 :         return result;
    1285             : }
    1286             : 
    1287    64655917 : static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
    1288             : {
    1289             :         int result;
    1290             : 
    1291    64655917 :         START_PROFILE(syscall_fstat);
    1292    64655917 :         result = sys_fstat(fsp_get_pathref_fd(fsp),
    1293    64655917 :                            sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
    1294    64655917 :         END_PROFILE(syscall_fstat);
    1295    64655917 :         return result;
    1296             : }
    1297             : 
    1298      107895 : static int vfswrap_lstat(vfs_handle_struct *handle,
    1299             :                          struct smb_filename *smb_fname)
    1300             : {
    1301      107895 :         int result = -1;
    1302             : 
    1303      107895 :         START_PROFILE(syscall_lstat);
    1304             : 
    1305      107895 :         if (is_named_stream(smb_fname)) {
    1306           0 :                 errno = ENOENT;
    1307           0 :                 goto out;
    1308             :         }
    1309             : 
    1310      107895 :         result = sys_lstat(smb_fname->base_name, &smb_fname->st,
    1311      107895 :                            lp_fake_directory_create_times(SNUM(handle->conn)));
    1312      107895 :  out:
    1313      107895 :         END_PROFILE(syscall_lstat);
    1314      107895 :         return result;
    1315             : }
    1316             : 
    1317   207448038 : static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
    1318             :                                        const char *name,
    1319             :                                        enum vfs_translate_direction direction,
    1320             :                                        TALLOC_CTX *mem_ctx,
    1321             :                                        char **mapped_name)
    1322             : {
    1323   207448038 :         return NT_STATUS_NONE_MAPPED;
    1324             : }
    1325             : 
    1326             : /**
    1327             :  * Return allocated parent directory and basename of path
    1328             :  *
    1329             :  * Note: if requesting name, it is returned as talloc child of the
    1330             :  * parent. Freeing the parent is thus sufficient to free both.
    1331             :  */
    1332     2005936 : static NTSTATUS vfswrap_parent_pathname(struct vfs_handle_struct *handle,
    1333             :                                         TALLOC_CTX *mem_ctx,
    1334             :                                         const struct smb_filename *smb_fname_in,
    1335             :                                         struct smb_filename **parent_dir_out,
    1336             :                                         struct smb_filename **atname_out)
    1337             : {
    1338     2005936 :         TALLOC_CTX *frame = talloc_stackframe();
    1339     2005936 :         struct smb_filename *parent = NULL;
    1340     2005936 :         struct smb_filename *name = NULL;
    1341     2005936 :         char *p = NULL;
    1342             : 
    1343     2005936 :         parent = cp_smb_filename(frame, smb_fname_in);
    1344     2005936 :         if (parent == NULL) {
    1345           0 :                 TALLOC_FREE(frame);
    1346           0 :                 return NT_STATUS_NO_MEMORY;
    1347             :         }
    1348     2005936 :         TALLOC_FREE(parent->stream_name);
    1349     2005936 :         SET_STAT_INVALID(parent->st);
    1350             : 
    1351     2005936 :         p = strrchr_m(parent->base_name, '/'); /* Find final '/', if any */
    1352     2005936 :         if (p == NULL) {
    1353      377455 :                 TALLOC_FREE(parent->base_name);
    1354      377455 :                 parent->base_name = talloc_strdup(parent, ".");
    1355      377455 :                 if (parent->base_name == NULL) {
    1356           0 :                         TALLOC_FREE(frame);
    1357           0 :                         return NT_STATUS_NO_MEMORY;
    1358             :                 }
    1359      377455 :                 p = smb_fname_in->base_name;
    1360             :         } else {
    1361     1628481 :                 *p = '\0';
    1362     1628481 :                 p++;
    1363             :         }
    1364             : 
    1365     2005936 :         if (atname_out == NULL) {
    1366         741 :                 *parent_dir_out = talloc_move(mem_ctx, &parent);
    1367         741 :                 TALLOC_FREE(frame);
    1368         741 :                 return NT_STATUS_OK;
    1369             :         }
    1370             : 
    1371     2005195 :         name = cp_smb_filename(frame, smb_fname_in);
    1372     2005195 :         if (name == NULL) {
    1373           0 :                 TALLOC_FREE(frame);
    1374           0 :                 return NT_STATUS_NO_MEMORY;
    1375             :         }
    1376     2005195 :         TALLOC_FREE(name->base_name);
    1377             : 
    1378     2005195 :         name->base_name = talloc_strdup(name, p);
    1379     2005195 :         if (name->base_name == NULL) {
    1380           0 :                 TALLOC_FREE(frame);
    1381           0 :                 return NT_STATUS_NO_MEMORY;
    1382             :         }
    1383             : 
    1384     2005195 :         *parent_dir_out = talloc_move(mem_ctx, &parent);
    1385     2005195 :         *atname_out = talloc_move(*parent_dir_out, &name);
    1386     2005195 :         TALLOC_FREE(frame);
    1387     2005195 :         return NT_STATUS_OK;
    1388             : }
    1389             : 
    1390             : /*
    1391             :  * Implement the default fsctl operation.
    1392             :  */
    1393             : static bool vfswrap_logged_ioctl_message = false;
    1394             : 
    1395        3006 : static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
    1396             :                               struct files_struct *fsp,
    1397             :                               TALLOC_CTX *ctx,
    1398             :                               uint32_t function,
    1399             :                               uint16_t req_flags, /* Needed for UNICODE ... */
    1400             :                               const uint8_t *_in_data,
    1401             :                               uint32_t in_len,
    1402             :                               uint8_t **_out_data,
    1403             :                               uint32_t max_out_len,
    1404             :                               uint32_t *out_len)
    1405             : {
    1406        3006 :         const char *in_data = (const char *)_in_data;
    1407        3006 :         char **out_data = (char **)_out_data;
    1408             :         NTSTATUS status;
    1409             : 
    1410        3006 :         switch (function) {
    1411         188 :         case FSCTL_SET_SPARSE:
    1412             :         {
    1413         188 :                 bool set_sparse = true;
    1414             : 
    1415         188 :                 if (in_len >= 1 && in_data[0] == 0) {
    1416          30 :                         set_sparse = false;
    1417             :                 }
    1418             : 
    1419         188 :                 status = file_set_sparse(handle->conn, fsp, set_sparse);
    1420             : 
    1421         188 :                 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
    1422             :                       ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
    1423             :                        smb_fname_str_dbg(fsp->fsp_name), set_sparse,
    1424             :                        nt_errstr(status)));
    1425             : 
    1426         188 :                 return status;
    1427             :         }
    1428             : 
    1429          70 :         case FSCTL_CREATE_OR_GET_OBJECT_ID:
    1430             :         {
    1431             :                 unsigned char objid[16];
    1432          70 :                 char *return_data = NULL;
    1433             : 
    1434             :                 /* This should return the object-id on this file.
    1435             :                  * I think I'll make this be the inode+dev. JRA.
    1436             :                  */
    1437             : 
    1438          70 :                 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
    1439             :                           fsp_fnum_dbg(fsp)));
    1440             : 
    1441          70 :                 *out_len = MIN(max_out_len, 64);
    1442             : 
    1443             :                 /* Hmmm, will this cause problems if less data asked for? */
    1444          70 :                 return_data = talloc_array(ctx, char, 64);
    1445          70 :                 if (return_data == NULL) {
    1446           0 :                         return NT_STATUS_NO_MEMORY;
    1447             :                 }
    1448             : 
    1449             :                 /* For backwards compatibility only store the dev/inode. */
    1450          70 :                 push_file_id_16(return_data, &fsp->file_id);
    1451          70 :                 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
    1452          70 :                 push_file_id_16(return_data+32, &fsp->file_id);
    1453          70 :                 memset(return_data+48, 0, 16);
    1454          70 :                 *out_data = return_data;
    1455          70 :                 return NT_STATUS_OK;
    1456             :         }
    1457             : 
    1458           4 :         case FSCTL_GET_REPARSE_POINT:
    1459             :         {
    1460           4 :                 status = fsctl_get_reparse_point(
    1461             :                         fsp, ctx, out_data, max_out_len, out_len);
    1462           4 :                 return status;
    1463             :         }
    1464             : 
    1465          18 :         case FSCTL_SET_REPARSE_POINT:
    1466             :         {
    1467          18 :                 status = fsctl_set_reparse_point(fsp, ctx, _in_data, in_len);
    1468          18 :                 return status;
    1469             :         }
    1470             : 
    1471           0 :         case FSCTL_DELETE_REPARSE_POINT:
    1472             :         {
    1473           0 :                 status = fsctl_del_reparse_point(fsp, ctx, _in_data, in_len);
    1474           0 :                 return status;
    1475             :         }
    1476             : 
    1477        2714 :         case FSCTL_GET_SHADOW_COPY_DATA:
    1478             :         {
    1479             :                 /*
    1480             :                  * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
    1481             :                  * and return their volume names.  If max_data_count is 16, then it is just
    1482             :                  * asking for the number of volumes and length of the combined names.
    1483             :                  *
    1484             :                  * pdata is the data allocated by our caller, but that uses
    1485             :                  * total_data_count (which is 0 in our case) rather than max_data_count.
    1486             :                  * Allocate the correct amount and return the pointer to let
    1487             :                  * it be deallocated when we return.
    1488             :                  */
    1489        2714 :                 struct shadow_copy_data *shadow_data = NULL;
    1490        2714 :                 bool labels = False;
    1491        2714 :                 uint32_t labels_data_count = 0;
    1492             :                 uint32_t i;
    1493        2714 :                 char *cur_pdata = NULL;
    1494             : 
    1495        2714 :                 if (max_out_len < 16) {
    1496           4 :                         DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
    1497             :                                 max_out_len));
    1498           4 :                         return NT_STATUS_INVALID_PARAMETER;
    1499             :                 }
    1500             : 
    1501        2710 :                 if (max_out_len > 16) {
    1502        1236 :                         labels = True;
    1503             :                 }
    1504             : 
    1505        2710 :                 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
    1506        2710 :                 if (shadow_data == NULL) {
    1507           0 :                         DEBUG(0,("TALLOC_ZERO() failed!\n"));
    1508           0 :                         return NT_STATUS_NO_MEMORY;
    1509             :                 }
    1510             : 
    1511             :                 /*
    1512             :                  * Call the VFS routine to actually do the work.
    1513             :                  */
    1514        2710 :                 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
    1515         232 :                         int log_lev = 0;
    1516         232 :                         if (errno == 0) {
    1517             :                                 /* broken module didn't set errno on error */
    1518           0 :                                 status = NT_STATUS_UNSUCCESSFUL;
    1519             :                         } else {
    1520         232 :                                 status = map_nt_error_from_unix(errno);
    1521         232 :                                 if (NT_STATUS_EQUAL(status,
    1522             :                                                     NT_STATUS_NOT_SUPPORTED)) {
    1523         232 :                                         log_lev = 5;
    1524             :                                 }
    1525             :                         }
    1526         232 :                         DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
    1527             :                                         "connectpath %s, failed - %s.\n",
    1528             :                                         fsp->conn->connectpath,
    1529             :                                         nt_errstr(status)));
    1530         232 :                         TALLOC_FREE(shadow_data);
    1531         232 :                         return status;
    1532             :                 }
    1533             : 
    1534        4956 :                 labels_data_count = (shadow_data->num_volumes * 2 *
    1535        2478 :                                         sizeof(SHADOW_COPY_LABEL)) + 2;
    1536             : 
    1537        2478 :                 if (!labels) {
    1538        1242 :                         *out_len = 16;
    1539             :                 } else {
    1540        1236 :                         *out_len = 12 + labels_data_count;
    1541             :                 }
    1542             : 
    1543        2478 :                 if (max_out_len < *out_len) {
    1544           0 :                         DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
    1545             :                                 max_out_len, *out_len));
    1546           0 :                         TALLOC_FREE(shadow_data);
    1547           0 :                         return NT_STATUS_BUFFER_TOO_SMALL;
    1548             :                 }
    1549             : 
    1550        2478 :                 cur_pdata = talloc_zero_array(ctx, char, *out_len);
    1551        2478 :                 if (cur_pdata == NULL) {
    1552           0 :                         TALLOC_FREE(shadow_data);
    1553           0 :                         return NT_STATUS_NO_MEMORY;
    1554             :                 }
    1555             : 
    1556        2478 :                 *out_data = cur_pdata;
    1557             : 
    1558             :                 /* num_volumes 4 bytes */
    1559        2478 :                 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
    1560             : 
    1561        2478 :                 if (labels) {
    1562             :                         /* num_labels 4 bytes */
    1563        1236 :                         SIVAL(cur_pdata, 4, shadow_data->num_volumes);
    1564             :                 }
    1565             : 
    1566             :                 /* needed_data_count 4 bytes */
    1567        2478 :                 SIVAL(cur_pdata, 8, labels_data_count);
    1568             : 
    1569        2478 :                 cur_pdata += 12;
    1570             : 
    1571        2478 :                 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
    1572             :                           shadow_data->num_volumes, fsp_str_dbg(fsp)));
    1573        2478 :                 if (labels && shadow_data->labels) {
    1574        4916 :                         for (i=0; i<shadow_data->num_volumes; i++) {
    1575        3680 :                                 size_t len = 0;
    1576        3680 :                                 status = srvstr_push(cur_pdata, req_flags,
    1577             :                                             cur_pdata, shadow_data->labels[i],
    1578             :                                             2 * sizeof(SHADOW_COPY_LABEL),
    1579             :                                             STR_UNICODE|STR_TERMINATE, &len);
    1580        3680 :                                 if (!NT_STATUS_IS_OK(status)) {
    1581           0 :                                         TALLOC_FREE(*out_data);
    1582           0 :                                         TALLOC_FREE(shadow_data);
    1583           0 :                                         return status;
    1584             :                                 }
    1585        3680 :                                 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
    1586        3680 :                                 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
    1587             :                         }
    1588             :                 }
    1589             : 
    1590        2478 :                 TALLOC_FREE(shadow_data);
    1591             : 
    1592        2478 :                 return NT_STATUS_OK;
    1593             :         }
    1594             : 
    1595           4 :         case FSCTL_FIND_FILES_BY_SID:
    1596             :         {
    1597             :                 /* pretend this succeeded -
    1598             :                  *
    1599             :                  * we have to send back a list with all files owned by this SID
    1600             :                  *
    1601             :                  * but I have to check that --metze
    1602             :                  */
    1603             :                 ssize_t ret;
    1604             :                 struct dom_sid sid;
    1605             :                 struct dom_sid_buf buf;
    1606             :                 uid_t uid;
    1607             :                 size_t sid_len;
    1608             : 
    1609           4 :                 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
    1610             :                            fsp_fnum_dbg(fsp)));
    1611             : 
    1612           4 :                 if (in_len < 8) {
    1613             :                         /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
    1614           4 :                         return NT_STATUS_INVALID_PARAMETER;
    1615             :                 }
    1616             : 
    1617           0 :                 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
    1618             : 
    1619             :                 /* unknown 4 bytes: this is not the length of the sid :-(  */
    1620             :                 /*unknown = IVAL(pdata,0);*/
    1621             : 
    1622           0 :                 ret = sid_parse(_in_data + 4, sid_len, &sid);
    1623           0 :                 if (ret == -1) {
    1624           0 :                         return NT_STATUS_INVALID_PARAMETER;
    1625             :                 }
    1626           0 :                 DEBUGADD(10, ("for SID: %s\n",
    1627             :                               dom_sid_str_buf(&sid, &buf)));
    1628             : 
    1629           0 :                 if (!sid_to_uid(&sid, &uid)) {
    1630           0 :                         DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
    1631             :                                  dom_sid_str_buf(&sid, &buf),
    1632             :                                  (unsigned long)sid_len));
    1633           0 :                         uid = (-1);
    1634             :                 }
    1635             : 
    1636             :                 /* we can take a look at the find source :-)
    1637             :                  *
    1638             :                  * find ./ -uid $uid  -name '*'   is what we need here
    1639             :                  *
    1640             :                  *
    1641             :                  * and send 4bytes len and then NULL terminated unicode strings
    1642             :                  * for each file
    1643             :                  *
    1644             :                  * but I don't know how to deal with the paged results
    1645             :                  * (maybe we can hang the result anywhere in the fsp struct)
    1646             :                  *
    1647             :                  * but I don't know how to deal with the paged results
    1648             :                  * (maybe we can hang the result anywhere in the fsp struct)
    1649             :                  *
    1650             :                  * we don't send all files at once
    1651             :                  * and at the next we should *not* start from the beginning,
    1652             :                  * so we have to cache the result
    1653             :                  *
    1654             :                  * --metze
    1655             :                  */
    1656             : 
    1657             :                 /* this works for now... */
    1658           0 :                 return NT_STATUS_OK;
    1659             :         }
    1660             : 
    1661           4 :         case FSCTL_QUERY_ALLOCATED_RANGES:
    1662             :         {
    1663             :                 /* FIXME: This is just a dummy reply, telling that all of the
    1664             :                  * file is allocated. MKS cp needs that.
    1665             :                  * Adding the real allocated ranges via FIEMAP on Linux
    1666             :                  * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
    1667             :                  * this FSCTL correct for sparse files.
    1668             :                  */
    1669             :                 uint64_t offset, length;
    1670           4 :                 char *out_data_tmp = NULL;
    1671             : 
    1672           4 :                 if (in_len != 16) {
    1673           0 :                         DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
    1674             :                                 in_len));
    1675           0 :                         return NT_STATUS_INVALID_PARAMETER;
    1676             :                 }
    1677             : 
    1678           4 :                 if (max_out_len < 16) {
    1679           0 :                         DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
    1680             :                                 max_out_len));
    1681           0 :                         return NT_STATUS_INVALID_PARAMETER;
    1682             :                 }
    1683             : 
    1684           4 :                 offset = BVAL(in_data,0);
    1685           4 :                 length = BVAL(in_data,8);
    1686             : 
    1687           4 :                 if (offset + length < offset) {
    1688             :                         /* No 64-bit integer wrap. */
    1689           0 :                         return NT_STATUS_INVALID_PARAMETER;
    1690             :                 }
    1691             : 
    1692             :                 /* Shouldn't this be SMB_VFS_STAT ... ? */
    1693           4 :                 status = vfs_stat_fsp(fsp);
    1694           4 :                 if (!NT_STATUS_IS_OK(status)) {
    1695           0 :                         return status;
    1696             :                 }
    1697             : 
    1698           4 :                 *out_len = 16;
    1699           4 :                 out_data_tmp = talloc_array(ctx, char, *out_len);
    1700           4 :                 if (out_data_tmp == NULL) {
    1701           0 :                         DEBUG(10, ("unable to allocate memory for response\n"));
    1702           0 :                         return NT_STATUS_NO_MEMORY;
    1703             :                 }
    1704             : 
    1705           8 :                 if (offset > fsp->fsp_name->st.st_ex_size ||
    1706           4 :                                 fsp->fsp_name->st.st_ex_size == 0 ||
    1707             :                                 length == 0) {
    1708           4 :                         memset(out_data_tmp, 0, *out_len);
    1709             :                 } else {
    1710           0 :                         uint64_t end = offset + length;
    1711           0 :                         end = MIN(end, fsp->fsp_name->st.st_ex_size);
    1712           0 :                         SBVAL(out_data_tmp, 0, 0);
    1713           0 :                         SBVAL(out_data_tmp, 8, end);
    1714             :                 }
    1715             : 
    1716           4 :                 *out_data = out_data_tmp;
    1717             : 
    1718           4 :                 return NT_STATUS_OK;
    1719             :         }
    1720             : 
    1721           4 :         case FSCTL_IS_VOLUME_DIRTY:
    1722             :         {
    1723           4 :                 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
    1724             :                           "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
    1725             :                 /*
    1726             :                  * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
    1727             :                  * says we have to respond with NT_STATUS_INVALID_PARAMETER
    1728             :                  */
    1729           4 :                 return NT_STATUS_INVALID_PARAMETER;
    1730             :         }
    1731             : 
    1732           0 :         default:
    1733             :                 /*
    1734             :                  * Only print once ... unfortunately there could be lots of
    1735             :                  * different FSCTLs that are called.
    1736             :                  */
    1737           0 :                 if (!vfswrap_logged_ioctl_message) {
    1738           0 :                         vfswrap_logged_ioctl_message = true;
    1739           0 :                         DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
    1740             :                         __func__, function));
    1741             :                 }
    1742             :         }
    1743             : 
    1744           0 :         return NT_STATUS_NOT_SUPPORTED;
    1745             : }
    1746             : 
    1747             : static bool vfswrap_is_offline(struct connection_struct *conn,
    1748             :                                const struct smb_filename *fname);
    1749             : 
    1750             : struct vfswrap_get_dos_attributes_state {
    1751             :         struct vfs_aio_state aio_state;
    1752             :         connection_struct *conn;
    1753             :         TALLOC_CTX *mem_ctx;
    1754             :         struct tevent_context *ev;
    1755             :         files_struct *dir_fsp;
    1756             :         struct smb_filename *smb_fname;
    1757             :         uint32_t dosmode;
    1758             :         bool as_root;
    1759             : };
    1760             : 
    1761             : static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq);
    1762             : 
    1763       40234 : static struct tevent_req *vfswrap_get_dos_attributes_send(
    1764             :                         TALLOC_CTX *mem_ctx,
    1765             :                         struct tevent_context *ev,
    1766             :                         struct vfs_handle_struct *handle,
    1767             :                         files_struct *dir_fsp,
    1768             :                         struct smb_filename *smb_fname)
    1769             : {
    1770       40234 :         struct tevent_req *req = NULL;
    1771       40234 :         struct tevent_req *subreq = NULL;
    1772       40234 :         struct vfswrap_get_dos_attributes_state *state = NULL;
    1773             : 
    1774       40234 :         req = tevent_req_create(mem_ctx, &state,
    1775             :                                 struct vfswrap_get_dos_attributes_state);
    1776       40234 :         if (req == NULL) {
    1777           0 :                 return NULL;
    1778             :         }
    1779             : 
    1780       80468 :         *state = (struct vfswrap_get_dos_attributes_state) {
    1781       40234 :                 .conn = dir_fsp->conn,
    1782             :                 .mem_ctx = mem_ctx,
    1783             :                 .ev = ev,
    1784             :                 .dir_fsp = dir_fsp,
    1785             :                 .smb_fname = smb_fname,
    1786             :         };
    1787             : 
    1788       40234 :         subreq = SMB_VFS_GETXATTRAT_SEND(state,
    1789             :                                          ev,
    1790             :                                          dir_fsp,
    1791             :                                          smb_fname,
    1792             :                                          SAMBA_XATTR_DOS_ATTRIB,
    1793             :                                          sizeof(fstring));
    1794       40234 :         if (tevent_req_nomem(subreq, req)) {
    1795           0 :                 return tevent_req_post(req, ev);
    1796             :         }
    1797       40234 :         tevent_req_set_callback(subreq,
    1798             :                                 vfswrap_get_dos_attributes_getxattr_done,
    1799             :                                 req);
    1800             : 
    1801       40234 :         return req;
    1802             : }
    1803             : 
    1804       40234 : static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq)
    1805             : {
    1806       40234 :         struct tevent_req *req =
    1807       40234 :                 tevent_req_callback_data(subreq,
    1808             :                 struct tevent_req);
    1809       40234 :         struct vfswrap_get_dos_attributes_state *state =
    1810       40234 :                 tevent_req_data(req,
    1811             :                 struct vfswrap_get_dos_attributes_state);
    1812             :         ssize_t xattr_size;
    1813       40234 :         DATA_BLOB blob = {0};
    1814       40234 :         char *path = NULL;
    1815       40234 :         char *tofree = NULL;
    1816             :         char pathbuf[PATH_MAX+1];
    1817             :         ssize_t pathlen;
    1818             :         struct smb_filename smb_fname;
    1819             :         bool offline;
    1820             :         NTSTATUS status;
    1821             : 
    1822       40234 :         xattr_size = SMB_VFS_GETXATTRAT_RECV(subreq,
    1823             :                                              &state->aio_state,
    1824             :                                              state,
    1825             :                                              &blob.data);
    1826       40234 :         TALLOC_FREE(subreq);
    1827       40234 :         if (xattr_size == -1) {
    1828         208 :                 status = map_nt_error_from_unix(state->aio_state.error);
    1829             : 
    1830         208 :                 if (state->as_root) {
    1831           0 :                         tevent_req_nterror(req, status);
    1832           0 :                         return;
    1833             :                 }
    1834         208 :                 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
    1835         208 :                         tevent_req_nterror(req, status);
    1836         208 :                         return;
    1837             :                 }
    1838             : 
    1839           0 :                 state->as_root = true;
    1840             : 
    1841           0 :                 become_root();
    1842           0 :                 subreq = SMB_VFS_GETXATTRAT_SEND(state,
    1843             :                                                  state->ev,
    1844             :                                                  state->dir_fsp,
    1845             :                                                  state->smb_fname,
    1846             :                                                  SAMBA_XATTR_DOS_ATTRIB,
    1847             :                                                  sizeof(fstring));
    1848           0 :                 unbecome_root();
    1849           0 :                 if (tevent_req_nomem(subreq, req)) {
    1850           0 :                         return;
    1851             :                 }
    1852           0 :                 tevent_req_set_callback(subreq,
    1853             :                                         vfswrap_get_dos_attributes_getxattr_done,
    1854             :                                         req);
    1855           0 :                 return;
    1856             :         }
    1857             : 
    1858       40026 :         blob.length = xattr_size;
    1859             : 
    1860       40026 :         status = parse_dos_attribute_blob(state->smb_fname,
    1861             :                                           blob,
    1862             :                                           &state->dosmode);
    1863       40026 :         if (!NT_STATUS_IS_OK(status)) {
    1864           0 :                 tevent_req_nterror(req, status);
    1865           0 :                 return;
    1866             :         }
    1867             : 
    1868       40026 :         pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
    1869       40026 :                                 state->smb_fname->base_name,
    1870             :                                 pathbuf,
    1871             :                                 sizeof(pathbuf),
    1872             :                                 &path,
    1873             :                                 &tofree);
    1874       40026 :         if (pathlen == -1) {
    1875           0 :                 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
    1876           0 :                 return;
    1877             :         }
    1878             : 
    1879       80052 :         smb_fname = (struct smb_filename) {
    1880             :                 .base_name = path,
    1881       40026 :                 .st = state->smb_fname->st,
    1882       40026 :                 .flags = state->smb_fname->flags,
    1883       40026 :                 .twrp = state->smb_fname->twrp,
    1884             :         };
    1885             : 
    1886       40026 :         offline = vfswrap_is_offline(state->conn, &smb_fname);
    1887       40026 :         if (offline) {
    1888           0 :                 state->dosmode |= FILE_ATTRIBUTE_OFFLINE;
    1889             :         }
    1890       40026 :         TALLOC_FREE(tofree);
    1891             : 
    1892       40026 :         tevent_req_done(req);
    1893       40026 :         return;
    1894             : }
    1895             : 
    1896       40234 : static NTSTATUS vfswrap_get_dos_attributes_recv(struct tevent_req *req,
    1897             :                                                 struct vfs_aio_state *aio_state,
    1898             :                                                 uint32_t *dosmode)
    1899             : {
    1900       40234 :         struct vfswrap_get_dos_attributes_state *state =
    1901       40234 :                 tevent_req_data(req,
    1902             :                 struct vfswrap_get_dos_attributes_state);
    1903             :         NTSTATUS status;
    1904             : 
    1905       40234 :         if (tevent_req_is_nterror(req, &status)) {
    1906         208 :                 tevent_req_received(req);
    1907         208 :                 return status;
    1908             :         }
    1909             : 
    1910       40026 :         *aio_state = state->aio_state;
    1911       40026 :         *dosmode = state->dosmode;
    1912       40026 :         tevent_req_received(req);
    1913       40026 :         return NT_STATUS_OK;
    1914             : }
    1915             : 
    1916     1335547 : static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
    1917             :                                             struct files_struct *fsp,
    1918             :                                             uint32_t *dosmode)
    1919             : {
    1920             :         bool offline;
    1921             : 
    1922     1335547 :         offline = vfswrap_is_offline(handle->conn, fsp->fsp_name);
    1923     1335547 :         if (offline) {
    1924           0 :                 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
    1925             :         }
    1926             : 
    1927     1335547 :         return fget_ea_dos_attribute(fsp, dosmode);
    1928             : }
    1929             : 
    1930      188811 : static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
    1931             :                                             struct files_struct *fsp,
    1932             :                                             uint32_t dosmode)
    1933             : {
    1934      188811 :         return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
    1935             : }
    1936             : 
    1937             : static struct vfs_offload_ctx *vfswrap_offload_ctx;
    1938             : 
    1939             : struct vfswrap_offload_read_state {
    1940             :         DATA_BLOB token;
    1941             : };
    1942             : 
    1943         220 : static struct tevent_req *vfswrap_offload_read_send(
    1944             :         TALLOC_CTX *mem_ctx,
    1945             :         struct tevent_context *ev,
    1946             :         struct vfs_handle_struct *handle,
    1947             :         struct files_struct *fsp,
    1948             :         uint32_t fsctl,
    1949             :         uint32_t ttl,
    1950             :         off_t offset,
    1951             :         size_t to_copy)
    1952             : {
    1953         220 :         struct tevent_req *req = NULL;
    1954         220 :         struct vfswrap_offload_read_state *state = NULL;
    1955             :         NTSTATUS status;
    1956             : 
    1957         220 :         req = tevent_req_create(mem_ctx, &state,
    1958             :                                 struct vfswrap_offload_read_state);
    1959         220 :         if (req == NULL) {
    1960           0 :                 return NULL;
    1961             :         }
    1962             : 
    1963         220 :         status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
    1964             :                                             &vfswrap_offload_ctx);
    1965         220 :         if (tevent_req_nterror(req, status)) {
    1966           0 :                 return tevent_req_post(req, ev);
    1967             :         }
    1968             : 
    1969         220 :         if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
    1970           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
    1971           0 :                 return tevent_req_post(req, ev);
    1972             :         }
    1973             : 
    1974         220 :         status = vfs_offload_token_create_blob(state, fsp, fsctl,
    1975         220 :                                                &state->token);
    1976         220 :         if (tevent_req_nterror(req, status)) {
    1977           0 :                 return tevent_req_post(req, ev);
    1978             :         }
    1979             : 
    1980         220 :         status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
    1981         220 :                                                 &state->token);
    1982         220 :         if (tevent_req_nterror(req, status)) {
    1983           0 :                 return tevent_req_post(req, ev);
    1984             :         }
    1985             : 
    1986         220 :         tevent_req_done(req);
    1987         220 :         return tevent_req_post(req, ev);
    1988             : }
    1989             : 
    1990         220 : static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
    1991             :                                           struct vfs_handle_struct *handle,
    1992             :                                           TALLOC_CTX *mem_ctx,
    1993             :                                           DATA_BLOB *token)
    1994             : {
    1995         220 :         struct vfswrap_offload_read_state *state = tevent_req_data(
    1996             :                 req, struct vfswrap_offload_read_state);
    1997             :         NTSTATUS status;
    1998             : 
    1999         220 :         if (tevent_req_is_nterror(req, &status)) {
    2000           0 :                 tevent_req_received(req);
    2001           0 :                 return status;
    2002             :         }
    2003             : 
    2004         220 :         token->length = state->token.length;
    2005         220 :         token->data = talloc_move(mem_ctx, &state->token.data);
    2006             : 
    2007         220 :         tevent_req_received(req);
    2008         220 :         return NT_STATUS_OK;
    2009             : }
    2010             : 
    2011             : struct vfswrap_offload_write_state {
    2012             :         uint8_t *buf;
    2013             :         bool read_lck_locked;
    2014             :         bool write_lck_locked;
    2015             :         DATA_BLOB *token;
    2016             :         struct tevent_context *src_ev;
    2017             :         struct files_struct *src_fsp;
    2018             :         off_t src_off;
    2019             :         struct tevent_context *dst_ev;
    2020             :         struct files_struct *dst_fsp;
    2021             :         off_t dst_off;
    2022             :         off_t to_copy;
    2023             :         off_t remaining;
    2024             :         off_t copied;
    2025             :         size_t next_io_size;
    2026             : };
    2027             : 
    2028         488 : static void vfswrap_offload_write_cleanup(struct tevent_req *req,
    2029             :                                           enum tevent_req_state req_state)
    2030             : {
    2031         488 :         struct vfswrap_offload_write_state *state = tevent_req_data(
    2032             :                 req, struct vfswrap_offload_write_state);
    2033             :         bool ok;
    2034             : 
    2035         488 :         if (state->dst_fsp == NULL) {
    2036         390 :                 return;
    2037             :         }
    2038             : 
    2039          98 :         ok = change_to_user_and_service_by_fsp(state->dst_fsp);
    2040          98 :         SMB_ASSERT(ok);
    2041          98 :         state->dst_fsp = NULL;
    2042             : }
    2043             : 
    2044             : static NTSTATUS vfswrap_offload_copy_file_range(struct tevent_req *req);
    2045             : static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
    2046             : 
    2047         244 : static struct tevent_req *vfswrap_offload_write_send(
    2048             :         struct vfs_handle_struct *handle,
    2049             :         TALLOC_CTX *mem_ctx,
    2050             :         struct tevent_context *ev,
    2051             :         uint32_t fsctl,
    2052             :         DATA_BLOB *token,
    2053             :         off_t transfer_offset,
    2054             :         struct files_struct *dest_fsp,
    2055             :         off_t dest_off,
    2056             :         off_t to_copy)
    2057             : {
    2058             :         struct tevent_req *req;
    2059         244 :         struct vfswrap_offload_write_state *state = NULL;
    2060             :         /* off_t is signed! */
    2061         244 :         off_t max_offset = INT64_MAX - to_copy;
    2062         244 :         size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
    2063         244 :         files_struct *src_fsp = NULL;
    2064             :         NTSTATUS status;
    2065             :         bool ok;
    2066             : 
    2067         244 :         req = tevent_req_create(mem_ctx, &state,
    2068             :                                 struct vfswrap_offload_write_state);
    2069         244 :         if (req == NULL) {
    2070           0 :                 return NULL;
    2071             :         }
    2072             : 
    2073         244 :         *state = (struct vfswrap_offload_write_state) {
    2074             :                 .token = token,
    2075             :                 .src_off = transfer_offset,
    2076             :                 .dst_ev = ev,
    2077             :                 .dst_fsp = dest_fsp,
    2078             :                 .dst_off = dest_off,
    2079             :                 .to_copy = to_copy,
    2080             :                 .remaining = to_copy,
    2081             :         };
    2082             : 
    2083         244 :         tevent_req_set_cleanup_fn(req, vfswrap_offload_write_cleanup);
    2084             : 
    2085         244 :         switch (fsctl) {
    2086         244 :         case FSCTL_SRV_COPYCHUNK:
    2087             :         case FSCTL_SRV_COPYCHUNK_WRITE:
    2088         244 :                 break;
    2089             : 
    2090           0 :         case FSCTL_OFFLOAD_WRITE:
    2091           0 :                 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
    2092           0 :                 return tevent_req_post(req, ev);
    2093             : 
    2094           0 :         case FSCTL_DUP_EXTENTS_TO_FILE:
    2095           0 :                 DBG_DEBUG("COW clones not supported by vfs_default\n");
    2096           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
    2097           0 :                 return tevent_req_post(req, ev);
    2098             : 
    2099           0 :         default:
    2100           0 :                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
    2101           0 :                 return tevent_req_post(req, ev);
    2102             :         }
    2103             : 
    2104             :         /*
    2105             :          * From here on we assume a copy-chunk fsctl
    2106             :          */
    2107             : 
    2108         244 :         if (to_copy == 0) {
    2109           8 :                 tevent_req_done(req);
    2110           8 :                 return tevent_req_post(req, ev);
    2111             :         }
    2112             : 
    2113         236 :         if (state->src_off > max_offset) {
    2114             :                 /*
    2115             :                  * Protect integer checks below.
    2116             :                  */
    2117           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
    2118           0 :                 return tevent_req_post(req, ev);
    2119             :         }
    2120         236 :         if (state->src_off < 0) {
    2121             :                 /*
    2122             :                  * Protect integer checks below.
    2123             :                  */
    2124           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
    2125           0 :                 return tevent_req_post(req, ev);
    2126             :         }
    2127         236 :         if (state->dst_off > max_offset) {
    2128             :                 /*
    2129             :                  * Protect integer checks below.
    2130             :                  */
    2131           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
    2132           0 :                 return tevent_req_post(req, ev);
    2133             :         }
    2134         236 :         if (state->dst_off < 0) {
    2135             :                 /*
    2136             :                  * Protect integer checks below.
    2137             :                  */
    2138           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
    2139           0 :                 return tevent_req_post(req, ev);
    2140             :         }
    2141             : 
    2142         236 :         status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
    2143             :                                                 token, &src_fsp);
    2144         236 :         if (tevent_req_nterror(req, status)) {
    2145          12 :                 return tevent_req_post(req, ev);
    2146             :         }
    2147             : 
    2148         224 :         DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
    2149             : 
    2150         224 :         status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
    2151         224 :         if (!NT_STATUS_IS_OK(status)) {
    2152          18 :                 tevent_req_nterror(req, status);
    2153          18 :                 return tevent_req_post(req, ev);
    2154             :         }
    2155             : 
    2156         206 :         ok = change_to_user_and_service_by_fsp(src_fsp);
    2157         206 :         if (!ok) {
    2158           0 :                 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
    2159           0 :                 return tevent_req_post(req, ev);
    2160             :         }
    2161             : 
    2162         206 :         state->src_ev = src_fsp->conn->sconn->ev_ctx;
    2163         206 :         state->src_fsp = src_fsp;
    2164             : 
    2165         206 :         status = vfs_stat_fsp(src_fsp);
    2166         206 :         if (tevent_req_nterror(req, status)) {
    2167           0 :                 return tevent_req_post(req, ev);
    2168             :         }
    2169             : 
    2170         206 :         if (src_fsp->fsp_name->st.st_ex_size < state->src_off + to_copy) {
    2171             :                 /*
    2172             :                  * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
    2173             :                  *   If the SourceOffset or SourceOffset + Length extends beyond
    2174             :                  *   the end of file, the server SHOULD<240> treat this as a
    2175             :                  *   STATUS_END_OF_FILE error.
    2176             :                  * ...
    2177             :                  *   <240> Section 3.3.5.15.6: Windows servers will return
    2178             :                  *   STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
    2179             :                  */
    2180          12 :                 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
    2181          12 :                 return tevent_req_post(req, ev);
    2182             :         }
    2183             : 
    2184         194 :         status = vfswrap_offload_copy_file_range(req);
    2185         194 :         if (NT_STATUS_IS_OK(status)) {
    2186         146 :                 tevent_req_done(req);
    2187         146 :                 return tevent_req_post(req, ev);
    2188             :         }
    2189          48 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
    2190          12 :                 tevent_req_nterror(req, status);
    2191          12 :                 return tevent_req_post(req, ev);
    2192             :         }
    2193             : 
    2194          36 :         state->buf = talloc_array(state, uint8_t, num);
    2195          36 :         if (tevent_req_nomem(state->buf, req)) {
    2196           0 :                 return tevent_req_post(req, ev);
    2197             :         }
    2198             : 
    2199          36 :         status = vfswrap_offload_write_loop(req);
    2200          36 :         if (!NT_STATUS_IS_OK(status)) {
    2201           0 :                 tevent_req_nterror(req, status);
    2202           0 :                 return tevent_req_post(req, ev);
    2203             :         }
    2204             : 
    2205          36 :         return req;
    2206             : }
    2207             : 
    2208         194 : static NTSTATUS vfswrap_offload_copy_file_range(struct tevent_req *req)
    2209             : {
    2210         194 :         struct vfswrap_offload_write_state *state = tevent_req_data(
    2211             :                 req, struct vfswrap_offload_write_state);
    2212             :         struct lock_struct lck;
    2213             :         ssize_t nwritten;
    2214             :         NTSTATUS status;
    2215             :         bool same_file;
    2216             :         bool ok;
    2217             :         static bool try_copy_file_range = true;
    2218             : 
    2219         194 :         if (!try_copy_file_range) {
    2220           0 :                 return NT_STATUS_MORE_PROCESSING_REQUIRED;
    2221             :         }
    2222             : 
    2223         194 :         same_file = file_id_equal(&state->src_fsp->file_id,
    2224         194 :                                   &state->dst_fsp->file_id);
    2225         206 :         if (same_file &&
    2226          22 :             sys_io_ranges_overlap(state->remaining,
    2227             :                                   state->src_off,
    2228          12 :                                   state->remaining,
    2229             :                                   state->dst_off))
    2230             :         {
    2231           6 :                 return NT_STATUS_MORE_PROCESSING_REQUIRED;
    2232             :         }
    2233             : 
    2234         346 :         if (is_named_stream(state->src_fsp->fsp_name) ||
    2235         158 :             is_named_stream(state->dst_fsp->fsp_name))
    2236             :         {
    2237          30 :                 return NT_STATUS_MORE_PROCESSING_REQUIRED;
    2238             :         }
    2239             : 
    2240         424 :         init_strict_lock_struct(state->src_fsp,
    2241         158 :                                 state->src_fsp->op->global->open_persistent_id,
    2242         158 :                                 state->src_off,
    2243         158 :                                 state->remaining,
    2244             :                                 READ_LOCK,
    2245             :                                 &lck);
    2246             : 
    2247         158 :         ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
    2248             :                                  state->src_fsp,
    2249             :                                  &lck);
    2250         158 :         if (!ok) {
    2251           6 :                 return NT_STATUS_FILE_LOCK_CONFLICT;
    2252             :         }
    2253             : 
    2254         152 :         ok = change_to_user_and_service_by_fsp(state->dst_fsp);
    2255         152 :         if (!ok) {
    2256           0 :                 return NT_STATUS_INTERNAL_ERROR;
    2257             :         }
    2258             : 
    2259         408 :         init_strict_lock_struct(state->dst_fsp,
    2260         152 :                                 state->dst_fsp->op->global->open_persistent_id,
    2261         152 :                                 state->dst_off,
    2262         152 :                                 state->remaining,
    2263             :                                 WRITE_LOCK,
    2264             :                                 &lck);
    2265             : 
    2266         152 :         ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
    2267             :                                        state->dst_fsp,
    2268             :                                        &lck);
    2269         152 :         if (!ok) {
    2270           6 :                 return NT_STATUS_FILE_LOCK_CONFLICT;
    2271             :         }
    2272             : 
    2273         415 :         while (state->remaining > 0) {
    2274         392 :                 nwritten = copy_file_range(fsp_get_io_fd(state->src_fsp),
    2275         146 :                                            &state->src_off,
    2276         146 :                                            fsp_get_io_fd(state->dst_fsp),
    2277         146 :                                            &state->dst_off,
    2278         146 :                                            state->remaining,
    2279             :                                            0);
    2280         146 :                 if (nwritten == -1) {
    2281           0 :                         DBG_DEBUG("copy_file_range src [%s]:[%jd] dst [%s]:[%jd] "
    2282             :                                   "n [%jd] failed: %s\n",
    2283             :                                   fsp_str_dbg(state->src_fsp),
    2284             :                                   (intmax_t)state->src_off,
    2285             :                                   fsp_str_dbg(state->dst_fsp),
    2286             :                                   (intmax_t)state->dst_off,
    2287             :                                   (intmax_t)state->remaining,
    2288             :                                   strerror(errno));
    2289           0 :                         switch (errno) {
    2290           0 :                         case EOPNOTSUPP:
    2291             :                         case ENOSYS:
    2292           0 :                                 try_copy_file_range = false;
    2293           0 :                                 status = NT_STATUS_MORE_PROCESSING_REQUIRED;
    2294           0 :                                 break;
    2295           0 :                         case EXDEV:
    2296           0 :                                 status = NT_STATUS_MORE_PROCESSING_REQUIRED;
    2297           0 :                                 break;
    2298           0 :                         default:
    2299           0 :                                 status = map_nt_error_from_unix(errno);
    2300           0 :                                 if (NT_STATUS_EQUAL(
    2301             :                                             status,
    2302             :                                             NT_STATUS_MORE_PROCESSING_REQUIRED))
    2303             :                                 {
    2304             :                                         /* Avoid triggering the fallback */
    2305           0 :                                         status = NT_STATUS_INTERNAL_ERROR;
    2306             :                                 }
    2307           0 :                                 break;
    2308             :                         }
    2309           0 :                         return status;
    2310             :                 }
    2311             : 
    2312         146 :                 if (state->remaining < nwritten) {
    2313           0 :                         DBG_DEBUG("copy_file_range src [%s] dst [%s] "
    2314             :                                   "n [%jd] remaining [%jd]\n",
    2315             :                                   fsp_str_dbg(state->src_fsp),
    2316             :                                   fsp_str_dbg(state->dst_fsp),
    2317             :                                   (intmax_t)nwritten,
    2318             :                                   (intmax_t)state->remaining);
    2319           0 :                         return NT_STATUS_INTERNAL_ERROR;
    2320             :                 }
    2321             : 
    2322         146 :                 if (nwritten == 0) {
    2323           0 :                         break;
    2324             :                 }
    2325         146 :                 state->copied += nwritten;
    2326         146 :                 state->remaining -= nwritten;
    2327             :         }
    2328             : 
    2329             :         /*
    2330             :          * Tell the req cleanup function there's no need to call
    2331             :          * change_to_user_and_service_by_fsp() on the dst handle.
    2332             :          */
    2333         146 :         state->dst_fsp = NULL;
    2334         146 :         return NT_STATUS_OK;
    2335             : }
    2336             : 
    2337             : static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
    2338             : 
    2339          36 : static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
    2340             : {
    2341          36 :         struct vfswrap_offload_write_state *state = tevent_req_data(
    2342             :                 req, struct vfswrap_offload_write_state);
    2343          36 :         struct tevent_req *subreq = NULL;
    2344             :         struct lock_struct read_lck;
    2345             :         bool ok;
    2346             : 
    2347             :         /*
    2348             :          * This is called under the context of state->src_fsp.
    2349             :          */
    2350             : 
    2351          36 :         state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
    2352             : 
    2353         104 :         init_strict_lock_struct(state->src_fsp,
    2354          36 :                                 state->src_fsp->op->global->open_persistent_id,
    2355          36 :                                 state->src_off,
    2356             :                                 state->next_io_size,
    2357             :                                 READ_LOCK,
    2358             :                                 &read_lck);
    2359             : 
    2360          36 :         ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
    2361             :                                  state->src_fsp,
    2362             :                                  &read_lck);
    2363          36 :         if (!ok) {
    2364           0 :                 return NT_STATUS_FILE_LOCK_CONFLICT;
    2365             :         }
    2366             : 
    2367          36 :         subreq = SMB_VFS_PREAD_SEND(state,
    2368             :                                     state->src_ev,
    2369             :                                     state->src_fsp,
    2370             :                                     state->buf,
    2371             :                                     state->next_io_size,
    2372             :                                     state->src_off);
    2373          36 :         if (subreq == NULL) {
    2374           0 :                 return NT_STATUS_NO_MEMORY;
    2375             :         }
    2376          36 :         tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
    2377             : 
    2378          36 :         return NT_STATUS_OK;
    2379             : }
    2380             : 
    2381             : static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
    2382             : 
    2383          36 : static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
    2384             : {
    2385          36 :         struct tevent_req *req = tevent_req_callback_data(
    2386             :                 subreq, struct tevent_req);
    2387          36 :         struct vfswrap_offload_write_state *state = tevent_req_data(
    2388             :                 req, struct vfswrap_offload_write_state);
    2389             :         struct vfs_aio_state aio_state;
    2390             :         struct lock_struct write_lck;
    2391             :         ssize_t nread;
    2392             :         bool ok;
    2393             : 
    2394          36 :         nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
    2395          36 :         TALLOC_FREE(subreq);
    2396          36 :         if (nread == -1) {
    2397           0 :                 DBG_ERR("read failed: %s\n", strerror(aio_state.error));
    2398           0 :                 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
    2399           0 :                 return;
    2400             :         }
    2401          36 :         if (nread != state->next_io_size) {
    2402           0 :                 DBG_ERR("Short read, only %zd of %zu\n",
    2403             :                         nread, state->next_io_size);
    2404           0 :                 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
    2405           0 :                 return;
    2406             :         }
    2407             : 
    2408          36 :         state->src_off += nread;
    2409             : 
    2410          36 :         ok = change_to_user_and_service_by_fsp(state->dst_fsp);
    2411          36 :         if (!ok) {
    2412           0 :                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
    2413           0 :                 return;
    2414             :         }
    2415             : 
    2416         104 :         init_strict_lock_struct(state->dst_fsp,
    2417          36 :                                 state->dst_fsp->op->global->open_persistent_id,
    2418          36 :                                 state->dst_off,
    2419             :                                 state->next_io_size,
    2420             :                                 WRITE_LOCK,
    2421             :                                 &write_lck);
    2422             : 
    2423          36 :         ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
    2424             :                                  state->dst_fsp,
    2425             :                                  &write_lck);
    2426          36 :         if (!ok) {
    2427           0 :                 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
    2428           0 :                 return;
    2429             :         }
    2430             : 
    2431          36 :         subreq = SMB_VFS_PWRITE_SEND(state,
    2432             :                                      state->dst_ev,
    2433             :                                      state->dst_fsp,
    2434             :                                      state->buf,
    2435             :                                      state->next_io_size,
    2436             :                                      state->dst_off);
    2437          36 :         if (subreq == NULL) {
    2438           0 :                 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
    2439           0 :                 return;
    2440             :         }
    2441          36 :         tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
    2442             : }
    2443             : 
    2444          36 : static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
    2445             : {
    2446          36 :         struct tevent_req *req = tevent_req_callback_data(
    2447             :                 subreq, struct tevent_req);
    2448          36 :         struct vfswrap_offload_write_state *state = tevent_req_data(
    2449             :                 req, struct vfswrap_offload_write_state);
    2450             :         struct vfs_aio_state aio_state;
    2451             :         ssize_t nwritten;
    2452             :         NTSTATUS status;
    2453             :         bool ok;
    2454             : 
    2455          36 :         nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
    2456          36 :         TALLOC_FREE(subreq);
    2457          36 :         if (nwritten == -1) {
    2458           0 :                 DBG_ERR("write failed: %s\n", strerror(aio_state.error));
    2459           0 :                 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
    2460           0 :                 return;
    2461             :         }
    2462          36 :         if (nwritten != state->next_io_size) {
    2463           0 :                 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
    2464           0 :                 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
    2465           0 :                 return;
    2466             :         }
    2467             : 
    2468          36 :         state->dst_off += nwritten;
    2469             : 
    2470          36 :         if (state->remaining < nwritten) {
    2471             :                 /* Paranoia check */
    2472           0 :                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
    2473           0 :                 return;
    2474             :         }
    2475          36 :         state->copied += nwritten;
    2476          36 :         state->remaining -= nwritten;
    2477          36 :         if (state->remaining == 0) {
    2478          36 :                 tevent_req_done(req);
    2479          36 :                 return;
    2480             :         }
    2481             : 
    2482           0 :         ok = change_to_user_and_service_by_fsp(state->src_fsp);
    2483           0 :         if (!ok) {
    2484           0 :                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
    2485           0 :                 return;
    2486             :         }
    2487             : 
    2488           0 :         status = vfswrap_offload_write_loop(req);
    2489           0 :         if (!NT_STATUS_IS_OK(status)) {
    2490           0 :                 tevent_req_nterror(req, status);
    2491           0 :                 return;
    2492             :         }
    2493             : 
    2494           0 :         return;
    2495             : }
    2496             : 
    2497         244 : static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
    2498             :                                         struct tevent_req *req,
    2499             :                                         off_t *copied)
    2500             : {
    2501         244 :         struct vfswrap_offload_write_state *state = tevent_req_data(
    2502             :                 req, struct vfswrap_offload_write_state);
    2503             :         NTSTATUS status;
    2504             : 
    2505         244 :         if (tevent_req_is_nterror(req, &status)) {
    2506          54 :                 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
    2507          54 :                 *copied = 0;
    2508          54 :                 tevent_req_received(req);
    2509          54 :                 return status;
    2510             :         }
    2511             : 
    2512         190 :         *copied = state->copied;
    2513         190 :         DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
    2514         190 :         tevent_req_received(req);
    2515             : 
    2516         190 :         return NT_STATUS_OK;
    2517             : }
    2518             : 
    2519           0 : static NTSTATUS vfswrap_fget_compression(struct vfs_handle_struct *handle,
    2520             :                                         TALLOC_CTX *mem_ctx,
    2521             :                                         struct files_struct *fsp,
    2522             :                                         uint16_t *_compression_fmt)
    2523             : {
    2524           0 :         return NT_STATUS_INVALID_DEVICE_REQUEST;
    2525             : }
    2526             : 
    2527           0 : static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
    2528             :                                         TALLOC_CTX *mem_ctx,
    2529             :                                         struct files_struct *fsp,
    2530             :                                         uint16_t compression_fmt)
    2531             : {
    2532           0 :         return NT_STATUS_INVALID_DEVICE_REQUEST;
    2533             : }
    2534             : 
    2535             : /********************************************************************
    2536             :  Given a stat buffer return the allocated size on disk, taking into
    2537             :  account sparse files.
    2538             : ********************************************************************/
    2539     1277988 : static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
    2540             :                                        struct files_struct *fsp,
    2541             :                                        const SMB_STRUCT_STAT *sbuf)
    2542             : {
    2543             :         uint64_t result;
    2544             : 
    2545     1277988 :         START_PROFILE(syscall_get_alloc_size);
    2546             : 
    2547     1277988 :         if(S_ISDIR(sbuf->st_ex_mode)) {
    2548       94180 :                 result = 0;
    2549       94180 :                 goto out;
    2550             :         }
    2551             : 
    2552             : #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
    2553             :         /* The type of st_blocksize is blkcnt_t which *MUST* be
    2554             :            signed (according to POSIX) and can be less than 64-bits.
    2555             :            Ensure when we're converting to 64 bits wide we don't
    2556             :            sign extend. */
    2557             : #if defined(SIZEOF_BLKCNT_T_8)
    2558     1183447 :         result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
    2559             : #elif defined(SIZEOF_BLKCNT_T_4)
    2560             :         {
    2561             :                 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
    2562             :                 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
    2563             :         }
    2564             : #else
    2565             : #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
    2566             : #endif
    2567     1183447 :         if (result == 0) {
    2568             :                 /*
    2569             :                  * Some file systems do not allocate a block for very
    2570             :                  * small files. But for non-empty file should report a
    2571             :                  * positive size.
    2572             :                  */
    2573             : 
    2574     1121585 :                 uint64_t filesize = get_file_size_stat(sbuf);
    2575     1121585 :                 if (filesize > 0) {
    2576        1073 :                         result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
    2577             :                 }
    2578             :         }
    2579             : #else
    2580             :         result = get_file_size_stat(sbuf);
    2581             : #endif
    2582             : 
    2583     1183447 :         if (fsp && fsp->initial_allocation_size)
    2584        2530 :                 result = MAX(result,fsp->initial_allocation_size);
    2585             : 
    2586     1183447 :         result = smb_roundup(handle->conn, result);
    2587             : 
    2588     1277988 :  out:
    2589     1277988 :         END_PROFILE(syscall_get_alloc_size);
    2590     1277988 :         return result;
    2591             : }
    2592             : 
    2593      184628 : static int vfswrap_unlinkat(vfs_handle_struct *handle,
    2594             :                         struct files_struct *dirfsp,
    2595             :                         const struct smb_filename *smb_fname,
    2596             :                         int flags)
    2597             : {
    2598      184628 :         int result = -1;
    2599             : 
    2600      184628 :         START_PROFILE(syscall_unlinkat);
    2601             : 
    2602      184628 :         if (is_named_stream(smb_fname)) {
    2603           0 :                 errno = ENOENT;
    2604           0 :                 goto out;
    2605             :         }
    2606      184628 :         result = unlinkat(fsp_get_pathref_fd(dirfsp),
    2607      184628 :                         smb_fname->base_name,
    2608             :                         flags);
    2609             : 
    2610      184628 :  out:
    2611      184628 :         END_PROFILE(syscall_unlinkat);
    2612      184628 :         return result;
    2613             : }
    2614             : 
    2615          12 : static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
    2616             : {
    2617             :         int result;
    2618             : 
    2619          12 :         START_PROFILE(syscall_fchmod);
    2620             : 
    2621          12 :         if (!fsp->fsp_flags.is_pathref) {
    2622           0 :                 result = fchmod(fsp_get_io_fd(fsp), mode);
    2623           0 :                 END_PROFILE(syscall_fchmod);
    2624           0 :                 return result;
    2625             :         }
    2626             : 
    2627          12 :         if (fsp->fsp_flags.have_proc_fds) {
    2628          12 :                 int fd = fsp_get_pathref_fd(fsp);
    2629          12 :                 const char *p = NULL;
    2630             :                 char buf[PATH_MAX];
    2631             : 
    2632          12 :                 p = sys_proc_fd_path(fd, buf, sizeof(buf));
    2633          12 :                 if (p != NULL) {
    2634          12 :                         result = chmod(p, mode);
    2635             :                 } else {
    2636           0 :                         result = -1;
    2637             :                 }
    2638          12 :                 END_PROFILE(syscall_fchmod);
    2639          12 :                 return result;
    2640             :         }
    2641             : 
    2642             :         /*
    2643             :          * This is no longer a handle based call.
    2644             :          */
    2645           0 :         result = chmod(fsp->fsp_name->base_name, mode);
    2646             : 
    2647           0 :         END_PROFILE(syscall_fchmod);
    2648           0 :         return result;
    2649             : }
    2650             : 
    2651        2492 : static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
    2652             : {
    2653             : #ifdef HAVE_FCHOWN
    2654             :         int result;
    2655             : 
    2656        2492 :         START_PROFILE(syscall_fchown);
    2657        2492 :         if (!fsp->fsp_flags.is_pathref) {
    2658        2492 :                 result = fchown(fsp_get_io_fd(fsp), uid, gid);
    2659        2492 :                 END_PROFILE(syscall_fchown);
    2660        2492 :                 return result;
    2661             :         }
    2662             : 
    2663           0 :         if (fsp->fsp_flags.have_proc_fds) {
    2664           0 :                 int fd = fsp_get_pathref_fd(fsp);
    2665           0 :                 const char *p = NULL;
    2666             :                 char buf[PATH_MAX];
    2667             : 
    2668           0 :                 p = sys_proc_fd_path(fd, buf, sizeof(buf));
    2669           0 :                 if (p != NULL) {
    2670           0 :                         result = chown(p, uid, gid);
    2671             :                 } else {
    2672           0 :                         result = -1;
    2673             :                 }
    2674           0 :                 END_PROFILE(syscall_fchown);
    2675           0 :                 return result;
    2676             :         }
    2677             : 
    2678             :         /*
    2679             :          * This is no longer a handle based call.
    2680             :          */
    2681           0 :         result = chown(fsp->fsp_name->base_name, uid, gid);
    2682           0 :         END_PROFILE(syscall_fchown);
    2683           0 :         return result;
    2684             : #else
    2685             :         errno = ENOSYS;
    2686             :         return -1;
    2687             : #endif
    2688             : }
    2689             : 
    2690           0 : static int vfswrap_lchown(vfs_handle_struct *handle,
    2691             :                         const struct smb_filename *smb_fname,
    2692             :                         uid_t uid,
    2693             :                         gid_t gid)
    2694             : {
    2695             :         int result;
    2696             : 
    2697           0 :         START_PROFILE(syscall_lchown);
    2698           0 :         result = lchown(smb_fname->base_name, uid, gid);
    2699           0 :         END_PROFILE(syscall_lchown);
    2700           0 :         return result;
    2701             : }
    2702             : 
    2703     7913514 : static int vfswrap_chdir(vfs_handle_struct *handle,
    2704             :                         const struct smb_filename *smb_fname)
    2705             : {
    2706             :         int result;
    2707             : 
    2708     7913514 :         START_PROFILE(syscall_chdir);
    2709     7913514 :         result = chdir(smb_fname->base_name);
    2710     7913514 :         END_PROFILE(syscall_chdir);
    2711     7913514 :         return result;
    2712             : }
    2713             : 
    2714      163879 : static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
    2715             :                                 TALLOC_CTX *ctx)
    2716             : {
    2717             :         char *result;
    2718      163879 :         struct smb_filename *smb_fname = NULL;
    2719             : 
    2720      163879 :         START_PROFILE(syscall_getwd);
    2721      163879 :         result = sys_getwd();
    2722      163879 :         END_PROFILE(syscall_getwd);
    2723             : 
    2724      163879 :         if (result == NULL) {
    2725           0 :                 return NULL;
    2726             :         }
    2727      163879 :         smb_fname = synthetic_smb_fname(ctx,
    2728             :                                 result,
    2729             :                                 NULL,
    2730             :                                 NULL,
    2731             :                                 0,
    2732             :                                 0);
    2733             :         /*
    2734             :          * sys_getwd() *always* returns malloced memory.
    2735             :          * We must free here to avoid leaks:
    2736             :          * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
    2737             :          */
    2738      163879 :         SAFE_FREE(result);
    2739      163879 :         return smb_fname;
    2740             : }
    2741             : 
    2742             : /*********************************************************************
    2743             :  nsec timestamp resolution call. Convert down to whatever the underlying
    2744             :  system will support.
    2745             : **********************************************************************/
    2746             : 
    2747       10601 : static int vfswrap_fntimes(vfs_handle_struct *handle,
    2748             :                            files_struct *fsp,
    2749             :                            struct smb_file_time *ft)
    2750             : {
    2751       10601 :         int result = -1;
    2752             :         struct timespec ts[2];
    2753       10601 :         struct timespec *times = NULL;
    2754             : 
    2755       10601 :         START_PROFILE(syscall_fntimes);
    2756             : 
    2757       10601 :         if (is_named_stream(fsp->fsp_name)) {
    2758           0 :                 errno = ENOENT;
    2759           0 :                 goto out;
    2760             :         }
    2761             : 
    2762       10601 :         if (ft != NULL) {
    2763       10601 :                 if (is_omit_timespec(&ft->atime)) {
    2764        9698 :                         ft->atime = fsp->fsp_name->st.st_ex_atime;
    2765             :                 }
    2766             : 
    2767       10601 :                 if (is_omit_timespec(&ft->mtime)) {
    2768        3061 :                         ft->mtime = fsp->fsp_name->st.st_ex_mtime;
    2769             :                 }
    2770             : 
    2771       10601 :                 if (!is_omit_timespec(&ft->create_time)) {
    2772         836 :                         set_create_timespec_ea(fsp,
    2773             :                                                ft->create_time);
    2774             :                 }
    2775             : 
    2776       10601 :                 if ((timespec_compare(&ft->atime,
    2777       20338 :                                       &fsp->fsp_name->st.st_ex_atime) == 0) &&
    2778        9737 :                     (timespec_compare(&ft->mtime,
    2779        9737 :                                       &fsp->fsp_name->st.st_ex_mtime) == 0)) {
    2780        3628 :                         result = 0;
    2781        3628 :                         goto out;
    2782             :                 }
    2783             : 
    2784        6912 :                 ts[0] = ft->atime;
    2785        6912 :                 ts[1] = ft->mtime;
    2786        6912 :                 times = ts;
    2787             :         } else {
    2788           0 :                 times = NULL;
    2789             :         }
    2790             : 
    2791        6912 :         if (!fsp->fsp_flags.is_pathref) {
    2792        4725 :                 result = futimens(fsp_get_io_fd(fsp), times);
    2793        4725 :                 goto out;
    2794             :         }
    2795             : 
    2796        2187 :         if (fsp->fsp_flags.have_proc_fds) {
    2797        2187 :                 int fd = fsp_get_pathref_fd(fsp);
    2798        2187 :                 const char *p = NULL;
    2799             :                 char buf[PATH_MAX];
    2800             : 
    2801        2187 :                 p = sys_proc_fd_path(fd, buf, sizeof(buf));
    2802        2187 :                 if (p != NULL) {
    2803             :                         /*
    2804             :                          * The dirfd argument of utimensat is ignored when
    2805             :                          * pathname is an absolute path
    2806             :                          */
    2807        2187 :                         result = utimensat(AT_FDCWD, p, times, 0);
    2808             :                 } else {
    2809           0 :                         result = -1;
    2810             :                 }
    2811             : 
    2812        2186 :                 goto out;
    2813             :         }
    2814             : 
    2815             :         /*
    2816             :          * The fd is a pathref (opened with O_PATH) and there isn't fd to
    2817             :          * path translation mechanism. Fallback to path based call.
    2818             :          */
    2819           0 :         result = utimensat(AT_FDCWD, fsp->fsp_name->base_name, times, 0);
    2820             : 
    2821       10601 : out:
    2822       10601 :         END_PROFILE(syscall_fntimes);
    2823             : 
    2824       10601 :         return result;
    2825             : }
    2826             : 
    2827             : 
    2828             : /*********************************************************************
    2829             :  A version of ftruncate that will write the space on disk if strict
    2830             :  allocate is set.
    2831             : **********************************************************************/
    2832             : 
    2833           0 : static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
    2834             : {
    2835             :         off_t space_to_write;
    2836             :         uint64_t space_avail;
    2837             :         uint64_t bsize,dfree,dsize;
    2838             :         int ret;
    2839             :         NTSTATUS status;
    2840             :         SMB_STRUCT_STAT *pst;
    2841             :         bool ok;
    2842             : 
    2843           0 :         ok = vfs_valid_pwrite_range(len, 0);
    2844           0 :         if (!ok) {
    2845           0 :                 errno = EINVAL;
    2846           0 :                 return -1;
    2847             :         }
    2848             : 
    2849           0 :         status = vfs_stat_fsp(fsp);
    2850           0 :         if (!NT_STATUS_IS_OK(status)) {
    2851           0 :                 return -1;
    2852             :         }
    2853           0 :         pst = &fsp->fsp_name->st;
    2854             : 
    2855             : #ifdef S_ISFIFO
    2856           0 :         if (S_ISFIFO(pst->st_ex_mode))
    2857           0 :                 return 0;
    2858             : #endif
    2859             : 
    2860           0 :         if (pst->st_ex_size == len)
    2861           0 :                 return 0;
    2862             : 
    2863             :         /* Shrink - just ftruncate. */
    2864           0 :         if (pst->st_ex_size > len)
    2865           0 :                 return ftruncate(fsp_get_io_fd(fsp), len);
    2866             : 
    2867           0 :         space_to_write = len - pst->st_ex_size;
    2868             : 
    2869             :         /* for allocation try fallocate first. This can fail on some
    2870             :            platforms e.g. when the filesystem doesn't support it and no
    2871             :            emulation is being done by the libc (like on AIX with JFS1). In that
    2872             :            case we do our own emulation. fallocate implementations can
    2873             :            return ENOTSUP or EINVAL in cases like that. */
    2874           0 :         ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
    2875           0 :         if (ret == -1 && errno == ENOSPC) {
    2876           0 :                 return -1;
    2877             :         }
    2878           0 :         if (ret == 0) {
    2879           0 :                 return 0;
    2880             :         }
    2881           0 :         DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
    2882             :                 "error %d. Falling back to slow manual allocation\n", errno));
    2883             : 
    2884             :         /* available disk space is enough or not? */
    2885           0 :         space_avail =
    2886           0 :             get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
    2887             :         /* space_avail is 1k blocks */
    2888           0 :         if (space_avail == (uint64_t)-1 ||
    2889           0 :                         ((uint64_t)space_to_write/1024 > space_avail) ) {
    2890           0 :                 errno = ENOSPC;
    2891           0 :                 return -1;
    2892             :         }
    2893             : 
    2894             :         /* Write out the real space on disk. */
    2895           0 :         ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
    2896           0 :         if (ret != 0) {
    2897           0 :                 return -1;
    2898             :         }
    2899             : 
    2900           0 :         return 0;
    2901             : }
    2902             : 
    2903         969 : static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
    2904             : {
    2905         969 :         int result = -1;
    2906             :         SMB_STRUCT_STAT *pst;
    2907             :         NTSTATUS status;
    2908         969 :         char c = 0;
    2909             : 
    2910         969 :         START_PROFILE(syscall_ftruncate);
    2911             : 
    2912         969 :         if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->fsp_flags.is_sparse) {
    2913           0 :                 result = strict_allocate_ftruncate(handle, fsp, len);
    2914           0 :                 END_PROFILE(syscall_ftruncate);
    2915           0 :                 return result;
    2916             :         }
    2917             : 
    2918             :         /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
    2919             :            ftruncate if the system supports it. Then I discovered that
    2920             :            you can have some filesystems that support ftruncate
    2921             :            expansion and some that don't! On Linux fat can't do
    2922             :            ftruncate extend but ext2 can. */
    2923             : 
    2924         969 :         result = ftruncate(fsp_get_io_fd(fsp), len);
    2925             : 
    2926             :         /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
    2927             :            extend a file with ftruncate. Provide alternate implementation
    2928             :            for this */
    2929             : 
    2930             :         /* Do an fstat to see if the file is longer than the requested
    2931             :            size in which case the ftruncate above should have
    2932             :            succeeded or shorter, in which case seek to len - 1 and
    2933             :            write 1 byte of zero */
    2934         969 :         status = vfs_stat_fsp(fsp);
    2935         969 :         if (!NT_STATUS_IS_OK(status)) {
    2936           0 :                 goto done;
    2937             :         }
    2938             : 
    2939             :         /* We need to update the files_struct after successful ftruncate */
    2940         969 :         if (result == 0) {
    2941         914 :                 goto done;
    2942             :         }
    2943             : 
    2944           0 :         pst = &fsp->fsp_name->st;
    2945             : 
    2946             : #ifdef S_ISFIFO
    2947           0 :         if (S_ISFIFO(pst->st_ex_mode)) {
    2948           0 :                 result = 0;
    2949           0 :                 goto done;
    2950             :         }
    2951             : #endif
    2952             : 
    2953           0 :         if (pst->st_ex_size == len) {
    2954           0 :                 result = 0;
    2955           0 :                 goto done;
    2956             :         }
    2957             : 
    2958           0 :         if (pst->st_ex_size > len) {
    2959             :                 /* the ftruncate should have worked */
    2960           0 :                 goto done;
    2961             :         }
    2962             : 
    2963           0 :         if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
    2964           0 :                 goto done;
    2965             :         }
    2966             : 
    2967           0 :         result = 0;
    2968             : 
    2969        1024 :   done:
    2970             : 
    2971         969 :         END_PROFILE(syscall_ftruncate);
    2972         914 :         return result;
    2973             : }
    2974             : 
    2975         140 : static int vfswrap_fallocate(vfs_handle_struct *handle,
    2976             :                         files_struct *fsp,
    2977             :                         uint32_t mode,
    2978             :                         off_t offset,
    2979             :                         off_t len)
    2980             : {
    2981             :         int result;
    2982             : 
    2983         140 :         START_PROFILE(syscall_fallocate);
    2984         140 :         if (mode == 0) {
    2985           0 :                 result = sys_posix_fallocate(fsp_get_io_fd(fsp), offset, len);
    2986             :                 /*
    2987             :                  * posix_fallocate returns 0 on success, errno on error
    2988             :                  * and doesn't set errno. Make it behave like fallocate()
    2989             :                  * which returns -1, and sets errno on failure.
    2990             :                  */
    2991           0 :                 if (result != 0) {
    2992           0 :                         errno = result;
    2993           0 :                         result = -1;
    2994             :                 }
    2995             :         } else {
    2996             :                 /* sys_fallocate handles filtering of unsupported mode flags */
    2997         140 :                 result = sys_fallocate(fsp_get_io_fd(fsp), mode, offset, len);
    2998             :         }
    2999         140 :         END_PROFILE(syscall_fallocate);
    3000         140 :         return result;
    3001             : }
    3002             : 
    3003        5664 : static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
    3004             : {
    3005             :         bool result;
    3006             : 
    3007        5664 :         START_PROFILE(syscall_fcntl_lock);
    3008             : 
    3009        5664 :         if (fsp->fsp_flags.use_ofd_locks) {
    3010        5664 :                 op = map_process_lock_to_ofd_lock(op);
    3011             :         }
    3012             : 
    3013        5664 :         result =  fcntl_lock(fsp_get_io_fd(fsp), op, offset, count, type);
    3014        5664 :         END_PROFILE(syscall_fcntl_lock);
    3015        5664 :         return result;
    3016             : }
    3017             : 
    3018           0 : static int vfswrap_filesystem_sharemode(vfs_handle_struct *handle,
    3019             :                                         files_struct *fsp,
    3020             :                                         uint32_t share_access,
    3021             :                                         uint32_t access_mask)
    3022             : {
    3023           0 :         errno = ENOTSUP;
    3024           0 :         return -1;
    3025             : }
    3026             : 
    3027      407492 : static int vfswrap_fcntl(vfs_handle_struct *handle, files_struct *fsp, int cmd,
    3028             :                          va_list cmd_arg)
    3029             : {
    3030             :         void *argp;
    3031             :         va_list dup_cmd_arg;
    3032             :         int result;
    3033             :         int val;
    3034             : 
    3035      407492 :         START_PROFILE(syscall_fcntl);
    3036             : 
    3037      407492 :         va_copy(dup_cmd_arg, cmd_arg);
    3038             : 
    3039      407492 :         switch(cmd) {
    3040           0 :         case F_SETLK:
    3041             :         case F_SETLKW:
    3042             :         case F_GETLK:
    3043             : #if defined(HAVE_OFD_LOCKS)
    3044             :         case F_OFD_SETLK:
    3045             :         case F_OFD_SETLKW:
    3046             :         case F_OFD_GETLK:
    3047             : #endif
    3048             : #if defined(HAVE_F_OWNER_EX)
    3049             :         case F_GETOWN_EX:
    3050             :         case F_SETOWN_EX:
    3051             : #endif
    3052             : #if defined(HAVE_RW_HINTS)
    3053             :         case F_GET_RW_HINT:
    3054             :         case F_SET_RW_HINT:
    3055             :         case F_GET_FILE_RW_HINT:
    3056             :         case F_SET_FILE_RW_HINT:
    3057             : #endif
    3058           0 :                 argp = va_arg(dup_cmd_arg, void *);
    3059           0 :                 result = sys_fcntl_ptr(fsp_get_io_fd(fsp), cmd, argp);
    3060           0 :                 break;
    3061      407492 :         default:
    3062      407492 :                 val = va_arg(dup_cmd_arg, int);
    3063      407492 :                 result = sys_fcntl_int(fsp_get_io_fd(fsp), cmd, val);
    3064             :         }
    3065             : 
    3066      407492 :         va_end(dup_cmd_arg);
    3067             : 
    3068      407492 :         END_PROFILE(syscall_fcntl);
    3069      407492 :         return result;
    3070             : }
    3071             : 
    3072      186747 : static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
    3073             : {
    3074             :         bool result;
    3075      186747 :         int op = F_GETLK;
    3076             : 
    3077      186747 :         START_PROFILE(syscall_fcntl_getlock);
    3078             : 
    3079      186747 :         if (fsp->fsp_flags.use_ofd_locks) {
    3080      186747 :                 op = map_process_lock_to_ofd_lock(op);
    3081             :         }
    3082             : 
    3083      186747 :         result = fcntl_getlock(fsp_get_io_fd(fsp), op, poffset, pcount, ptype, ppid);
    3084      186747 :         END_PROFILE(syscall_fcntl_getlock);
    3085      186747 :         return result;
    3086             : }
    3087             : 
    3088          12 : static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
    3089             :                                 int leasetype)
    3090             : {
    3091          12 :         int result = -1;
    3092             : 
    3093          12 :         START_PROFILE(syscall_linux_setlease);
    3094             : 
    3095             : #ifdef HAVE_KERNEL_OPLOCKS_LINUX
    3096          12 :         result = linux_setlease(fsp_get_io_fd(fsp), leasetype);
    3097             : #else
    3098             :         errno = ENOSYS;
    3099             : #endif
    3100          12 :         END_PROFILE(syscall_linux_setlease);
    3101          12 :         return result;
    3102             : }
    3103             : 
    3104         118 : static int vfswrap_symlinkat(vfs_handle_struct *handle,
    3105             :                         const struct smb_filename *link_target,
    3106             :                         struct files_struct *dirfsp,
    3107             :                         const struct smb_filename *new_smb_fname)
    3108             : {
    3109             :         int result;
    3110             : 
    3111         118 :         START_PROFILE(syscall_symlinkat);
    3112             : 
    3113         118 :         result = symlinkat(link_target->base_name,
    3114             :                         fsp_get_pathref_fd(dirfsp),
    3115         118 :                         new_smb_fname->base_name);
    3116         118 :         END_PROFILE(syscall_symlinkat);
    3117         118 :         return result;
    3118             : }
    3119             : 
    3120        1384 : static int vfswrap_readlinkat(vfs_handle_struct *handle,
    3121             :                         const struct files_struct *dirfsp,
    3122             :                         const struct smb_filename *smb_fname,
    3123             :                         char *buf,
    3124             :                         size_t bufsiz)
    3125             : {
    3126             :         int result;
    3127             : 
    3128        1384 :         START_PROFILE(syscall_readlinkat);
    3129             : 
    3130        1384 :         result = readlinkat(fsp_get_pathref_fd(dirfsp),
    3131        1384 :                         smb_fname->base_name,
    3132             :                         buf,
    3133             :                         bufsiz);
    3134             : 
    3135        1384 :         END_PROFILE(syscall_readlinkat);
    3136        1384 :         return result;
    3137             : }
    3138             : 
    3139          21 : static int vfswrap_linkat(vfs_handle_struct *handle,
    3140             :                         files_struct *srcfsp,
    3141             :                         const struct smb_filename *old_smb_fname,
    3142             :                         files_struct *dstfsp,
    3143             :                         const struct smb_filename *new_smb_fname,
    3144             :                         int flags)
    3145             : {
    3146             :         int result;
    3147             : 
    3148          21 :         START_PROFILE(syscall_linkat);
    3149             : 
    3150          41 :         result = linkat(fsp_get_pathref_fd(srcfsp),
    3151          21 :                         old_smb_fname->base_name,
    3152             :                         fsp_get_pathref_fd(dstfsp),
    3153          21 :                         new_smb_fname->base_name,
    3154             :                         flags);
    3155             : 
    3156          21 :         END_PROFILE(syscall_linkat);
    3157          21 :         return result;
    3158             : }
    3159             : 
    3160           0 : static int vfswrap_mknodat(vfs_handle_struct *handle,
    3161             :                         files_struct *dirfsp,
    3162             :                         const struct smb_filename *smb_fname,
    3163             :                         mode_t mode,
    3164             :                         SMB_DEV_T dev)
    3165             : {
    3166             :         int result;
    3167             : 
    3168           0 :         START_PROFILE(syscall_mknodat);
    3169             : 
    3170           0 :         result = sys_mknodat(fsp_get_pathref_fd(dirfsp),
    3171           0 :                         smb_fname->base_name,
    3172             :                         mode,
    3173             :                         dev);
    3174             : 
    3175           0 :         END_PROFILE(syscall_mknodat);
    3176           0 :         return result;
    3177             : }
    3178             : 
    3179    11121798 : static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
    3180             :                         TALLOC_CTX *ctx,
    3181             :                         const struct smb_filename *smb_fname)
    3182             : {
    3183             :         char *result;
    3184    11121798 :         struct smb_filename *result_fname = NULL;
    3185             : 
    3186    11121798 :         START_PROFILE(syscall_realpath);
    3187    11121798 :         result = sys_realpath(smb_fname->base_name);
    3188    11121798 :         END_PROFILE(syscall_realpath);
    3189    11121798 :         if (result) {
    3190    10645817 :                 result_fname = synthetic_smb_fname(ctx,
    3191             :                                                    result,
    3192             :                                                    NULL,
    3193             :                                                    NULL,
    3194             :                                                    0,
    3195             :                                                    0);
    3196    10645817 :                 SAFE_FREE(result);
    3197             :         }
    3198    11121798 :         return result_fname;
    3199             : }
    3200             : 
    3201           0 : static int vfswrap_fchflags(vfs_handle_struct *handle,
    3202             :                         struct files_struct *fsp,
    3203             :                         unsigned int flags)
    3204             : {
    3205             : #ifdef HAVE_FCHFLAGS
    3206             :         int fd = fsp_get_pathref_fd(fsp);
    3207             : 
    3208             :         if (!fsp->fsp_flags.is_pathref) {
    3209             :                 return fchflags(fd, flags);
    3210             :         }
    3211             : 
    3212             :         if (fsp->fsp_flags.have_proc_fds) {
    3213             :                 const char *p = NULL;
    3214             :                 char buf[PATH_MAX];
    3215             : 
    3216             :                 p = sys_proc_fd_path(fd, buf, sizeof(buf));
    3217             :                 if (p == NULL) {
    3218             :                         return -1;
    3219             :                 }
    3220             : 
    3221             :                 return chflags(p, flags);
    3222             :         }
    3223             : 
    3224             :         /*
    3225             :          * This is no longer a handle based call.
    3226             :          */
    3227             :         return chflags(fsp->fsp_name->base_name, flags);
    3228             : #else
    3229           0 :         errno = ENOSYS;
    3230           0 :         return -1;
    3231             : #endif
    3232             : }
    3233             : 
    3234    76240237 : static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
    3235             :                                              const SMB_STRUCT_STAT *sbuf)
    3236             : {
    3237             :         struct file_id key;
    3238             : 
    3239             :         /* the ZERO_STRUCT ensures padding doesn't break using the key as a
    3240             :          * blob */
    3241    76240237 :         ZERO_STRUCT(key);
    3242             : 
    3243    76240237 :         key.devid = sbuf->st_ex_dev;
    3244    76240237 :         key.inode = sbuf->st_ex_ino;
    3245             :         /* key.extid is unused by default. */
    3246             : 
    3247    76240237 :         return key;
    3248             : }
    3249             : 
    3250      519329 : static uint64_t vfswrap_fs_file_id(struct vfs_handle_struct *handle,
    3251             :                                    const SMB_STRUCT_STAT *psbuf)
    3252             : {
    3253             :         uint64_t file_id;
    3254             : 
    3255      519329 :         if (!(psbuf->st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)) {
    3256      439243 :                 return psbuf->st_ex_file_id;
    3257             :         }
    3258             : 
    3259       80086 :         if (handle->conn->base_share_dev == psbuf->st_ex_dev) {
    3260       80060 :                 return (uint64_t)psbuf->st_ex_ino;
    3261             :         }
    3262             : 
    3263             :         /* FileIDLow */
    3264          26 :         file_id = ((psbuf->st_ex_ino) & UINT32_MAX);
    3265             : 
    3266             :         /* FileIDHigh */
    3267          26 :         file_id |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32;
    3268             : 
    3269          26 :         return file_id;
    3270             : }
    3271             : 
    3272      302838 : static NTSTATUS vfswrap_fstreaminfo(vfs_handle_struct *handle,
    3273             :                                    struct files_struct *fsp,
    3274             :                                    TALLOC_CTX *mem_ctx,
    3275             :                                    unsigned int *pnum_streams,
    3276             :                                    struct stream_struct **pstreams)
    3277             : {
    3278      302838 :         struct stream_struct *tmp_streams = NULL;
    3279      302838 :         unsigned int num_streams = *pnum_streams;
    3280      302838 :         struct stream_struct *streams = *pstreams;
    3281             :         NTSTATUS status;
    3282             : 
    3283      302838 :         if (fsp->fsp_flags.is_directory) {
    3284             :                 /*
    3285             :                  * No default streams on directories
    3286             :                  */
    3287       22878 :                 goto done;
    3288             :         }
    3289      279766 :         status = vfs_stat_fsp(fsp);
    3290      279766 :         if (!NT_STATUS_IS_OK(status)) {
    3291           0 :                 return status;
    3292             :         }
    3293             : 
    3294      279766 :         if (num_streams + 1 < 1) {
    3295             :                 /* Integer wrap. */
    3296           0 :                 return NT_STATUS_INVALID_PARAMETER;
    3297             :         }
    3298             : 
    3299      279766 :         tmp_streams = talloc_realloc(mem_ctx,
    3300             :                                         streams,
    3301             :                                         struct stream_struct,
    3302             :                                         num_streams + 1);
    3303      279766 :         if (tmp_streams == NULL) {
    3304           0 :                 return NT_STATUS_NO_MEMORY;
    3305             :         }
    3306      279766 :         tmp_streams[num_streams].name = talloc_strdup(tmp_streams, "::$DATA");
    3307      279766 :         if (tmp_streams[num_streams].name == NULL) {
    3308           0 :                 return NT_STATUS_NO_MEMORY;
    3309             :         }
    3310      279766 :         tmp_streams[num_streams].size = fsp->fsp_name->st.st_ex_size;
    3311      279766 :         tmp_streams[num_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(
    3312             :                                                 handle->conn,
    3313             :                                                 fsp,
    3314             :                                                 &fsp->fsp_name->st);
    3315      279766 :         num_streams += 1;
    3316             : 
    3317      279766 :         *pnum_streams = num_streams;
    3318      279766 :         *pstreams = tmp_streams;
    3319      303032 :  done:
    3320      302838 :         return NT_STATUS_OK;
    3321             : }
    3322             : 
    3323      282707 : static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
    3324             :                                      const struct smb_filename *path,
    3325             :                                      const char *name,
    3326             :                                      TALLOC_CTX *mem_ctx,
    3327             :                                      char **found_name)
    3328             : {
    3329             :         /*
    3330             :          * Don't fall back to get_real_filename so callers can differentiate
    3331             :          * between a full directory scan and an actual case-insensitive stat.
    3332             :          */
    3333      282707 :         errno = EOPNOTSUPP;
    3334      282707 :         return -1;
    3335             : }
    3336             : 
    3337    10536341 : static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
    3338             :                                    const struct smb_filename *smb_fname)
    3339             : {
    3340    10536341 :         return handle->conn->connectpath;
    3341             : }
    3342             : 
    3343        5807 : static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
    3344             :                                          struct byte_range_lock *br_lck,
    3345             :                                          struct lock_struct *plock)
    3346             : {
    3347        5807 :         SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
    3348             : 
    3349             :         /* Note: blr is not used in the default implementation. */
    3350        5807 :         return brl_lock_windows_default(br_lck, plock);
    3351             : }
    3352             : 
    3353        2879 : static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
    3354             :                                        struct byte_range_lock *br_lck,
    3355             :                                        const struct lock_struct *plock)
    3356             : {
    3357        2879 :         SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
    3358             : 
    3359        2879 :         return brl_unlock_windows_default(br_lck, plock);
    3360             : }
    3361             : 
    3362      185343 : static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
    3363             :                                       files_struct *fsp,
    3364             :                                       struct lock_struct *plock)
    3365             : {
    3366      185343 :         SMB_ASSERT(plock->lock_type == READ_LOCK ||
    3367             :             plock->lock_type == WRITE_LOCK);
    3368             : 
    3369      185343 :         return strict_lock_check_default(fsp, plock);
    3370             : }
    3371             : 
    3372             : /* NT ACL operations. */
    3373             : 
    3374      431545 : static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
    3375             :                                     files_struct *fsp,
    3376             :                                     uint32_t security_info,
    3377             :                                     TALLOC_CTX *mem_ctx,
    3378             :                                     struct security_descriptor **ppdesc)
    3379             : {
    3380             :         NTSTATUS result;
    3381             : 
    3382      431545 :         START_PROFILE(fget_nt_acl);
    3383      431545 :         result = posix_fget_nt_acl(fsp, security_info,
    3384             :                                    mem_ctx, ppdesc);
    3385      431545 :         END_PROFILE(fget_nt_acl);
    3386      431545 :         return result;
    3387             : }
    3388             : 
    3389      151935 : static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
    3390             : {
    3391             :         NTSTATUS result;
    3392             : 
    3393      151935 :         START_PROFILE(fset_nt_acl);
    3394      151935 :         result = set_nt_acl(fsp, security_info_sent, psd);
    3395      151935 :         END_PROFILE(fset_nt_acl);
    3396      151935 :         return result;
    3397             : }
    3398             : 
    3399           0 : static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
    3400             :                                    struct smb_filename *file,
    3401             :                                    struct security_acl *sacl,
    3402             :                                    uint32_t access_requested,
    3403             :                                    uint32_t access_denied)
    3404             : {
    3405           0 :         return NT_STATUS_OK; /* Nothing to do here ... */
    3406             : }
    3407             : 
    3408      208104 : static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
    3409             :                                         files_struct *fsp,
    3410             :                                         SMB_ACL_TYPE_T type,
    3411             :                                         TALLOC_CTX *mem_ctx)
    3412             : {
    3413      208104 :         return sys_acl_get_fd(handle, fsp, type, mem_ctx);
    3414             : }
    3415             : 
    3416         938 : static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle,
    3417             :                                   files_struct *fsp,
    3418             :                                   SMB_ACL_TYPE_T type,
    3419             :                                   SMB_ACL_T theacl)
    3420             : {
    3421         938 :         return sys_acl_set_fd(handle, fsp, type, theacl);
    3422             : }
    3423             : 
    3424           0 : static int vfswrap_sys_acl_delete_def_fd(vfs_handle_struct *handle,
    3425             :                                          files_struct *fsp)
    3426             : {
    3427           0 :         return sys_acl_delete_def_fd(handle, fsp);
    3428             : }
    3429             : 
    3430             : /****************************************************************
    3431             :  Extended attribute operations.
    3432             : *****************************************************************/
    3433             : 
    3434      146253 : static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle,
    3435             :                                  struct files_struct *fsp,
    3436             :                                  const char *name,
    3437             :                                  void *value,
    3438             :                                  size_t size)
    3439             : {
    3440      146253 :         int fd = fsp_get_pathref_fd(fsp);
    3441             : 
    3442      146253 :         if (!fsp->fsp_flags.is_pathref) {
    3443       43203 :                 return fgetxattr(fd, name, value, size);
    3444             :         }
    3445             : 
    3446      103050 :         if (fsp->fsp_flags.have_proc_fds) {
    3447       22802 :                 const char *p = NULL;
    3448             :                 char buf[PATH_MAX];
    3449             : 
    3450       22802 :                 p = sys_proc_fd_path(fd, buf, sizeof(buf));
    3451       22802 :                 if (p == NULL) {
    3452           0 :                         return -1;
    3453             :                 }
    3454             : 
    3455       22802 :                 return getxattr(p, name, value, size);
    3456             :         }
    3457             : 
    3458             :         /*
    3459             :          * This is no longer a handle based call.
    3460             :          */
    3461       80248 :         return getxattr(fsp->fsp_name->base_name, name, value, size);
    3462             : }
    3463             : 
    3464             : struct vfswrap_getxattrat_state {
    3465             :         struct tevent_context *ev;
    3466             :         struct vfs_handle_struct *handle;
    3467             :         files_struct *dir_fsp;
    3468             :         const struct smb_filename *smb_fname;
    3469             : 
    3470             :         /*
    3471             :          * The following variables are talloced off "state" which is protected
    3472             :          * by a destructor and thus are guaranteed to be safe to be used in the
    3473             :          * job function in the worker thread.
    3474             :          */
    3475             :         char *name;
    3476             :         const char *xattr_name;
    3477             :         uint8_t *xattr_value;
    3478             :         struct security_unix_token *token;
    3479             : 
    3480             :         ssize_t xattr_size;
    3481             :         struct vfs_aio_state vfs_aio_state;
    3482             :         SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
    3483             : };
    3484             : 
    3485           0 : static int vfswrap_getxattrat_state_destructor(
    3486             :                 struct vfswrap_getxattrat_state *state)
    3487             : {
    3488           0 :         return -1;
    3489             : }
    3490             : 
    3491             : static void vfswrap_getxattrat_do_sync(struct tevent_req *req);
    3492             : static void vfswrap_getxattrat_do_async(void *private_data);
    3493             : static void vfswrap_getxattrat_done(struct tevent_req *subreq);
    3494             : 
    3495       20118 : static struct tevent_req *vfswrap_getxattrat_send(
    3496             :                         TALLOC_CTX *mem_ctx,
    3497             :                         struct tevent_context *ev,
    3498             :                         struct vfs_handle_struct *handle,
    3499             :                         files_struct *dir_fsp,
    3500             :                         const struct smb_filename *smb_fname,
    3501             :                         const char *xattr_name,
    3502             :                         size_t alloc_hint)
    3503             : {
    3504       20118 :         struct tevent_req *req = NULL;
    3505       20118 :         struct tevent_req *subreq = NULL;
    3506       20118 :         struct vfswrap_getxattrat_state *state = NULL;
    3507       20118 :         size_t max_threads = 0;
    3508       20118 :         bool have_per_thread_cwd = false;
    3509       20118 :         bool have_per_thread_creds = false;
    3510       20118 :         bool do_async = false;
    3511             : 
    3512       20118 :         req = tevent_req_create(mem_ctx, &state,
    3513             :                                 struct vfswrap_getxattrat_state);
    3514       20118 :         if (req == NULL) {
    3515           0 :                 return NULL;
    3516             :         }
    3517       20118 :         *state = (struct vfswrap_getxattrat_state) {
    3518             :                 .ev = ev,
    3519             :                 .handle = handle,
    3520             :                 .dir_fsp = dir_fsp,
    3521             :                 .smb_fname = smb_fname,
    3522             :         };
    3523             : 
    3524       20118 :         max_threads = pthreadpool_tevent_max_threads(dir_fsp->conn->sconn->pool);
    3525       20118 :         if (max_threads >= 1) {
    3526             :                 /*
    3527             :                  * We need a non sync threadpool!
    3528             :                  */
    3529       20118 :                 have_per_thread_cwd = per_thread_cwd_supported();
    3530             :         }
    3531             : #ifdef HAVE_LINUX_THREAD_CREDENTIALS
    3532       20118 :         have_per_thread_creds = true;
    3533             : #endif
    3534       20118 :         if (have_per_thread_cwd && have_per_thread_creds) {
    3535       20118 :                 do_async = true;
    3536             :         }
    3537             : 
    3538       20118 :         SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat, profile_p,
    3539             :                                      state->profile_bytes, 0);
    3540             : 
    3541       20118 :         if (fsp_get_pathref_fd(dir_fsp) == -1) {
    3542           0 :                 DBG_ERR("Need a valid directory fd\n");
    3543           0 :                 tevent_req_error(req, EINVAL);
    3544           0 :                 return tevent_req_post(req, ev);
    3545             :         }
    3546             : 
    3547       20118 :         if (alloc_hint > 0) {
    3548       20118 :                 state->xattr_value = talloc_zero_array(state,
    3549             :                                                        uint8_t,
    3550             :                                                        alloc_hint);
    3551       20118 :                 if (tevent_req_nomem(state->xattr_value, req)) {
    3552           0 :                         return tevent_req_post(req, ev);
    3553             :                 }
    3554             :         }
    3555             : 
    3556       20118 :         if (!do_async) {
    3557           0 :                 vfswrap_getxattrat_do_sync(req);
    3558           0 :                 return tevent_req_post(req, ev);
    3559             :         }
    3560             : 
    3561             :         /*
    3562             :          * Now allocate all parameters from a memory context that won't go away
    3563             :          * no matter what. These paremeters will get used in threads and we
    3564             :          * can't reliably cancel threads, so all buffers passed to the threads
    3565             :          * must not be freed before all referencing threads terminate.
    3566             :          */
    3567             : 
    3568       20118 :         state->name = talloc_strdup(state, smb_fname->base_name);
    3569       20118 :         if (tevent_req_nomem(state->name, req)) {
    3570           0 :                 return tevent_req_post(req, ev);
    3571             :         }
    3572             : 
    3573       20118 :         state->xattr_name = talloc_strdup(state, xattr_name);
    3574       20118 :         if (tevent_req_nomem(state->xattr_name, req)) {
    3575           0 :                 return tevent_req_post(req, ev);
    3576             :         }
    3577             : 
    3578             :         /*
    3579             :          * This is a hot codepath so at first glance one might think we should
    3580             :          * somehow optimize away the token allocation and do a
    3581             :          * talloc_reference() or similar black magic instead. But due to the
    3582             :          * talloc_stackframe pool per SMB2 request this should be a simple copy
    3583             :          * without a malloc in most cases.
    3584             :          */
    3585       20118 :         if (geteuid() == sec_initial_uid()) {
    3586       20118 :                 state->token = root_unix_token(state);
    3587             :         } else {
    3588           0 :                 state->token = copy_unix_token(
    3589             :                                         state,
    3590           0 :                                         dir_fsp->conn->session_info->unix_token);
    3591             :         }
    3592       20118 :         if (tevent_req_nomem(state->token, req)) {
    3593           0 :                 return tevent_req_post(req, ev);
    3594             :         }
    3595             : 
    3596       20118 :         SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
    3597             : 
    3598       40236 :         subreq = pthreadpool_tevent_job_send(
    3599             :                         state,
    3600             :                         ev,
    3601       20118 :                         dir_fsp->conn->sconn->pool,
    3602             :                         vfswrap_getxattrat_do_async,
    3603             :                         state);
    3604       20118 :         if (tevent_req_nomem(subreq, req)) {
    3605           0 :                 return tevent_req_post(req, ev);
    3606             :         }
    3607       20118 :         tevent_req_set_callback(subreq, vfswrap_getxattrat_done, req);
    3608             : 
    3609       20118 :         talloc_set_destructor(state, vfswrap_getxattrat_state_destructor);
    3610             : 
    3611       20118 :         return req;
    3612             : }
    3613             : 
    3614           0 : static void vfswrap_getxattrat_do_sync(struct tevent_req *req)
    3615             : {
    3616           0 :         struct vfswrap_getxattrat_state *state = tevent_req_data(
    3617             :                 req, struct vfswrap_getxattrat_state);
    3618           0 :         struct files_struct *fsp = state->smb_fname->fsp;
    3619             : 
    3620           0 :         if (fsp->base_fsp != NULL) {
    3621           0 :                 fsp = fsp->base_fsp;
    3622             :         }
    3623             : 
    3624           0 :         state->xattr_size = vfswrap_fgetxattr(state->handle,
    3625             :                                               fsp,
    3626             :                                               state->xattr_name,
    3627           0 :                                               state->xattr_value,
    3628           0 :                                               talloc_array_length(state->xattr_value));
    3629           0 :         if (state->xattr_size == -1) {
    3630           0 :                 tevent_req_error(req, errno);
    3631           0 :                 return;
    3632             :         }
    3633             : 
    3634           0 :         tevent_req_done(req);
    3635           0 :         return;
    3636             : }
    3637             : 
    3638       20118 : static void vfswrap_getxattrat_do_async(void *private_data)
    3639             : {
    3640       20118 :         struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
    3641             :                 private_data, struct vfswrap_getxattrat_state);
    3642             :         struct timespec start_time;
    3643             :         struct timespec end_time;
    3644             :         int ret;
    3645       20118 :         struct files_struct *fsp = state->smb_fname->fsp;
    3646             : 
    3647       20118 :         if (fsp->base_fsp != NULL) {
    3648           0 :                 fsp = fsp->base_fsp;
    3649             :         }
    3650             : 
    3651       20118 :         PROFILE_TIMESTAMP(&start_time);
    3652       20118 :         SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
    3653             : 
    3654             :         /*
    3655             :          * Here we simulate a getxattrat()
    3656             :          * call using fchdir();getxattr()
    3657             :          */
    3658             : 
    3659       20118 :         per_thread_cwd_activate();
    3660             : 
    3661             :         /* Become the correct credential on this thread. */
    3662       40236 :         ret = set_thread_credentials(state->token->uid,
    3663       20118 :                                      state->token->gid,
    3664       20118 :                                      (size_t)state->token->ngroups,
    3665       20118 :                                      state->token->groups);
    3666       20118 :         if (ret != 0) {
    3667           0 :                 state->xattr_size = -1;
    3668           0 :                 state->vfs_aio_state.error = errno;
    3669           0 :                 goto end_profile;
    3670             :         }
    3671             : 
    3672       20118 :         state->xattr_size = vfswrap_fgetxattr(state->handle,
    3673             :                                               fsp,
    3674             :                                               state->xattr_name,
    3675       20118 :                                               state->xattr_value,
    3676       20118 :                                               talloc_array_length(state->xattr_value));
    3677       20118 :         if (state->xattr_size == -1) {
    3678         104 :                 state->vfs_aio_state.error = errno;
    3679             :         }
    3680             : 
    3681       40132 : end_profile:
    3682       20118 :         PROFILE_TIMESTAMP(&end_time);
    3683       20118 :         state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
    3684       20117 :         SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
    3685       20117 : }
    3686             : 
    3687       20118 : static void vfswrap_getxattrat_done(struct tevent_req *subreq)
    3688             : {
    3689       20118 :         struct tevent_req *req = tevent_req_callback_data(
    3690             :                 subreq, struct tevent_req);
    3691       20118 :         struct vfswrap_getxattrat_state *state = tevent_req_data(
    3692             :                 req, struct vfswrap_getxattrat_state);
    3693             :         int ret;
    3694             :         bool ok;
    3695             : 
    3696             :         /*
    3697             :          * Make sure we run as the user again
    3698             :          */
    3699       20118 :         ok = change_to_user_and_service_by_fsp(state->dir_fsp);
    3700       20118 :         SMB_ASSERT(ok);
    3701             : 
    3702       20118 :         ret = pthreadpool_tevent_job_recv(subreq);
    3703       20118 :         TALLOC_FREE(subreq);
    3704       20118 :         SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
    3705       20118 :         talloc_set_destructor(state, NULL);
    3706       20118 :         if (ret != 0) {
    3707           0 :                 if (ret != EAGAIN) {
    3708           0 :                         tevent_req_error(req, ret);
    3709           0 :                         return;
    3710             :                 }
    3711             :                 /*
    3712             :                  * If we get EAGAIN from pthreadpool_tevent_job_recv() this
    3713             :                  * means the lower level pthreadpool failed to create a new
    3714             :                  * thread. Fallback to sync processing in that case to allow
    3715             :                  * some progress for the client.
    3716             :                  */
    3717           0 :                 vfswrap_getxattrat_do_sync(req);
    3718           0 :                 return;
    3719             :         }
    3720             : 
    3721       20118 :         if (state->xattr_size == -1) {
    3722         104 :                 tevent_req_error(req, state->vfs_aio_state.error);
    3723         104 :                 return;
    3724             :         }
    3725             : 
    3726       20014 :         if (state->xattr_value == NULL) {
    3727             :                 /*
    3728             :                  * The caller only wanted the size.
    3729             :                  */
    3730           0 :                 tevent_req_done(req);
    3731           0 :                 return;
    3732             :         }
    3733             : 
    3734             :         /*
    3735             :          * shrink the buffer to the returned size.
    3736             :          * (can't fail). It means NULL if size is 0.
    3737             :          */
    3738       20014 :         state->xattr_value = talloc_realloc(state,
    3739             :                                             state->xattr_value,
    3740             :                                             uint8_t,
    3741             :                                             state->xattr_size);
    3742             : 
    3743       20014 :         tevent_req_done(req);
    3744             : }
    3745             : 
    3746       20118 : static ssize_t vfswrap_getxattrat_recv(struct tevent_req *req,
    3747             :                                        struct vfs_aio_state *aio_state,
    3748             :                                        TALLOC_CTX *mem_ctx,
    3749             :                                        uint8_t **xattr_value)
    3750             : {
    3751       20118 :         struct vfswrap_getxattrat_state *state = tevent_req_data(
    3752             :                 req, struct vfswrap_getxattrat_state);
    3753             :         ssize_t xattr_size;
    3754             : 
    3755       20118 :         if (tevent_req_is_unix_error(req, &aio_state->error)) {
    3756         104 :                 tevent_req_received(req);
    3757         104 :                 return -1;
    3758             :         }
    3759             : 
    3760       20014 :         *aio_state = state->vfs_aio_state;
    3761       20014 :         xattr_size = state->xattr_size;
    3762       20014 :         if (xattr_value != NULL) {
    3763       20014 :                 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
    3764             :         }
    3765             : 
    3766       20014 :         tevent_req_received(req);
    3767       20014 :         return xattr_size;
    3768             : }
    3769             : 
    3770       23907 : static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
    3771             : {
    3772       23907 :         int fd = fsp_get_pathref_fd(fsp);
    3773             : 
    3774       23907 :         if (!fsp->fsp_flags.is_pathref) {
    3775         552 :                 return flistxattr(fd, list, size);
    3776             :         }
    3777             : 
    3778       23355 :         if (fsp->fsp_flags.have_proc_fds) {
    3779        3329 :                 const char *p = NULL;
    3780             :                 char buf[PATH_MAX];
    3781             : 
    3782        3329 :                 p = sys_proc_fd_path(fd, buf, sizeof(buf));
    3783        3329 :                 if (p == NULL) {
    3784           0 :                         return -1;
    3785             :                 }
    3786             : 
    3787        3329 :                 return listxattr(p, list, size);
    3788             :         }
    3789             : 
    3790             :         /*
    3791             :          * This is no longer a handle based call.
    3792             :          */
    3793       20026 :         return listxattr(fsp->fsp_name->base_name, list, size);
    3794             : }
    3795             : 
    3796          10 : static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
    3797             : {
    3798          10 :         int fd = fsp_get_pathref_fd(fsp);
    3799             : 
    3800          10 :         if (!fsp->fsp_flags.is_pathref) {
    3801           0 :                 return fremovexattr(fd, name);
    3802             :         }
    3803             : 
    3804          10 :         if (fsp->fsp_flags.have_proc_fds) {
    3805          10 :                 const char *p = NULL;
    3806             :                 char buf[PATH_MAX];
    3807             : 
    3808          10 :                 p = sys_proc_fd_path(fd, buf, sizeof(buf));
    3809          10 :                 if (p == NULL) {
    3810           0 :                         return -1;
    3811             :                 }
    3812             : 
    3813          10 :                 return removexattr(p, name);
    3814             :         }
    3815             : 
    3816             :         /*
    3817             :          * This is no longer a handle based call.
    3818             :          */
    3819           0 :         return removexattr(fsp->fsp_name->base_name, name);
    3820             : }
    3821             : 
    3822       20237 : static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
    3823             : {
    3824       20237 :         int fd = fsp_get_pathref_fd(fsp);
    3825             : 
    3826       20237 :         if (!fsp->fsp_flags.is_pathref) {
    3827       20185 :                 return fsetxattr(fd, name, value, size, flags);
    3828             :         }
    3829             : 
    3830          52 :         if (fsp->fsp_flags.have_proc_fds) {
    3831          38 :                 const char *p = NULL;
    3832             :                 char buf[PATH_MAX];
    3833             : 
    3834          38 :                 p = sys_proc_fd_path(fd, buf, sizeof(buf));
    3835          38 :                 if (p == NULL) {
    3836           0 :                         return -1;
    3837             :                 }
    3838             : 
    3839          38 :                 return setxattr(p, name, value, size, flags);
    3840             :         }
    3841             : 
    3842             :         /*
    3843             :          * This is no longer a handle based call.
    3844             :          */
    3845          14 :         return setxattr(fsp->fsp_name->base_name, name, value, size, flags);
    3846             : }
    3847             : 
    3848          67 : static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
    3849             : {
    3850          67 :         return false;
    3851             : }
    3852             : 
    3853     1375573 : static bool vfswrap_is_offline(struct connection_struct *conn,
    3854             :                                const struct smb_filename *fname)
    3855             : {
    3856             :         NTSTATUS status;
    3857             :         char *path;
    3858     1375573 :         bool offline = false;
    3859             : 
    3860     1375573 :         if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
    3861        7921 :                 return false;
    3862             :         }
    3863             : 
    3864     1367652 :         if (!lp_dmapi_support(SNUM(conn)) || !dmapi_have_session()) {
    3865             : #if defined(ENOTSUP)
    3866     1367652 :                 errno = ENOTSUP;
    3867             : #endif
    3868     1367652 :                 return false;
    3869             :         }
    3870             : 
    3871           0 :         status = get_full_smb_filename(talloc_tos(), fname, &path);
    3872           0 :         if (!NT_STATUS_IS_OK(status)) {
    3873           0 :                 errno = map_errno_from_nt_status(status);
    3874           0 :                 return false;
    3875             :         }
    3876             : 
    3877           0 :         offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
    3878             : 
    3879           0 :         TALLOC_FREE(path);
    3880             : 
    3881           0 :         return offline;
    3882             : }
    3883             : 
    3884         546 : static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
    3885             :                                        struct files_struct *fsp,
    3886             :                                        TALLOC_CTX *mem_ctx,
    3887             :                                        DATA_BLOB *cookie)
    3888             : {
    3889         546 :         return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
    3890             : }
    3891             : 
    3892         166 : static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
    3893             :                                            struct files_struct *fsp,
    3894             :                                            const DATA_BLOB old_cookie,
    3895             :                                            TALLOC_CTX *mem_ctx,
    3896             :                                            DATA_BLOB *new_cookie)
    3897             : {
    3898         166 :         return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
    3899             :                                               new_cookie);
    3900             : }
    3901             : 
    3902         156 : static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
    3903             :                                           struct smb_request *smb1req,
    3904             :                                           struct smbXsrv_open *op,
    3905             :                                           const DATA_BLOB old_cookie,
    3906             :                                           TALLOC_CTX *mem_ctx,
    3907             :                                           struct files_struct **fsp,
    3908             :                                           DATA_BLOB *new_cookie)
    3909             : {
    3910         156 :         return vfs_default_durable_reconnect(handle->conn, smb1req, op,
    3911             :                                              old_cookie, mem_ctx,
    3912             :                                              fsp, new_cookie);
    3913             : }
    3914             : 
    3915             : static struct vfs_fn_pointers vfs_default_fns = {
    3916             :         /* Disk operations */
    3917             : 
    3918             :         .connect_fn = vfswrap_connect,
    3919             :         .disconnect_fn = vfswrap_disconnect,
    3920             :         .disk_free_fn = vfswrap_disk_free,
    3921             :         .get_quota_fn = vfswrap_get_quota,
    3922             :         .set_quota_fn = vfswrap_set_quota,
    3923             :         .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
    3924             :         .statvfs_fn = vfswrap_statvfs,
    3925             :         .fs_capabilities_fn = vfswrap_fs_capabilities,
    3926             :         .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
    3927             :         .create_dfs_pathat_fn = vfswrap_create_dfs_pathat,
    3928             :         .read_dfs_pathat_fn = vfswrap_read_dfs_pathat,
    3929             :         .snap_check_path_fn = vfswrap_snap_check_path,
    3930             :         .snap_create_fn = vfswrap_snap_create,
    3931             :         .snap_delete_fn = vfswrap_snap_delete,
    3932             : 
    3933             :         /* Directory operations */
    3934             : 
    3935             :         .fdopendir_fn = vfswrap_fdopendir,
    3936             :         .readdir_fn = vfswrap_readdir,
    3937             :         .freaddir_attr_fn = vfswrap_freaddir_attr,
    3938             :         .seekdir_fn = vfswrap_seekdir,
    3939             :         .telldir_fn = vfswrap_telldir,
    3940             :         .rewind_dir_fn = vfswrap_rewinddir,
    3941             :         .mkdirat_fn = vfswrap_mkdirat,
    3942             :         .closedir_fn = vfswrap_closedir,
    3943             : 
    3944             :         /* File operations */
    3945             : 
    3946             :         .openat_fn = vfswrap_openat,
    3947             :         .create_file_fn = vfswrap_create_file,
    3948             :         .close_fn = vfswrap_close,
    3949             :         .pread_fn = vfswrap_pread,
    3950             :         .pread_send_fn = vfswrap_pread_send,
    3951             :         .pread_recv_fn = vfswrap_pread_recv,
    3952             :         .pwrite_fn = vfswrap_pwrite,
    3953             :         .pwrite_send_fn = vfswrap_pwrite_send,
    3954             :         .pwrite_recv_fn = vfswrap_pwrite_recv,
    3955             :         .lseek_fn = vfswrap_lseek,
    3956             :         .sendfile_fn = vfswrap_sendfile,
    3957             :         .recvfile_fn = vfswrap_recvfile,
    3958             :         .renameat_fn = vfswrap_renameat,
    3959             :         .fsync_send_fn = vfswrap_fsync_send,
    3960             :         .fsync_recv_fn = vfswrap_fsync_recv,
    3961             :         .stat_fn = vfswrap_stat,
    3962             :         .fstat_fn = vfswrap_fstat,
    3963             :         .lstat_fn = vfswrap_lstat,
    3964             :         .get_alloc_size_fn = vfswrap_get_alloc_size,
    3965             :         .unlinkat_fn = vfswrap_unlinkat,
    3966             :         .fchmod_fn = vfswrap_fchmod,
    3967             :         .fchown_fn = vfswrap_fchown,
    3968             :         .lchown_fn = vfswrap_lchown,
    3969             :         .chdir_fn = vfswrap_chdir,
    3970             :         .getwd_fn = vfswrap_getwd,
    3971             :         .fntimes_fn = vfswrap_fntimes,
    3972             :         .ftruncate_fn = vfswrap_ftruncate,
    3973             :         .fallocate_fn = vfswrap_fallocate,
    3974             :         .lock_fn = vfswrap_lock,
    3975             :         .filesystem_sharemode_fn = vfswrap_filesystem_sharemode,
    3976             :         .fcntl_fn = vfswrap_fcntl,
    3977             :         .linux_setlease_fn = vfswrap_linux_setlease,
    3978             :         .getlock_fn = vfswrap_getlock,
    3979             :         .symlinkat_fn = vfswrap_symlinkat,
    3980             :         .readlinkat_fn = vfswrap_readlinkat,
    3981             :         .linkat_fn = vfswrap_linkat,
    3982             :         .mknodat_fn = vfswrap_mknodat,
    3983             :         .realpath_fn = vfswrap_realpath,
    3984             :         .fchflags_fn = vfswrap_fchflags,
    3985             :         .file_id_create_fn = vfswrap_file_id_create,
    3986             :         .fs_file_id_fn = vfswrap_fs_file_id,
    3987             :         .fstreaminfo_fn = vfswrap_fstreaminfo,
    3988             :         .get_real_filename_fn = vfswrap_get_real_filename,
    3989             :         .connectpath_fn = vfswrap_connectpath,
    3990             :         .brl_lock_windows_fn = vfswrap_brl_lock_windows,
    3991             :         .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
    3992             :         .strict_lock_check_fn = vfswrap_strict_lock_check,
    3993             :         .translate_name_fn = vfswrap_translate_name,
    3994             :         .parent_pathname_fn = vfswrap_parent_pathname,
    3995             :         .fsctl_fn = vfswrap_fsctl,
    3996             :         .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
    3997             :         .get_dos_attributes_send_fn = vfswrap_get_dos_attributes_send,
    3998             :         .get_dos_attributes_recv_fn = vfswrap_get_dos_attributes_recv,
    3999             :         .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
    4000             :         .offload_read_send_fn = vfswrap_offload_read_send,
    4001             :         .offload_read_recv_fn = vfswrap_offload_read_recv,
    4002             :         .offload_write_send_fn = vfswrap_offload_write_send,
    4003             :         .offload_write_recv_fn = vfswrap_offload_write_recv,
    4004             :         .fget_compression_fn = vfswrap_fget_compression,
    4005             :         .set_compression_fn = vfswrap_set_compression,
    4006             : 
    4007             :         /* NT ACL operations. */
    4008             : 
    4009             :         .fget_nt_acl_fn = vfswrap_fget_nt_acl,
    4010             :         .fset_nt_acl_fn = vfswrap_fset_nt_acl,
    4011             :         .audit_file_fn = vfswrap_audit_file,
    4012             : 
    4013             :         /* POSIX ACL operations. */
    4014             : 
    4015             :         .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
    4016             :         .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
    4017             :         .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
    4018             :         .sys_acl_delete_def_fd_fn = vfswrap_sys_acl_delete_def_fd,
    4019             : 
    4020             :         /* EA operations. */
    4021             :         .getxattrat_send_fn = vfswrap_getxattrat_send,
    4022             :         .getxattrat_recv_fn = vfswrap_getxattrat_recv,
    4023             :         .fgetxattr_fn = vfswrap_fgetxattr,
    4024             :         .flistxattr_fn = vfswrap_flistxattr,
    4025             :         .fremovexattr_fn = vfswrap_fremovexattr,
    4026             :         .fsetxattr_fn = vfswrap_fsetxattr,
    4027             : 
    4028             :         /* aio operations */
    4029             :         .aio_force_fn = vfswrap_aio_force,
    4030             : 
    4031             :         /* durable handle operations */
    4032             :         .durable_cookie_fn = vfswrap_durable_cookie,
    4033             :         .durable_disconnect_fn = vfswrap_durable_disconnect,
    4034             :         .durable_reconnect_fn = vfswrap_durable_reconnect,
    4035             : };
    4036             : 
    4037             : static_decl_vfs;
    4038       25301 : NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
    4039             : {
    4040             :         /*
    4041             :          * Here we need to implement every call!
    4042             :          *
    4043             :          * As this is the end of the vfs module chain.
    4044             :          */
    4045       25301 :         smb_vfs_assert_all_fns(&vfs_default_fns, DEFAULT_VFS_MODULE_NAME);
    4046       25301 :         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
    4047             :                                 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);
    4048             : }
    4049             : 
    4050             : 

Generated by: LCOV version 1.13