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