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