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