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