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