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