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
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.
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.
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/>.
22 #include "system/time.h"
23 #include "system/filesys.h"
24 #include "smbd/smbd.h"
25 #include "smbd/globals.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/asys/asys.h"
34 #include "lib/util/tevent_ntstatus.h"
35 #include "lib/sys_rw.h"
38 #define DBGC_CLASS DBGC_VFS
40 /* Check for NULL pointer parameters in vfswrap_* functions */
42 /* We don't want to have NULL function pointers lying around. Someone
43 is sure to try and execute them. These stubs are used to prevent
46 static int vfswrap_connect(vfs_handle_struct *handle, const char *service, const char *user)
48 return 0; /* Return >= 0 for success */
51 static void vfswrap_disconnect(vfs_handle_struct *handle)
57 static uint64_t vfswrap_disk_free(vfs_handle_struct *handle, const char *path,
58 uint64_t *bsize, uint64_t *dfree,
63 result = sys_disk_free(handle->conn, path, bsize, dfree, dsize);
67 static int vfswrap_get_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
69 #ifdef HAVE_SYS_QUOTAS
72 START_PROFILE(syscall_get_quota);
73 result = sys_get_quota(handle->conn->connectpath, qtype, id, qt);
74 END_PROFILE(syscall_get_quota);
82 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
84 #ifdef HAVE_SYS_QUOTAS
87 START_PROFILE(syscall_set_quota);
88 result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
89 END_PROFILE(syscall_set_quota);
97 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
98 struct files_struct *fsp,
99 struct shadow_copy_data *shadow_copy_data,
103 return -1; /* Not implemented. */
106 static int vfswrap_statvfs(struct vfs_handle_struct *handle, const char *path, vfs_statvfs_struct *statbuf)
108 return sys_statvfs(path, statbuf);
111 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
112 enum timestamp_set_resolution *p_ts_res)
114 connection_struct *conn = handle->conn;
115 uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
116 struct smb_filename *smb_fname_cpath = NULL;
117 struct vfs_statvfs_struct statbuf;
120 ZERO_STRUCT(statbuf);
121 ret = sys_statvfs(conn->connectpath, &statbuf);
123 caps = statbuf.FsCapabilities;
126 *p_ts_res = TIMESTAMP_SET_SECONDS;
128 /* Work out what timestamp resolution we can
129 * use when setting a timestamp. */
131 smb_fname_cpath = synthetic_smb_fname(talloc_tos(), conn->connectpath,
133 if (smb_fname_cpath == NULL) {
137 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
139 TALLOC_FREE(smb_fname_cpath);
143 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
144 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
145 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
146 /* If any of the normal UNIX directory timestamps
147 * have a non-zero tv_nsec component assume
148 * we might be able to set sub-second timestamps.
149 * See what filetime set primitives we have.
151 #if defined(HAVE_UTIMENSAT)
152 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
153 #elif defined(HAVE_UTIMES)
154 /* utimes allows msec timestamps to be set. */
155 *p_ts_res = TIMESTAMP_SET_MSEC;
156 #elif defined(HAVE_UTIME)
157 /* utime only allows sec timestamps to be set. */
158 *p_ts_res = TIMESTAMP_SET_SECONDS;
161 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
163 "available on share %s, directory %s\n",
164 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
165 lp_servicename(talloc_tos(), conn->params->service),
166 conn->connectpath ));
168 TALLOC_FREE(smb_fname_cpath);
172 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
173 struct dfs_GetDFSReferral *r)
175 struct junction_map *junction = NULL;
177 bool self_referral = false;
178 char *pathnamep = NULL;
179 char *local_dfs_path = NULL;
182 uint16_t max_referral_level = r->in.req.max_referral_level;
185 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
188 /* get the junction entry */
189 if (r->in.req.servername == NULL) {
190 return NT_STATUS_NOT_FOUND;
194 * Trim pathname sent by client so it begins with only one backslash.
195 * Two backslashes confuse some dfs clients
198 local_dfs_path = talloc_strdup(r, r->in.req.servername);
199 if (local_dfs_path == NULL) {
200 return NT_STATUS_NO_MEMORY;
202 pathnamep = local_dfs_path;
203 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
204 IS_DIRECTORY_SEP(pathnamep[1])) {
208 junction = talloc_zero(r, struct junction_map);
209 if (junction == NULL) {
210 return NT_STATUS_NO_MEMORY;
213 /* The following call can change cwd. */
214 status = get_referred_path(r, pathnamep,
215 !handle->conn->sconn->using_smb2,
216 junction, &consumedcnt, &self_referral);
217 if (!NT_STATUS_IS_OK(status)) {
218 vfs_ChDir(handle->conn, handle->conn->connectpath);
221 vfs_ChDir(handle->conn, handle->conn->connectpath);
223 if (!self_referral) {
224 pathnamep[consumedcnt] = '\0';
227 dbgtext("Path %s to alternate path(s):",
229 for (i=0; i < junction->referral_count; i++) {
231 junction->referral_list[i].alternate_path);
237 if (r->in.req.max_referral_level <= 2) {
238 max_referral_level = 2;
240 if (r->in.req.max_referral_level >= 3) {
241 max_referral_level = 3;
244 r->out.resp = talloc_zero(r, struct dfs_referral_resp);
245 if (r->out.resp == NULL) {
246 return NT_STATUS_NO_MEMORY;
249 r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
250 r->out.resp->nb_referrals = junction->referral_count;
252 r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
254 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
257 r->out.resp->referral_entries = talloc_zero_array(r,
258 struct dfs_referral_type,
259 r->out.resp->nb_referrals);
260 if (r->out.resp->referral_entries == NULL) {
261 return NT_STATUS_NO_MEMORY;
264 switch (max_referral_level) {
266 for(i=0; i < junction->referral_count; i++) {
267 struct referral *ref = &junction->referral_list[i];
268 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
269 struct dfs_referral_type *t =
270 &r->out.resp->referral_entries[i];
271 struct dfs_referral_v2 *v2 = &t->referral.v2;
274 v2->size = VERSION2_REFERRAL_SIZE;
276 v2->server_type = DFS_SERVER_ROOT;
278 v2->server_type = DFS_SERVER_NON_ROOT;
281 v2->proximity = ref->proximity;
283 v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
284 if (v2->DFS_path == NULL) {
285 return NT_STATUS_NO_MEMORY;
287 v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
288 if (v2->DFS_alt_path == NULL) {
289 return NT_STATUS_NO_MEMORY;
291 v2->netw_address = talloc_strdup(mem_ctx,
292 ref->alternate_path);
293 if (v2->netw_address == NULL) {
294 return NT_STATUS_NO_MEMORY;
300 for(i=0; i < junction->referral_count; i++) {
301 struct referral *ref = &junction->referral_list[i];
302 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
303 struct dfs_referral_type *t =
304 &r->out.resp->referral_entries[i];
305 struct dfs_referral_v3 *v3 = &t->referral.v3;
306 struct dfs_normal_referral *r1 = &v3->referrals.r1;
309 v3->size = VERSION3_REFERRAL_SIZE;
311 v3->server_type = DFS_SERVER_ROOT;
313 v3->server_type = DFS_SERVER_NON_ROOT;
317 r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
318 if (r1->DFS_path == NULL) {
319 return NT_STATUS_NO_MEMORY;
321 r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
322 if (r1->DFS_alt_path == NULL) {
323 return NT_STATUS_NO_MEMORY;
325 r1->netw_address = talloc_strdup(mem_ctx,
326 ref->alternate_path);
327 if (r1->netw_address == NULL) {
328 return NT_STATUS_NO_MEMORY;
333 DEBUG(0,("Invalid dfs referral version: %d\n",
334 max_referral_level));
335 return NT_STATUS_INVALID_LEVEL;
339 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
345 static NTSTATUS vfswrap_snap_check_path(struct vfs_handle_struct *handle,
347 const char *service_path,
350 return NT_STATUS_NOT_SUPPORTED;
353 static NTSTATUS vfswrap_snap_create(struct vfs_handle_struct *handle,
355 const char *base_volume,
361 return NT_STATUS_NOT_SUPPORTED;
364 static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle,
369 return NT_STATUS_NOT_SUPPORTED;
372 /* Directory operations */
374 static DIR *vfswrap_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32_t attr)
378 START_PROFILE(syscall_opendir);
379 result = opendir(fname);
380 END_PROFILE(syscall_opendir);
384 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
391 START_PROFILE(syscall_fdopendir);
392 result = sys_fdopendir(fsp->fh->fd);
393 END_PROFILE(syscall_fdopendir);
398 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
400 SMB_STRUCT_STAT *sbuf)
402 struct dirent *result;
404 START_PROFILE(syscall_readdir);
405 result = readdir(dirp);
406 END_PROFILE(syscall_readdir);
408 /* Default Posix readdir() does not give us stat info.
409 * Set to invalid to indicate we didn't return this info. */
410 SET_STAT_INVALID(*sbuf);
411 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
412 if (result != NULL) {
413 /* See if we can efficiently return this. */
415 int flags = (lp_posix_pathnames() ?
416 AT_SYMLINK_NOFOLLOW : 0);
417 int ret = fstatat(dirfd(dirp),
422 init_stat_ex_from_stat(sbuf,
424 lp_fake_directory_create_times(
425 SNUM(handle->conn)));
433 static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
434 const struct smb_filename *fname,
436 struct readdir_attr_data **attr_data)
438 return NT_STATUS_NOT_SUPPORTED;
441 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
443 START_PROFILE(syscall_seekdir);
444 seekdir(dirp, offset);
445 END_PROFILE(syscall_seekdir);
448 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
451 START_PROFILE(syscall_telldir);
452 result = telldir(dirp);
453 END_PROFILE(syscall_telldir);
457 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
459 START_PROFILE(syscall_rewinddir);
461 END_PROFILE(syscall_rewinddir);
464 static int vfswrap_mkdir(vfs_handle_struct *handle, const char *path, mode_t mode)
467 bool has_dacl = False;
470 START_PROFILE(syscall_mkdir);
472 if (lp_inherit_acls(SNUM(handle->conn))
473 && parent_dirname(talloc_tos(), path, &parent, NULL)
474 && (has_dacl = directory_has_default_acl(handle->conn, parent))) {
475 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
480 result = mkdir(path, mode);
482 if (result == 0 && !has_dacl) {
484 * We need to do this as the default behavior of POSIX ACLs
485 * is to set the mask to be the requested group permission
486 * bits, not the group permission bits to be the requested
487 * group permission bits. This is not what we want, as it will
488 * mess up any inherited ACL bits that were set. JRA.
490 int saved_errno = errno; /* We may get ENOSYS */
491 if ((SMB_VFS_CHMOD_ACL(handle->conn, path, mode) == -1) && (errno == ENOSYS))
495 END_PROFILE(syscall_mkdir);
499 static int vfswrap_rmdir(vfs_handle_struct *handle, const char *path)
503 START_PROFILE(syscall_rmdir);
504 result = rmdir(path);
505 END_PROFILE(syscall_rmdir);
509 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
513 START_PROFILE(syscall_closedir);
514 result = closedir(dirp);
515 END_PROFILE(syscall_closedir);
519 static void vfswrap_init_search_op(vfs_handle_struct *handle,
522 /* Default behavior is a NOOP */
525 /* File operations */
527 static int vfswrap_open(vfs_handle_struct *handle,
528 struct smb_filename *smb_fname,
529 files_struct *fsp, int flags, mode_t mode)
533 START_PROFILE(syscall_open);
535 if (smb_fname->stream_name) {
540 result = open(smb_fname->base_name, flags, mode);
542 END_PROFILE(syscall_open);
546 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
547 struct smb_request *req,
548 uint16_t root_dir_fid,
549 struct smb_filename *smb_fname,
550 uint32_t access_mask,
551 uint32_t share_access,
552 uint32_t create_disposition,
553 uint32_t create_options,
554 uint32_t file_attributes,
555 uint32_t oplock_request,
556 struct smb2_lease *lease,
557 uint64_t allocation_size,
558 uint32_t private_flags,
559 struct security_descriptor *sd,
560 struct ea_list *ea_list,
561 files_struct **result,
563 const struct smb2_create_blobs *in_context_blobs,
564 struct smb2_create_blobs *out_context_blobs)
566 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
567 access_mask, share_access,
568 create_disposition, create_options,
569 file_attributes, oplock_request, lease,
570 allocation_size, private_flags,
572 pinfo, in_context_blobs, out_context_blobs);
575 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
579 START_PROFILE(syscall_close);
580 result = fd_close_posix(fsp);
581 END_PROFILE(syscall_close);
585 static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
589 START_PROFILE_BYTES(syscall_read, n);
590 result = sys_read(fsp->fh->fd, data, n);
591 END_PROFILE_BYTES(syscall_read);
595 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
596 size_t n, off_t offset)
600 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
601 START_PROFILE_BYTES(syscall_pread, n);
602 result = sys_pread(fsp->fh->fd, data, n, offset);
603 END_PROFILE_BYTES(syscall_pread);
605 if (result == -1 && errno == ESPIPE) {
606 /* Maintain the fiction that pipes can be seeked (sought?) on. */
607 result = SMB_VFS_READ(fsp, data, n);
611 #else /* HAVE_PREAD */
615 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
616 if (curr == -1 && errno == ESPIPE) {
617 /* Maintain the fiction that pipes can be seeked (sought?) on. */
618 result = SMB_VFS_READ(fsp, data, n);
623 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
628 result = SMB_VFS_READ(fsp, data, n);
631 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
634 #endif /* HAVE_PREAD */
639 static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
643 START_PROFILE_BYTES(syscall_write, n);
644 result = sys_write(fsp->fh->fd, data, n);
645 END_PROFILE_BYTES(syscall_write);
649 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
650 size_t n, off_t offset)
654 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
655 START_PROFILE_BYTES(syscall_pwrite, n);
656 result = sys_pwrite(fsp->fh->fd, data, n, offset);
657 END_PROFILE_BYTES(syscall_pwrite);
659 if (result == -1 && errno == ESPIPE) {
660 /* Maintain the fiction that pipes can be sought on. */
661 result = SMB_VFS_WRITE(fsp, data, n);
664 #else /* HAVE_PWRITE */
668 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
673 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
677 result = SMB_VFS_WRITE(fsp, data, n);
680 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
683 #endif /* HAVE_PWRITE */
688 static void vfswrap_asys_finished(struct tevent_context *ev,
689 struct tevent_fd *fde,
690 uint16_t flags, void *p);
692 static bool vfswrap_init_asys_ctx(struct smbd_server_connection *conn)
694 struct asys_context *ctx;
695 struct tevent_fd *fde;
699 if (conn->asys_ctx != NULL) {
703 ret = asys_context_init(&ctx, aio_pending_size);
705 DEBUG(1, ("asys_context_init failed: %s\n", strerror(ret)));
709 fd = asys_signalfd(ctx);
711 ret = set_blocking(fd, false);
713 DBG_WARNING("set_blocking failed: %s\n", strerror(errno));
717 fde = tevent_add_fd(conn->ev_ctx, conn, fd, TEVENT_FD_READ,
718 vfswrap_asys_finished, ctx);
720 DEBUG(1, ("tevent_add_fd failed\n"));
724 conn->asys_ctx = ctx;
725 conn->asys_fde = fde;
729 asys_context_destroy(ctx);
733 struct vfswrap_asys_state {
734 struct asys_context *asys_ctx;
735 struct tevent_req *req;
738 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
739 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
742 static int vfswrap_asys_state_destructor(struct vfswrap_asys_state *s)
744 asys_cancel(s->asys_ctx, s->req);
748 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
750 struct tevent_context *ev,
751 struct files_struct *fsp,
753 size_t n, off_t offset)
755 struct tevent_req *req;
756 struct vfswrap_asys_state *state;
759 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
763 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
765 return tevent_req_post(req, ev);
767 state->asys_ctx = handle->conn->sconn->asys_ctx;
770 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
771 state->profile_bytes, n);
772 ret = asys_pread(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
774 tevent_req_error(req, ret);
775 return tevent_req_post(req, ev);
777 talloc_set_destructor(state, vfswrap_asys_state_destructor);
782 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
784 struct tevent_context *ev,
785 struct files_struct *fsp,
787 size_t n, off_t offset)
789 struct tevent_req *req;
790 struct vfswrap_asys_state *state;
793 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
797 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
799 return tevent_req_post(req, ev);
801 state->asys_ctx = handle->conn->sconn->asys_ctx;
804 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
805 state->profile_bytes, n);
806 ret = asys_pwrite(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
808 tevent_req_error(req, ret);
809 return tevent_req_post(req, ev);
811 talloc_set_destructor(state, vfswrap_asys_state_destructor);
816 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
818 struct tevent_context *ev,
819 struct files_struct *fsp)
821 struct tevent_req *req;
822 struct vfswrap_asys_state *state;
825 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
829 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
831 return tevent_req_post(req, ev);
833 state->asys_ctx = handle->conn->sconn->asys_ctx;
836 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
837 state->profile_basic);
838 ret = asys_fsync(state->asys_ctx, fsp->fh->fd, req);
840 tevent_req_error(req, ret);
841 return tevent_req_post(req, ev);
843 talloc_set_destructor(state, vfswrap_asys_state_destructor);
848 static void vfswrap_asys_finished(struct tevent_context *ev,
849 struct tevent_fd *fde,
850 uint16_t flags, void *p)
852 struct asys_context *asys_ctx = (struct asys_context *)p;
853 struct asys_result results[outstanding_aio_calls];
856 if ((flags & TEVENT_FD_READ) == 0) {
860 ret = asys_results(asys_ctx, results, outstanding_aio_calls);
862 DEBUG(1, ("asys_results returned %s\n", strerror(-ret)));
866 for (i=0; i<ret; i++) {
867 struct asys_result *result = &results[i];
868 struct tevent_req *req;
869 struct vfswrap_asys_state *state;
871 if ((result->ret == -1) && (result->err == ECANCELED)) {
875 req = talloc_get_type_abort(result->private_data,
877 state = tevent_req_data(req, struct vfswrap_asys_state);
879 talloc_set_destructor(state, NULL);
881 SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
882 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
883 state->ret = result->ret;
884 state->err = result->err;
885 tevent_req_defer_callback(req, ev);
886 tevent_req_done(req);
890 static ssize_t vfswrap_asys_ssize_t_recv(struct tevent_req *req, int *err)
892 struct vfswrap_asys_state *state = tevent_req_data(
893 req, struct vfswrap_asys_state);
895 if (tevent_req_is_unix_error(req, err)) {
902 static int vfswrap_asys_int_recv(struct tevent_req *req, int *err)
904 struct vfswrap_asys_state *state = tevent_req_data(
905 req, struct vfswrap_asys_state);
907 if (tevent_req_is_unix_error(req, err)) {
914 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
918 START_PROFILE(syscall_lseek);
920 /* Cope with 'stat' file opens. */
921 if (fsp->fh->fd != -1)
922 result = lseek(fsp->fh->fd, offset, whence);
925 * We want to maintain the fiction that we can seek
926 * on a fifo for file system purposes. This allows
927 * people to set up UNIX fifo's that feed data to Windows
931 if((result == -1) && (errno == ESPIPE)) {
936 END_PROFILE(syscall_lseek);
940 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
941 off_t offset, size_t n)
945 START_PROFILE_BYTES(syscall_sendfile, n);
946 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
947 END_PROFILE_BYTES(syscall_sendfile);
951 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
959 START_PROFILE_BYTES(syscall_recvfile, n);
960 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
961 END_PROFILE_BYTES(syscall_recvfile);
965 static int vfswrap_rename(vfs_handle_struct *handle,
966 const struct smb_filename *smb_fname_src,
967 const struct smb_filename *smb_fname_dst)
971 START_PROFILE(syscall_rename);
973 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
978 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
981 END_PROFILE(syscall_rename);
985 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
990 START_PROFILE(syscall_fsync);
991 result = fsync(fsp->fh->fd);
992 END_PROFILE(syscall_fsync);
999 static int vfswrap_stat(vfs_handle_struct *handle,
1000 struct smb_filename *smb_fname)
1004 START_PROFILE(syscall_stat);
1006 if (smb_fname->stream_name) {
1011 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1012 lp_fake_directory_create_times(SNUM(handle->conn)));
1014 END_PROFILE(syscall_stat);
1018 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1022 START_PROFILE(syscall_fstat);
1023 result = sys_fstat(fsp->fh->fd,
1024 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1025 END_PROFILE(syscall_fstat);
1029 static int vfswrap_lstat(vfs_handle_struct *handle,
1030 struct smb_filename *smb_fname)
1034 START_PROFILE(syscall_lstat);
1036 if (smb_fname->stream_name) {
1041 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1042 lp_fake_directory_create_times(SNUM(handle->conn)));
1044 END_PROFILE(syscall_lstat);
1048 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1050 enum vfs_translate_direction direction,
1051 TALLOC_CTX *mem_ctx,
1054 return NT_STATUS_NONE_MAPPED;
1058 * Implement the default fsctl operation.
1060 static bool vfswrap_logged_ioctl_message = false;
1062 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1063 struct files_struct *fsp,
1066 uint16_t req_flags, /* Needed for UNICODE ... */
1067 const uint8_t *_in_data,
1069 uint8_t **_out_data,
1070 uint32_t max_out_len,
1073 const char *in_data = (const char *)_in_data;
1074 char **out_data = (char **)_out_data;
1078 case FSCTL_SET_SPARSE:
1080 bool set_sparse = true;
1082 if (in_len >= 1 && in_data[0] == 0) {
1086 status = file_set_sparse(handle->conn, fsp, set_sparse);
1088 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1089 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1090 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1091 nt_errstr(status)));
1096 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1098 unsigned char objid[16];
1099 char *return_data = NULL;
1101 /* This should return the object-id on this file.
1102 * I think I'll make this be the inode+dev. JRA.
1105 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1106 fsp_fnum_dbg(fsp)));
1108 *out_len = MIN(max_out_len, 64);
1110 /* Hmmm, will this cause problems if less data asked for? */
1111 return_data = talloc_array(ctx, char, 64);
1112 if (return_data == NULL) {
1113 return NT_STATUS_NO_MEMORY;
1116 /* For backwards compatibility only store the dev/inode. */
1117 push_file_id_16(return_data, &fsp->file_id);
1118 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1119 push_file_id_16(return_data+32, &fsp->file_id);
1120 memset(return_data+48, 0, 16);
1121 *out_data = return_data;
1122 return NT_STATUS_OK;
1125 case FSCTL_GET_REPARSE_POINT:
1127 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1128 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1129 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1130 return NT_STATUS_NOT_A_REPARSE_POINT;
1133 case FSCTL_SET_REPARSE_POINT:
1135 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1136 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1137 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1138 return NT_STATUS_NOT_A_REPARSE_POINT;
1141 case FSCTL_GET_SHADOW_COPY_DATA:
1144 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1145 * and return their volume names. If max_data_count is 16, then it is just
1146 * asking for the number of volumes and length of the combined names.
1148 * pdata is the data allocated by our caller, but that uses
1149 * total_data_count (which is 0 in our case) rather than max_data_count.
1150 * Allocate the correct amount and return the pointer to let
1151 * it be deallocated when we return.
1153 struct shadow_copy_data *shadow_data = NULL;
1154 bool labels = False;
1155 uint32_t labels_data_count = 0;
1157 char *cur_pdata = NULL;
1159 if (max_out_len < 16) {
1160 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1162 return NT_STATUS_INVALID_PARAMETER;
1165 if (max_out_len > 16) {
1169 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1170 if (shadow_data == NULL) {
1171 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1172 return NT_STATUS_NO_MEMORY;
1176 * Call the VFS routine to actually do the work.
1178 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1181 /* broken module didn't set errno on error */
1182 status = NT_STATUS_UNSUCCESSFUL;
1184 status = map_nt_error_from_unix(errno);
1185 if (NT_STATUS_EQUAL(status,
1186 NT_STATUS_NOT_SUPPORTED)) {
1190 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1191 "connectpath %s, failed - %s.\n",
1192 fsp->conn->connectpath,
1193 nt_errstr(status)));
1194 TALLOC_FREE(shadow_data);
1198 labels_data_count = (shadow_data->num_volumes * 2 *
1199 sizeof(SHADOW_COPY_LABEL)) + 2;
1204 *out_len = 12 + labels_data_count;
1207 if (max_out_len < *out_len) {
1208 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1209 max_out_len, *out_len));
1210 TALLOC_FREE(shadow_data);
1211 return NT_STATUS_BUFFER_TOO_SMALL;
1214 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1215 if (cur_pdata == NULL) {
1216 TALLOC_FREE(shadow_data);
1217 return NT_STATUS_NO_MEMORY;
1220 *out_data = cur_pdata;
1222 /* num_volumes 4 bytes */
1223 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1226 /* num_labels 4 bytes */
1227 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1230 /* needed_data_count 4 bytes */
1231 SIVAL(cur_pdata, 8, labels_data_count);
1235 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1236 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1237 if (labels && shadow_data->labels) {
1238 for (i=0; i<shadow_data->num_volumes; i++) {
1240 status = srvstr_push(cur_pdata, req_flags,
1241 cur_pdata, shadow_data->labels[i],
1242 2 * sizeof(SHADOW_COPY_LABEL),
1243 STR_UNICODE|STR_TERMINATE, &len);
1244 if (!NT_STATUS_IS_OK(status)) {
1245 TALLOC_FREE(*out_data);
1246 TALLOC_FREE(shadow_data);
1249 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1250 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1254 TALLOC_FREE(shadow_data);
1256 return NT_STATUS_OK;
1259 case FSCTL_FIND_FILES_BY_SID:
1261 /* pretend this succeeded -
1263 * we have to send back a list with all files owned by this SID
1265 * but I have to check that --metze
1271 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1272 fsp_fnum_dbg(fsp)));
1275 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1276 return NT_STATUS_INVALID_PARAMETER;
1279 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1281 /* unknown 4 bytes: this is not the length of the sid :-( */
1282 /*unknown = IVAL(pdata,0);*/
1284 if (!sid_parse(in_data + 4, sid_len, &sid)) {
1285 return NT_STATUS_INVALID_PARAMETER;
1287 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1289 if (!sid_to_uid(&sid, &uid)) {
1290 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1291 sid_string_dbg(&sid),
1292 (unsigned long)sid_len));
1296 /* we can take a look at the find source :-)
1298 * find ./ -uid $uid -name '*' is what we need here
1301 * and send 4bytes len and then NULL terminated unicode strings
1304 * but I don't know how to deal with the paged results
1305 * (maybe we can hang the result anywhere in the fsp struct)
1307 * but I don't know how to deal with the paged results
1308 * (maybe we can hang the result anywhere in the fsp struct)
1310 * we don't send all files at once
1311 * and at the next we should *not* start from the beginning,
1312 * so we have to cache the result
1317 /* this works for now... */
1318 return NT_STATUS_OK;
1321 case FSCTL_QUERY_ALLOCATED_RANGES:
1323 /* FIXME: This is just a dummy reply, telling that all of the
1324 * file is allocated. MKS cp needs that.
1325 * Adding the real allocated ranges via FIEMAP on Linux
1326 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1327 * this FSCTL correct for sparse files.
1329 uint64_t offset, length;
1330 char *out_data_tmp = NULL;
1333 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1335 return NT_STATUS_INVALID_PARAMETER;
1338 if (max_out_len < 16) {
1339 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1341 return NT_STATUS_INVALID_PARAMETER;
1344 offset = BVAL(in_data,0);
1345 length = BVAL(in_data,8);
1347 if (offset + length < offset) {
1348 /* No 64-bit integer wrap. */
1349 return NT_STATUS_INVALID_PARAMETER;
1352 /* Shouldn't this be SMB_VFS_STAT ... ? */
1353 status = vfs_stat_fsp(fsp);
1354 if (!NT_STATUS_IS_OK(status)) {
1359 out_data_tmp = talloc_array(ctx, char, *out_len);
1360 if (out_data_tmp == NULL) {
1361 DEBUG(10, ("unable to allocate memory for response\n"));
1362 return NT_STATUS_NO_MEMORY;
1365 if (offset > fsp->fsp_name->st.st_ex_size ||
1366 fsp->fsp_name->st.st_ex_size == 0 ||
1368 memset(out_data_tmp, 0, *out_len);
1370 uint64_t end = offset + length;
1371 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1372 SBVAL(out_data_tmp, 0, 0);
1373 SBVAL(out_data_tmp, 8, end);
1376 *out_data = out_data_tmp;
1378 return NT_STATUS_OK;
1381 case FSCTL_IS_VOLUME_DIRTY:
1383 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1384 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1386 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1387 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1389 return NT_STATUS_INVALID_PARAMETER;
1394 * Only print once ... unfortunately there could be lots of
1395 * different FSCTLs that are called.
1397 if (!vfswrap_logged_ioctl_message) {
1398 vfswrap_logged_ioctl_message = true;
1399 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1400 __func__, function));
1404 return NT_STATUS_NOT_SUPPORTED;
1407 struct vfs_cc_state {
1412 static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *handle,
1413 TALLOC_CTX *mem_ctx,
1414 struct tevent_context *ev,
1415 struct files_struct *src_fsp,
1417 struct files_struct *dest_fsp,
1421 struct tevent_req *req;
1422 struct vfs_cc_state *vfs_cc_state;
1425 DEBUG(10, ("performing server side copy chunk of length %lu\n",
1426 (unsigned long)num));
1428 req = tevent_req_create(mem_ctx, &vfs_cc_state, struct vfs_cc_state);
1433 vfs_cc_state->buf = talloc_array(vfs_cc_state, uint8_t,
1434 MIN(num, 8*1024*1024));
1435 if (tevent_req_nomem(vfs_cc_state->buf, req)) {
1436 return tevent_req_post(req, ev);
1439 status = vfs_stat_fsp(src_fsp);
1440 if (tevent_req_nterror(req, status)) {
1441 return tevent_req_post(req, ev);
1444 if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
1446 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1447 * If the SourceOffset or SourceOffset + Length extends beyond
1448 * the end of file, the server SHOULD<240> treat this as a
1449 * STATUS_END_OF_FILE error.
1451 * <240> Section 3.3.5.15.6: Windows servers will return
1452 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1454 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1455 return tevent_req_post(req, ev);
1458 /* could use 2.6.33+ sendfile here to do this in kernel */
1459 while (vfs_cc_state->copied < num) {
1461 struct lock_struct lck;
1464 off_t this_num = MIN(talloc_array_length(vfs_cc_state->buf),
1465 num - vfs_cc_state->copied);
1467 if (src_fsp->op == NULL) {
1468 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1469 return tevent_req_post(req, ev);
1471 init_strict_lock_struct(src_fsp,
1472 src_fsp->op->global->open_persistent_id,
1478 if (!SMB_VFS_STRICT_LOCK(src_fsp->conn, src_fsp, &lck)) {
1479 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1480 return tevent_req_post(req, ev);
1483 ret = SMB_VFS_PREAD(src_fsp, vfs_cc_state->buf,
1486 saved_errno = errno;
1489 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1492 errno = saved_errno;
1493 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1494 return tevent_req_post(req, ev);
1496 if (ret != this_num) {
1497 /* zero tolerance for short reads */
1498 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1499 return tevent_req_post(req, ev);
1504 if (dest_fsp->op == NULL) {
1505 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1506 return tevent_req_post(req, ev);
1509 init_strict_lock_struct(dest_fsp,
1510 dest_fsp->op->global->open_persistent_id,
1516 if (!SMB_VFS_STRICT_LOCK(dest_fsp->conn, dest_fsp, &lck)) {
1517 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1518 return tevent_req_post(req, ev);
1521 ret = SMB_VFS_PWRITE(dest_fsp, vfs_cc_state->buf,
1522 this_num, dest_off);
1524 saved_errno = errno;
1527 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1530 errno = saved_errno;
1531 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1532 return tevent_req_post(req, ev);
1534 if (ret != this_num) {
1535 /* zero tolerance for short writes */
1536 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1537 return tevent_req_post(req, ev);
1541 vfs_cc_state->copied += this_num;
1544 tevent_req_done(req);
1545 return tevent_req_post(req, ev);
1548 static NTSTATUS vfswrap_copy_chunk_recv(struct vfs_handle_struct *handle,
1549 struct tevent_req *req,
1552 struct vfs_cc_state *vfs_cc_state = tevent_req_data(req,
1553 struct vfs_cc_state);
1556 if (tevent_req_is_nterror(req, &status)) {
1557 DEBUG(2, ("server side copy chunk failed: %s\n",
1558 nt_errstr(status)));
1560 tevent_req_received(req);
1564 *copied = vfs_cc_state->copied;
1565 DEBUG(10, ("server side copy chunk copied %lu\n",
1566 (unsigned long)*copied));
1567 tevent_req_received(req);
1569 return NT_STATUS_OK;
1572 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1573 TALLOC_CTX *mem_ctx,
1574 struct files_struct *fsp,
1575 struct smb_filename *smb_fname,
1576 uint16_t *_compression_fmt)
1578 return NT_STATUS_INVALID_DEVICE_REQUEST;
1581 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1582 TALLOC_CTX *mem_ctx,
1583 struct files_struct *fsp,
1584 uint16_t compression_fmt)
1586 return NT_STATUS_INVALID_DEVICE_REQUEST;
1589 /********************************************************************
1590 Given a stat buffer return the allocated size on disk, taking into
1591 account sparse files.
1592 ********************************************************************/
1593 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1594 struct files_struct *fsp,
1595 const SMB_STRUCT_STAT *sbuf)
1599 START_PROFILE(syscall_get_alloc_size);
1601 if(S_ISDIR(sbuf->st_ex_mode)) {
1606 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1607 /* The type of st_blocksize is blkcnt_t which *MUST* be
1608 signed (according to POSIX) and can be less than 64-bits.
1609 Ensure when we're converting to 64 bits wide we don't
1611 #if defined(SIZEOF_BLKCNT_T_8)
1612 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1613 #elif defined(SIZEOF_BLKCNT_T_4)
1615 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1616 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1619 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1623 * Some file systems do not allocate a block for very
1624 * small files. But for non-empty file should report a
1628 uint64_t filesize = get_file_size_stat(sbuf);
1630 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
1634 result = get_file_size_stat(sbuf);
1637 if (fsp && fsp->initial_allocation_size)
1638 result = MAX(result,fsp->initial_allocation_size);
1640 result = smb_roundup(handle->conn, result);
1643 END_PROFILE(syscall_get_alloc_size);
1647 static int vfswrap_unlink(vfs_handle_struct *handle,
1648 const struct smb_filename *smb_fname)
1652 START_PROFILE(syscall_unlink);
1654 if (smb_fname->stream_name) {
1658 result = unlink(smb_fname->base_name);
1661 END_PROFILE(syscall_unlink);
1665 static int vfswrap_chmod(vfs_handle_struct *handle, const char *path, mode_t mode)
1669 START_PROFILE(syscall_chmod);
1672 * We need to do this due to the fact that the default POSIX ACL
1673 * chmod modifies the ACL *mask* for the group owner, not the
1674 * group owner bits directly. JRA.
1679 int saved_errno = errno; /* We might get ENOSYS */
1680 if ((result = SMB_VFS_CHMOD_ACL(handle->conn, path, mode)) == 0) {
1681 END_PROFILE(syscall_chmod);
1684 /* Error - return the old errno. */
1685 errno = saved_errno;
1688 result = chmod(path, mode);
1689 END_PROFILE(syscall_chmod);
1693 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
1697 START_PROFILE(syscall_fchmod);
1700 * We need to do this due to the fact that the default POSIX ACL
1701 * chmod modifies the ACL *mask* for the group owner, not the
1702 * group owner bits directly. JRA.
1706 int saved_errno = errno; /* We might get ENOSYS */
1707 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
1708 END_PROFILE(syscall_fchmod);
1711 /* Error - return the old errno. */
1712 errno = saved_errno;
1715 #if defined(HAVE_FCHMOD)
1716 result = fchmod(fsp->fh->fd, mode);
1722 END_PROFILE(syscall_fchmod);
1726 static int vfswrap_chown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1730 START_PROFILE(syscall_chown);
1731 result = chown(path, uid, gid);
1732 END_PROFILE(syscall_chown);
1736 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
1741 START_PROFILE(syscall_fchown);
1742 result = fchown(fsp->fh->fd, uid, gid);
1743 END_PROFILE(syscall_fchown);
1751 static int vfswrap_lchown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1755 START_PROFILE(syscall_lchown);
1756 result = lchown(path, uid, gid);
1757 END_PROFILE(syscall_lchown);
1761 static int vfswrap_chdir(vfs_handle_struct *handle, const char *path)
1765 START_PROFILE(syscall_chdir);
1766 result = chdir(path);
1767 END_PROFILE(syscall_chdir);
1771 static char *vfswrap_getwd(vfs_handle_struct *handle)
1775 START_PROFILE(syscall_getwd);
1776 result = sys_getwd();
1777 END_PROFILE(syscall_getwd);
1781 /*********************************************************************
1782 nsec timestamp resolution call. Convert down to whatever the underlying
1783 system will support.
1784 **********************************************************************/
1786 static int vfswrap_ntimes(vfs_handle_struct *handle,
1787 const struct smb_filename *smb_fname,
1788 struct smb_file_time *ft)
1792 START_PROFILE(syscall_ntimes);
1794 if (smb_fname->stream_name) {
1800 if (null_timespec(ft->atime)) {
1801 ft->atime= smb_fname->st.st_ex_atime;
1804 if (null_timespec(ft->mtime)) {
1805 ft->mtime = smb_fname->st.st_ex_mtime;
1808 if (!null_timespec(ft->create_time)) {
1809 set_create_timespec_ea(handle->conn,
1814 if ((timespec_compare(&ft->atime,
1815 &smb_fname->st.st_ex_atime) == 0) &&
1816 (timespec_compare(&ft->mtime,
1817 &smb_fname->st.st_ex_mtime) == 0)) {
1822 #if defined(HAVE_UTIMENSAT)
1824 struct timespec ts[2];
1827 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
1829 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
1831 if (!((result == -1) && (errno == ENOSYS))) {
1835 #if defined(HAVE_UTIMES)
1837 struct timeval tv[2];
1838 tv[0] = convert_timespec_to_timeval(ft->atime);
1839 tv[1] = convert_timespec_to_timeval(ft->mtime);
1840 result = utimes(smb_fname->base_name, tv);
1842 result = utimes(smb_fname->base_name, NULL);
1844 if (!((result == -1) && (errno == ENOSYS))) {
1848 #if defined(HAVE_UTIME)
1850 struct utimbuf times;
1851 times.actime = convert_timespec_to_time_t(ft->atime);
1852 times.modtime = convert_timespec_to_time_t(ft->mtime);
1853 result = utime(smb_fname->base_name, ×);
1855 result = utime(smb_fname->base_name, NULL);
1857 if (!((result == -1) && (errno == ENOSYS))) {
1865 END_PROFILE(syscall_ntimes);
1869 /*********************************************************************
1870 A version of ftruncate that will write the space on disk if strict
1872 **********************************************************************/
1874 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1876 off_t space_to_write;
1877 uint64_t space_avail;
1878 uint64_t bsize,dfree,dsize;
1881 SMB_STRUCT_STAT *pst;
1883 status = vfs_stat_fsp(fsp);
1884 if (!NT_STATUS_IS_OK(status)) {
1887 pst = &fsp->fsp_name->st;
1890 if (S_ISFIFO(pst->st_ex_mode))
1894 if (pst->st_ex_size == len)
1897 /* Shrink - just ftruncate. */
1898 if (pst->st_ex_size > len)
1899 return ftruncate(fsp->fh->fd, len);
1901 space_to_write = len - pst->st_ex_size;
1903 /* for allocation try fallocate first. This can fail on some
1904 platforms e.g. when the filesystem doesn't support it and no
1905 emulation is being done by the libc (like on AIX with JFS1). In that
1906 case we do our own emulation. fallocate implementations can
1907 return ENOTSUP or EINVAL in cases like that. */
1908 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
1909 if (ret == -1 && errno == ENOSPC) {
1915 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
1916 "error %d. Falling back to slow manual allocation\n", errno));
1918 /* available disk space is enough or not? */
1919 space_avail = get_dfree_info(fsp->conn,
1920 fsp->fsp_name->base_name,
1921 &bsize, &dfree, &dsize);
1922 /* space_avail is 1k blocks */
1923 if (space_avail == (uint64_t)-1 ||
1924 ((uint64_t)space_to_write/1024 > space_avail) ) {
1929 /* Write out the real space on disk. */
1930 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
1938 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1941 SMB_STRUCT_STAT *pst;
1945 START_PROFILE(syscall_ftruncate);
1947 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
1948 result = strict_allocate_ftruncate(handle, fsp, len);
1949 END_PROFILE(syscall_ftruncate);
1953 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
1954 ftruncate if the system supports it. Then I discovered that
1955 you can have some filesystems that support ftruncate
1956 expansion and some that don't! On Linux fat can't do
1957 ftruncate extend but ext2 can. */
1959 result = ftruncate(fsp->fh->fd, len);
1961 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
1962 extend a file with ftruncate. Provide alternate implementation
1965 /* Do an fstat to see if the file is longer than the requested
1966 size in which case the ftruncate above should have
1967 succeeded or shorter, in which case seek to len - 1 and
1968 write 1 byte of zero */
1969 status = vfs_stat_fsp(fsp);
1970 if (!NT_STATUS_IS_OK(status)) {
1974 /* We need to update the files_struct after successful ftruncate */
1979 pst = &fsp->fsp_name->st;
1982 if (S_ISFIFO(pst->st_ex_mode)) {
1988 if (pst->st_ex_size == len) {
1993 if (pst->st_ex_size > len) {
1994 /* the ftruncate should have worked */
1998 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2006 END_PROFILE(syscall_ftruncate);
2010 static int vfswrap_fallocate(vfs_handle_struct *handle,
2018 START_PROFILE(syscall_fallocate);
2020 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2022 * posix_fallocate returns 0 on success, errno on error
2023 * and doesn't set errno. Make it behave like fallocate()
2024 * which returns -1, and sets errno on failure.
2031 /* sys_fallocate handles filtering of unsupported mode flags */
2032 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2034 END_PROFILE(syscall_fallocate);
2038 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2042 START_PROFILE(syscall_fcntl_lock);
2043 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2044 END_PROFILE(syscall_fcntl_lock);
2048 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2049 uint32_t share_mode, uint32_t access_mask)
2051 START_PROFILE(syscall_kernel_flock);
2052 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2053 END_PROFILE(syscall_kernel_flock);
2057 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2061 START_PROFILE(syscall_fcntl_getlock);
2062 result = fcntl_getlock(fsp->fh->fd, poffset, pcount, ptype, ppid);
2063 END_PROFILE(syscall_fcntl_getlock);
2067 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2072 START_PROFILE(syscall_linux_setlease);
2074 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2075 result = linux_setlease(fsp->fh->fd, leasetype);
2079 END_PROFILE(syscall_linux_setlease);
2083 static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2087 START_PROFILE(syscall_symlink);
2088 result = symlink(oldpath, newpath);
2089 END_PROFILE(syscall_symlink);
2093 static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
2097 START_PROFILE(syscall_readlink);
2098 result = readlink(path, buf, bufsiz);
2099 END_PROFILE(syscall_readlink);
2103 static int vfswrap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2107 START_PROFILE(syscall_link);
2108 result = link(oldpath, newpath);
2109 END_PROFILE(syscall_link);
2113 static int vfswrap_mknod(vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev)
2117 START_PROFILE(syscall_mknod);
2118 result = sys_mknod(pathname, mode, dev);
2119 END_PROFILE(syscall_mknod);
2123 static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
2127 START_PROFILE(syscall_realpath);
2128 #ifdef REALPATH_TAKES_NULL
2129 result = realpath(path, NULL);
2131 result = SMB_MALLOC_ARRAY(char, PATH_MAX+1);
2133 char *resolved_path = realpath(path, result);
2134 if (!resolved_path) {
2137 /* SMB_ASSERT(result == resolved_path) ? */
2138 result = resolved_path;
2142 END_PROFILE(syscall_realpath);
2146 static int vfswrap_chflags(vfs_handle_struct *handle, const char *path,
2150 return chflags(path, flags);
2157 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2158 const SMB_STRUCT_STAT *sbuf)
2162 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2166 key.devid = sbuf->st_ex_dev;
2167 key.inode = sbuf->st_ex_ino;
2168 /* key.extid is unused by default. */
2173 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2174 struct files_struct *fsp,
2176 TALLOC_CTX *mem_ctx,
2177 unsigned int *pnum_streams,
2178 struct stream_struct **pstreams)
2180 SMB_STRUCT_STAT sbuf;
2181 struct stream_struct *tmp_streams = NULL;
2184 if ((fsp != NULL) && (fsp->is_directory)) {
2186 * No default streams on directories
2191 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2192 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2195 struct smb_filename smb_fname;
2197 ZERO_STRUCT(smb_fname);
2198 smb_fname.base_name = discard_const_p(char, fname);
2200 if (lp_posix_pathnames()) {
2201 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname);
2203 ret = SMB_VFS_STAT(handle->conn, &smb_fname);
2205 sbuf = smb_fname.st;
2209 return map_nt_error_from_unix(errno);
2212 if (S_ISDIR(sbuf.st_ex_mode)) {
2216 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2217 (*pnum_streams) + 1);
2218 if (tmp_streams == NULL) {
2219 return NT_STATUS_NO_MEMORY;
2221 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2222 if (tmp_streams[*pnum_streams].name == NULL) {
2223 return NT_STATUS_NO_MEMORY;
2225 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2226 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2229 *pstreams = tmp_streams;
2231 return NT_STATUS_OK;
2234 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2237 TALLOC_CTX *mem_ctx,
2241 * Don't fall back to get_real_filename so callers can differentiate
2242 * between a full directory scan and an actual case-insensitive stat.
2248 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2251 return handle->conn->connectpath;
2254 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2255 struct byte_range_lock *br_lck,
2256 struct lock_struct *plock,
2259 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2261 /* Note: blr is not used in the default implementation. */
2262 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2265 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2266 struct messaging_context *msg_ctx,
2267 struct byte_range_lock *br_lck,
2268 const struct lock_struct *plock)
2270 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2272 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2275 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2276 struct byte_range_lock *br_lck,
2277 struct lock_struct *plock)
2279 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2281 /* Note: blr is not used in the default implementation. */
2282 return brl_lock_cancel_default(br_lck, plock);
2285 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2287 struct lock_struct *plock)
2289 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2290 plock->lock_type == WRITE_LOCK);
2292 return strict_lock_default(fsp, plock);
2295 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2297 struct lock_struct *plock)
2299 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2300 plock->lock_type == WRITE_LOCK);
2302 strict_unlock_default(fsp, plock);
2305 /* NT ACL operations. */
2307 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2309 uint32_t security_info,
2310 TALLOC_CTX *mem_ctx,
2311 struct security_descriptor **ppdesc)
2315 START_PROFILE(fget_nt_acl);
2316 result = posix_fget_nt_acl(fsp, security_info,
2318 END_PROFILE(fget_nt_acl);
2322 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2324 uint32_t security_info,
2325 TALLOC_CTX *mem_ctx,
2326 struct security_descriptor **ppdesc)
2330 START_PROFILE(get_nt_acl);
2331 result = posix_get_nt_acl(handle->conn, name, security_info,
2333 END_PROFILE(get_nt_acl);
2337 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2341 START_PROFILE(fset_nt_acl);
2342 result = set_nt_acl(fsp, security_info_sent, psd);
2343 END_PROFILE(fset_nt_acl);
2347 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2348 struct smb_filename *file,
2349 struct security_acl *sacl,
2350 uint32_t access_requested,
2351 uint32_t access_denied)
2353 return NT_STATUS_OK; /* Nothing to do here ... */
2356 static int vfswrap_chmod_acl(vfs_handle_struct *handle, const char *name, mode_t mode)
2364 START_PROFILE(chmod_acl);
2365 result = chmod_acl(handle->conn, name, mode);
2366 END_PROFILE(chmod_acl);
2371 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2379 START_PROFILE(fchmod_acl);
2380 result = fchmod_acl(fsp, mode);
2381 END_PROFILE(fchmod_acl);
2386 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2388 SMB_ACL_TYPE_T type,
2389 TALLOC_CTX *mem_ctx)
2391 return sys_acl_get_file(handle, path_p, type, mem_ctx);
2394 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2396 TALLOC_CTX *mem_ctx)
2398 return sys_acl_get_fd(handle, fsp, mem_ctx);
2401 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2403 return sys_acl_set_file(handle, name, acltype, theacl);
2406 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2408 return sys_acl_set_fd(handle, fsp, theacl);
2411 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
2413 return sys_acl_delete_def_file(handle, path);
2416 /****************************************************************
2417 Extended attribute operations.
2418 *****************************************************************/
2420 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
2422 return getxattr(path, name, value, size);
2425 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2427 return fgetxattr(fsp->fh->fd, name, value, size);
2430 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
2432 return listxattr(path, list, size);
2435 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2437 return flistxattr(fsp->fh->fd, list, size);
2440 static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
2442 return removexattr(path, name);
2445 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2447 return fremovexattr(fsp->fh->fd, name);
2450 static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
2452 return setxattr(path, name, value, size, flags);
2455 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2457 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2460 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2465 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2466 const struct smb_filename *fname,
2467 SMB_STRUCT_STAT *sbuf)
2471 bool offline = false;
2473 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2477 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2478 #if defined(ENOTSUP)
2484 status = get_full_smb_filename(talloc_tos(), fname, &path);
2485 if (!NT_STATUS_IS_OK(status)) {
2486 errno = map_errno_from_nt_status(status);
2490 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2497 static int vfswrap_set_offline(struct vfs_handle_struct *handle,
2498 const struct smb_filename *fname)
2500 /* We don't know how to set offline bit by default, needs to be overriden in the vfs modules */
2501 #if defined(ENOTSUP)
2507 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2508 struct files_struct *fsp,
2509 TALLOC_CTX *mem_ctx,
2512 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2515 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2516 struct files_struct *fsp,
2517 const DATA_BLOB old_cookie,
2518 TALLOC_CTX *mem_ctx,
2519 DATA_BLOB *new_cookie)
2521 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2525 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2526 struct smb_request *smb1req,
2527 struct smbXsrv_open *op,
2528 const DATA_BLOB old_cookie,
2529 TALLOC_CTX *mem_ctx,
2530 struct files_struct **fsp,
2531 DATA_BLOB *new_cookie)
2533 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2534 old_cookie, mem_ctx,
2538 static struct vfs_fn_pointers vfs_default_fns = {
2539 /* Disk operations */
2541 .connect_fn = vfswrap_connect,
2542 .disconnect_fn = vfswrap_disconnect,
2543 .disk_free_fn = vfswrap_disk_free,
2544 .get_quota_fn = vfswrap_get_quota,
2545 .set_quota_fn = vfswrap_set_quota,
2546 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2547 .statvfs_fn = vfswrap_statvfs,
2548 .fs_capabilities_fn = vfswrap_fs_capabilities,
2549 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2550 .snap_check_path_fn = vfswrap_snap_check_path,
2551 .snap_create_fn = vfswrap_snap_create,
2552 .snap_delete_fn = vfswrap_snap_delete,
2554 /* Directory operations */
2556 .opendir_fn = vfswrap_opendir,
2557 .fdopendir_fn = vfswrap_fdopendir,
2558 .readdir_fn = vfswrap_readdir,
2559 .readdir_attr_fn = vfswrap_readdir_attr,
2560 .seekdir_fn = vfswrap_seekdir,
2561 .telldir_fn = vfswrap_telldir,
2562 .rewind_dir_fn = vfswrap_rewinddir,
2563 .mkdir_fn = vfswrap_mkdir,
2564 .rmdir_fn = vfswrap_rmdir,
2565 .closedir_fn = vfswrap_closedir,
2566 .init_search_op_fn = vfswrap_init_search_op,
2568 /* File operations */
2570 .open_fn = vfswrap_open,
2571 .create_file_fn = vfswrap_create_file,
2572 .close_fn = vfswrap_close,
2573 .read_fn = vfswrap_read,
2574 .pread_fn = vfswrap_pread,
2575 .pread_send_fn = vfswrap_pread_send,
2576 .pread_recv_fn = vfswrap_asys_ssize_t_recv,
2577 .write_fn = vfswrap_write,
2578 .pwrite_fn = vfswrap_pwrite,
2579 .pwrite_send_fn = vfswrap_pwrite_send,
2580 .pwrite_recv_fn = vfswrap_asys_ssize_t_recv,
2581 .lseek_fn = vfswrap_lseek,
2582 .sendfile_fn = vfswrap_sendfile,
2583 .recvfile_fn = vfswrap_recvfile,
2584 .rename_fn = vfswrap_rename,
2585 .fsync_fn = vfswrap_fsync,
2586 .fsync_send_fn = vfswrap_fsync_send,
2587 .fsync_recv_fn = vfswrap_asys_int_recv,
2588 .stat_fn = vfswrap_stat,
2589 .fstat_fn = vfswrap_fstat,
2590 .lstat_fn = vfswrap_lstat,
2591 .get_alloc_size_fn = vfswrap_get_alloc_size,
2592 .unlink_fn = vfswrap_unlink,
2593 .chmod_fn = vfswrap_chmod,
2594 .fchmod_fn = vfswrap_fchmod,
2595 .chown_fn = vfswrap_chown,
2596 .fchown_fn = vfswrap_fchown,
2597 .lchown_fn = vfswrap_lchown,
2598 .chdir_fn = vfswrap_chdir,
2599 .getwd_fn = vfswrap_getwd,
2600 .ntimes_fn = vfswrap_ntimes,
2601 .ftruncate_fn = vfswrap_ftruncate,
2602 .fallocate_fn = vfswrap_fallocate,
2603 .lock_fn = vfswrap_lock,
2604 .kernel_flock_fn = vfswrap_kernel_flock,
2605 .linux_setlease_fn = vfswrap_linux_setlease,
2606 .getlock_fn = vfswrap_getlock,
2607 .symlink_fn = vfswrap_symlink,
2608 .readlink_fn = vfswrap_readlink,
2609 .link_fn = vfswrap_link,
2610 .mknod_fn = vfswrap_mknod,
2611 .realpath_fn = vfswrap_realpath,
2612 .chflags_fn = vfswrap_chflags,
2613 .file_id_create_fn = vfswrap_file_id_create,
2614 .streaminfo_fn = vfswrap_streaminfo,
2615 .get_real_filename_fn = vfswrap_get_real_filename,
2616 .connectpath_fn = vfswrap_connectpath,
2617 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2618 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2619 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2620 .strict_lock_fn = vfswrap_strict_lock,
2621 .strict_unlock_fn = vfswrap_strict_unlock,
2622 .translate_name_fn = vfswrap_translate_name,
2623 .fsctl_fn = vfswrap_fsctl,
2624 .copy_chunk_send_fn = vfswrap_copy_chunk_send,
2625 .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
2626 .get_compression_fn = vfswrap_get_compression,
2627 .set_compression_fn = vfswrap_set_compression,
2629 /* NT ACL operations. */
2631 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2632 .get_nt_acl_fn = vfswrap_get_nt_acl,
2633 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2634 .audit_file_fn = vfswrap_audit_file,
2636 /* POSIX ACL operations. */
2638 .chmod_acl_fn = vfswrap_chmod_acl,
2639 .fchmod_acl_fn = vfswrap_fchmod_acl,
2641 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2642 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2643 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2644 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2645 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2646 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2647 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2649 /* EA operations. */
2650 .getxattr_fn = vfswrap_getxattr,
2651 .fgetxattr_fn = vfswrap_fgetxattr,
2652 .listxattr_fn = vfswrap_listxattr,
2653 .flistxattr_fn = vfswrap_flistxattr,
2654 .removexattr_fn = vfswrap_removexattr,
2655 .fremovexattr_fn = vfswrap_fremovexattr,
2656 .setxattr_fn = vfswrap_setxattr,
2657 .fsetxattr_fn = vfswrap_fsetxattr,
2659 /* aio operations */
2660 .aio_force_fn = vfswrap_aio_force,
2662 /* offline operations */
2663 .is_offline_fn = vfswrap_is_offline,
2664 .set_offline_fn = vfswrap_set_offline,
2666 /* durable handle operations */
2667 .durable_cookie_fn = vfswrap_durable_cookie,
2668 .durable_disconnect_fn = vfswrap_durable_disconnect,
2669 .durable_reconnect_fn = vfswrap_durable_reconnect,
2672 NTSTATUS vfs_default_init(void);
2673 NTSTATUS vfs_default_init(void)
2675 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
2676 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);