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