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