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