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