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