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