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