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