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