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