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