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/util/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, const char *path,
68 enum SMB_QUOTA_TYPE qtype, unid_t id,
71 #ifdef HAVE_SYS_QUOTAS
74 START_PROFILE(syscall_get_quota);
75 result = sys_get_quota(path, qtype, id, qt);
76 END_PROFILE(syscall_get_quota);
84 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
86 #ifdef HAVE_SYS_QUOTAS
89 START_PROFILE(syscall_set_quota);
90 result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
91 END_PROFILE(syscall_set_quota);
99 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
100 struct files_struct *fsp,
101 struct shadow_copy_data *shadow_copy_data,
105 return -1; /* Not implemented. */
108 static int vfswrap_statvfs(struct vfs_handle_struct *handle, const char *path, vfs_statvfs_struct *statbuf)
110 return sys_statvfs(path, statbuf);
113 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
114 enum timestamp_set_resolution *p_ts_res)
116 connection_struct *conn = handle->conn;
117 uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
118 struct smb_filename *smb_fname_cpath = NULL;
119 struct vfs_statvfs_struct statbuf;
122 ZERO_STRUCT(statbuf);
123 ret = sys_statvfs(conn->connectpath, &statbuf);
125 caps = statbuf.FsCapabilities;
128 *p_ts_res = TIMESTAMP_SET_SECONDS;
130 /* Work out what timestamp resolution we can
131 * use when setting a timestamp. */
133 smb_fname_cpath = synthetic_smb_fname(talloc_tos(), conn->connectpath,
135 if (smb_fname_cpath == NULL) {
139 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
141 TALLOC_FREE(smb_fname_cpath);
145 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
146 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
147 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
148 /* If any of the normal UNIX directory timestamps
149 * have a non-zero tv_nsec component assume
150 * we might be able to set sub-second timestamps.
151 * See what filetime set primitives we have.
153 #if defined(HAVE_UTIMENSAT)
154 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
155 #elif defined(HAVE_UTIMES)
156 /* utimes allows msec timestamps to be set. */
157 *p_ts_res = TIMESTAMP_SET_MSEC;
158 #elif defined(HAVE_UTIME)
159 /* utime only allows sec timestamps to be set. */
160 *p_ts_res = TIMESTAMP_SET_SECONDS;
163 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
165 "available on share %s, directory %s\n",
166 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
167 lp_servicename(talloc_tos(), conn->params->service),
168 conn->connectpath ));
170 TALLOC_FREE(smb_fname_cpath);
174 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
175 struct dfs_GetDFSReferral *r)
177 struct junction_map *junction = NULL;
179 bool self_referral = false;
180 char *pathnamep = NULL;
181 char *local_dfs_path = NULL;
184 uint16_t max_referral_level = r->in.req.max_referral_level;
187 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
190 /* get the junction entry */
191 if (r->in.req.servername == NULL) {
192 return NT_STATUS_NOT_FOUND;
196 * Trim pathname sent by client so it begins with only one backslash.
197 * Two backslashes confuse some dfs clients
200 local_dfs_path = talloc_strdup(r, r->in.req.servername);
201 if (local_dfs_path == NULL) {
202 return NT_STATUS_NO_MEMORY;
204 pathnamep = local_dfs_path;
205 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
206 IS_DIRECTORY_SEP(pathnamep[1])) {
210 junction = talloc_zero(r, struct junction_map);
211 if (junction == NULL) {
212 return NT_STATUS_NO_MEMORY;
215 /* The following call can change cwd. */
216 status = get_referred_path(r, pathnamep,
217 !handle->conn->sconn->using_smb2,
218 junction, &consumedcnt, &self_referral);
219 if (!NT_STATUS_IS_OK(status)) {
220 vfs_ChDir(handle->conn, handle->conn->connectpath);
223 vfs_ChDir(handle->conn, handle->conn->connectpath);
225 if (!self_referral) {
226 pathnamep[consumedcnt] = '\0';
229 dbgtext("Path %s to alternate path(s):",
231 for (i=0; i < junction->referral_count; i++) {
233 junction->referral_list[i].alternate_path);
239 if (r->in.req.max_referral_level <= 2) {
240 max_referral_level = 2;
242 if (r->in.req.max_referral_level >= 3) {
243 max_referral_level = 3;
246 r->out.resp = talloc_zero(r, struct dfs_referral_resp);
247 if (r->out.resp == NULL) {
248 return NT_STATUS_NO_MEMORY;
251 r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
252 r->out.resp->nb_referrals = junction->referral_count;
254 r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
256 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
259 r->out.resp->referral_entries = talloc_zero_array(r,
260 struct dfs_referral_type,
261 r->out.resp->nb_referrals);
262 if (r->out.resp->referral_entries == NULL) {
263 return NT_STATUS_NO_MEMORY;
266 switch (max_referral_level) {
268 for(i=0; i < junction->referral_count; i++) {
269 struct referral *ref = &junction->referral_list[i];
270 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
271 struct dfs_referral_type *t =
272 &r->out.resp->referral_entries[i];
273 struct dfs_referral_v2 *v2 = &t->referral.v2;
276 v2->size = VERSION2_REFERRAL_SIZE;
278 v2->server_type = DFS_SERVER_ROOT;
280 v2->server_type = DFS_SERVER_NON_ROOT;
283 v2->proximity = ref->proximity;
285 v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
286 if (v2->DFS_path == NULL) {
287 return NT_STATUS_NO_MEMORY;
289 v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
290 if (v2->DFS_alt_path == NULL) {
291 return NT_STATUS_NO_MEMORY;
293 v2->netw_address = talloc_strdup(mem_ctx,
294 ref->alternate_path);
295 if (v2->netw_address == NULL) {
296 return NT_STATUS_NO_MEMORY;
302 for(i=0; i < junction->referral_count; i++) {
303 struct referral *ref = &junction->referral_list[i];
304 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
305 struct dfs_referral_type *t =
306 &r->out.resp->referral_entries[i];
307 struct dfs_referral_v3 *v3 = &t->referral.v3;
308 struct dfs_normal_referral *r1 = &v3->referrals.r1;
311 v3->size = VERSION3_REFERRAL_SIZE;
313 v3->server_type = DFS_SERVER_ROOT;
315 v3->server_type = DFS_SERVER_NON_ROOT;
319 r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
320 if (r1->DFS_path == NULL) {
321 return NT_STATUS_NO_MEMORY;
323 r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
324 if (r1->DFS_alt_path == NULL) {
325 return NT_STATUS_NO_MEMORY;
327 r1->netw_address = talloc_strdup(mem_ctx,
328 ref->alternate_path);
329 if (r1->netw_address == NULL) {
330 return NT_STATUS_NO_MEMORY;
335 DEBUG(0,("Invalid dfs referral version: %d\n",
336 max_referral_level));
337 return NT_STATUS_INVALID_LEVEL;
341 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
347 static NTSTATUS vfswrap_snap_check_path(struct vfs_handle_struct *handle,
349 const char *service_path,
352 return NT_STATUS_NOT_SUPPORTED;
355 static NTSTATUS vfswrap_snap_create(struct vfs_handle_struct *handle,
357 const char *base_volume,
363 return NT_STATUS_NOT_SUPPORTED;
366 static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle,
371 return NT_STATUS_NOT_SUPPORTED;
374 /* Directory operations */
376 static DIR *vfswrap_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32_t attr)
380 START_PROFILE(syscall_opendir);
381 result = opendir(fname);
382 END_PROFILE(syscall_opendir);
386 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
393 START_PROFILE(syscall_fdopendir);
394 result = sys_fdopendir(fsp->fh->fd);
395 END_PROFILE(syscall_fdopendir);
400 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
402 SMB_STRUCT_STAT *sbuf)
404 struct dirent *result;
406 START_PROFILE(syscall_readdir);
407 result = readdir(dirp);
408 END_PROFILE(syscall_readdir);
410 /* Default Posix readdir() does not give us stat info.
411 * Set to invalid to indicate we didn't return this info. */
412 SET_STAT_INVALID(*sbuf);
413 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
414 if (result != NULL) {
415 /* See if we can efficiently return this. */
417 int flags = (lp_posix_pathnames() ?
418 AT_SYMLINK_NOFOLLOW : 0);
419 int ret = fstatat(dirfd(dirp),
424 init_stat_ex_from_stat(sbuf,
426 lp_fake_directory_create_times(
427 SNUM(handle->conn)));
435 static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
436 const struct smb_filename *fname,
438 struct readdir_attr_data **attr_data)
440 return NT_STATUS_NOT_SUPPORTED;
443 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
445 START_PROFILE(syscall_seekdir);
446 seekdir(dirp, offset);
447 END_PROFILE(syscall_seekdir);
450 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
453 START_PROFILE(syscall_telldir);
454 result = telldir(dirp);
455 END_PROFILE(syscall_telldir);
459 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
461 START_PROFILE(syscall_rewinddir);
463 END_PROFILE(syscall_rewinddir);
466 static int vfswrap_mkdir(vfs_handle_struct *handle, const char *path, mode_t mode)
469 bool has_dacl = False;
472 START_PROFILE(syscall_mkdir);
474 if (lp_inherit_acls(SNUM(handle->conn))
475 && parent_dirname(talloc_tos(), path, &parent, NULL)
476 && (has_dacl = directory_has_default_acl(handle->conn, parent))) {
477 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
482 result = mkdir(path, mode);
484 if (result == 0 && !has_dacl) {
486 * We need to do this as the default behavior of POSIX ACLs
487 * is to set the mask to be the requested group permission
488 * bits, not the group permission bits to be the requested
489 * group permission bits. This is not what we want, as it will
490 * mess up any inherited ACL bits that were set. JRA.
492 int saved_errno = errno; /* We may get ENOSYS */
493 if ((SMB_VFS_CHMOD_ACL(handle->conn, path, mode) == -1) && (errno == ENOSYS))
497 END_PROFILE(syscall_mkdir);
501 static int vfswrap_rmdir(vfs_handle_struct *handle, const char *path)
505 START_PROFILE(syscall_rmdir);
506 result = rmdir(path);
507 END_PROFILE(syscall_rmdir);
511 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
515 START_PROFILE(syscall_closedir);
516 result = closedir(dirp);
517 END_PROFILE(syscall_closedir);
521 static void vfswrap_init_search_op(vfs_handle_struct *handle,
524 /* Default behavior is a NOOP */
527 /* File operations */
529 static int vfswrap_open(vfs_handle_struct *handle,
530 struct smb_filename *smb_fname,
531 files_struct *fsp, int flags, mode_t mode)
535 START_PROFILE(syscall_open);
537 if (smb_fname->stream_name) {
542 result = open(smb_fname->base_name, flags, mode);
544 END_PROFILE(syscall_open);
548 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
549 struct smb_request *req,
550 uint16_t root_dir_fid,
551 struct smb_filename *smb_fname,
552 uint32_t access_mask,
553 uint32_t share_access,
554 uint32_t create_disposition,
555 uint32_t create_options,
556 uint32_t file_attributes,
557 uint32_t oplock_request,
558 struct smb2_lease *lease,
559 uint64_t allocation_size,
560 uint32_t private_flags,
561 struct security_descriptor *sd,
562 struct ea_list *ea_list,
563 files_struct **result,
565 const struct smb2_create_blobs *in_context_blobs,
566 struct smb2_create_blobs *out_context_blobs)
568 struct smb2_create_blob *svhdx = NULL;
571 * It might be empty ... and smb2_create_blob_find does not handle that
573 if (in_context_blobs) {
574 svhdx = smb2_create_blob_find(in_context_blobs,
575 SVHDX_OPEN_DEVICE_CONTEXT);
579 /* SharedVHD is not yet supported */
580 DEBUG(10, ("Shared VHD not yet supported, INVALID_DEVICE_REQUEST\n"));
581 return NT_STATUS_INVALID_DEVICE_REQUEST;
584 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
585 access_mask, share_access,
586 create_disposition, create_options,
587 file_attributes, oplock_request, lease,
588 allocation_size, private_flags,
590 pinfo, in_context_blobs, out_context_blobs);
593 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
597 START_PROFILE(syscall_close);
598 result = fd_close_posix(fsp);
599 END_PROFILE(syscall_close);
603 static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
607 START_PROFILE_BYTES(syscall_read, n);
608 result = sys_read(fsp->fh->fd, data, n);
609 END_PROFILE_BYTES(syscall_read);
613 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
614 size_t n, off_t offset)
618 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
619 START_PROFILE_BYTES(syscall_pread, n);
620 result = sys_pread(fsp->fh->fd, data, n, offset);
621 END_PROFILE_BYTES(syscall_pread);
623 if (result == -1 && errno == ESPIPE) {
624 /* Maintain the fiction that pipes can be seeked (sought?) on. */
625 result = SMB_VFS_READ(fsp, data, n);
629 #else /* HAVE_PREAD */
633 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
634 if (curr == -1 && errno == ESPIPE) {
635 /* Maintain the fiction that pipes can be seeked (sought?) on. */
636 result = SMB_VFS_READ(fsp, data, n);
641 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
646 result = SMB_VFS_READ(fsp, data, n);
649 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
652 #endif /* HAVE_PREAD */
657 static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
661 START_PROFILE_BYTES(syscall_write, n);
662 result = sys_write(fsp->fh->fd, data, n);
663 END_PROFILE_BYTES(syscall_write);
667 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
668 size_t n, off_t offset)
672 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
673 START_PROFILE_BYTES(syscall_pwrite, n);
674 result = sys_pwrite(fsp->fh->fd, data, n, offset);
675 END_PROFILE_BYTES(syscall_pwrite);
677 if (result == -1 && errno == ESPIPE) {
678 /* Maintain the fiction that pipes can be sought on. */
679 result = SMB_VFS_WRITE(fsp, data, n);
682 #else /* HAVE_PWRITE */
686 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
691 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
695 result = SMB_VFS_WRITE(fsp, data, n);
698 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
701 #endif /* HAVE_PWRITE */
706 static void vfswrap_asys_finished(struct tevent_context *ev,
707 struct tevent_fd *fde,
708 uint16_t flags, void *p);
710 static bool vfswrap_init_asys_ctx(struct smbd_server_connection *conn)
712 struct asys_context *ctx;
713 struct tevent_fd *fde;
717 if (conn->asys_ctx != NULL) {
721 ret = asys_context_init(&ctx, lp_aio_max_threads());
723 DEBUG(1, ("asys_context_init failed: %s\n", strerror(ret)));
727 fd = asys_signalfd(ctx);
729 ret = set_blocking(fd, false);
731 DBG_WARNING("set_blocking failed: %s\n", strerror(errno));
735 fde = tevent_add_fd(conn->ev_ctx, conn, fd, TEVENT_FD_READ,
736 vfswrap_asys_finished, ctx);
738 DEBUG(1, ("tevent_add_fd failed\n"));
742 conn->asys_ctx = ctx;
743 conn->asys_fde = fde;
747 asys_context_destroy(ctx);
751 struct vfswrap_asys_state {
752 struct asys_context *asys_ctx;
753 struct tevent_req *req;
756 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
757 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
760 static int vfswrap_asys_state_destructor(struct vfswrap_asys_state *s)
762 asys_cancel(s->asys_ctx, s->req);
766 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
768 struct tevent_context *ev,
769 struct files_struct *fsp,
771 size_t n, off_t offset)
773 struct tevent_req *req;
774 struct vfswrap_asys_state *state;
777 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
781 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
783 return tevent_req_post(req, ev);
785 state->asys_ctx = handle->conn->sconn->asys_ctx;
788 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
789 state->profile_bytes, n);
790 ret = asys_pread(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
792 tevent_req_error(req, ret);
793 return tevent_req_post(req, ev);
795 talloc_set_destructor(state, vfswrap_asys_state_destructor);
800 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
802 struct tevent_context *ev,
803 struct files_struct *fsp,
805 size_t n, off_t offset)
807 struct tevent_req *req;
808 struct vfswrap_asys_state *state;
811 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
815 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
817 return tevent_req_post(req, ev);
819 state->asys_ctx = handle->conn->sconn->asys_ctx;
822 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
823 state->profile_bytes, n);
824 ret = asys_pwrite(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
826 tevent_req_error(req, ret);
827 return tevent_req_post(req, ev);
829 talloc_set_destructor(state, vfswrap_asys_state_destructor);
834 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
836 struct tevent_context *ev,
837 struct files_struct *fsp)
839 struct tevent_req *req;
840 struct vfswrap_asys_state *state;
843 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
847 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
849 return tevent_req_post(req, ev);
851 state->asys_ctx = handle->conn->sconn->asys_ctx;
854 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
855 state->profile_basic);
856 ret = asys_fsync(state->asys_ctx, fsp->fh->fd, req);
858 tevent_req_error(req, ret);
859 return tevent_req_post(req, ev);
861 talloc_set_destructor(state, vfswrap_asys_state_destructor);
866 static void vfswrap_asys_finished(struct tevent_context *ev,
867 struct tevent_fd *fde,
868 uint16_t flags, void *p)
870 struct asys_context *asys_ctx = (struct asys_context *)p;
871 struct asys_result results[get_outstanding_aio_calls()];
874 if ((flags & TEVENT_FD_READ) == 0) {
878 ret = asys_results(asys_ctx, results, get_outstanding_aio_calls());
880 DEBUG(1, ("asys_results returned %s\n", strerror(-ret)));
884 for (i=0; i<ret; i++) {
885 struct asys_result *result = &results[i];
886 struct tevent_req *req;
887 struct vfswrap_asys_state *state;
889 if ((result->ret == -1) && (result->err == ECANCELED)) {
893 req = talloc_get_type_abort(result->private_data,
895 state = tevent_req_data(req, struct vfswrap_asys_state);
897 talloc_set_destructor(state, NULL);
899 SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
900 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
901 state->ret = result->ret;
902 state->err = result->err;
903 tevent_req_defer_callback(req, ev);
904 tevent_req_done(req);
908 static ssize_t vfswrap_asys_ssize_t_recv(struct tevent_req *req, int *err)
910 struct vfswrap_asys_state *state = tevent_req_data(
911 req, struct vfswrap_asys_state);
913 if (tevent_req_is_unix_error(req, err)) {
920 static int vfswrap_asys_int_recv(struct tevent_req *req, int *err)
922 struct vfswrap_asys_state *state = tevent_req_data(
923 req, struct vfswrap_asys_state);
925 if (tevent_req_is_unix_error(req, err)) {
932 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
936 START_PROFILE(syscall_lseek);
938 /* Cope with 'stat' file opens. */
939 if (fsp->fh->fd != -1)
940 result = lseek(fsp->fh->fd, offset, whence);
943 * We want to maintain the fiction that we can seek
944 * on a fifo for file system purposes. This allows
945 * people to set up UNIX fifo's that feed data to Windows
949 if((result == -1) && (errno == ESPIPE)) {
954 END_PROFILE(syscall_lseek);
958 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
959 off_t offset, size_t n)
963 START_PROFILE_BYTES(syscall_sendfile, n);
964 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
965 END_PROFILE_BYTES(syscall_sendfile);
969 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
977 START_PROFILE_BYTES(syscall_recvfile, n);
978 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
979 END_PROFILE_BYTES(syscall_recvfile);
983 static int vfswrap_rename(vfs_handle_struct *handle,
984 const struct smb_filename *smb_fname_src,
985 const struct smb_filename *smb_fname_dst)
989 START_PROFILE(syscall_rename);
991 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
996 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
999 END_PROFILE(syscall_rename);
1003 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
1008 START_PROFILE(syscall_fsync);
1009 result = fsync(fsp->fh->fd);
1010 END_PROFILE(syscall_fsync);
1017 static int vfswrap_stat(vfs_handle_struct *handle,
1018 struct smb_filename *smb_fname)
1022 START_PROFILE(syscall_stat);
1024 if (smb_fname->stream_name) {
1029 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1030 lp_fake_directory_create_times(SNUM(handle->conn)));
1032 END_PROFILE(syscall_stat);
1036 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1040 START_PROFILE(syscall_fstat);
1041 result = sys_fstat(fsp->fh->fd,
1042 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1043 END_PROFILE(syscall_fstat);
1047 static int vfswrap_lstat(vfs_handle_struct *handle,
1048 struct smb_filename *smb_fname)
1052 START_PROFILE(syscall_lstat);
1054 if (smb_fname->stream_name) {
1059 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1060 lp_fake_directory_create_times(SNUM(handle->conn)));
1062 END_PROFILE(syscall_lstat);
1066 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1068 enum vfs_translate_direction direction,
1069 TALLOC_CTX *mem_ctx,
1072 return NT_STATUS_NONE_MAPPED;
1076 * Implement the default fsctl operation.
1078 static bool vfswrap_logged_ioctl_message = false;
1080 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1081 struct files_struct *fsp,
1084 uint16_t req_flags, /* Needed for UNICODE ... */
1085 const uint8_t *_in_data,
1087 uint8_t **_out_data,
1088 uint32_t max_out_len,
1091 const char *in_data = (const char *)_in_data;
1092 char **out_data = (char **)_out_data;
1096 case FSCTL_SET_SPARSE:
1098 bool set_sparse = true;
1100 if (in_len >= 1 && in_data[0] == 0) {
1104 status = file_set_sparse(handle->conn, fsp, set_sparse);
1106 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1107 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1108 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1109 nt_errstr(status)));
1114 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1116 unsigned char objid[16];
1117 char *return_data = NULL;
1119 /* This should return the object-id on this file.
1120 * I think I'll make this be the inode+dev. JRA.
1123 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1124 fsp_fnum_dbg(fsp)));
1126 *out_len = MIN(max_out_len, 64);
1128 /* Hmmm, will this cause problems if less data asked for? */
1129 return_data = talloc_array(ctx, char, 64);
1130 if (return_data == NULL) {
1131 return NT_STATUS_NO_MEMORY;
1134 /* For backwards compatibility only store the dev/inode. */
1135 push_file_id_16(return_data, &fsp->file_id);
1136 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1137 push_file_id_16(return_data+32, &fsp->file_id);
1138 memset(return_data+48, 0, 16);
1139 *out_data = return_data;
1140 return NT_STATUS_OK;
1143 case FSCTL_GET_REPARSE_POINT:
1145 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1146 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1147 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1148 return NT_STATUS_NOT_A_REPARSE_POINT;
1151 case FSCTL_SET_REPARSE_POINT:
1153 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1154 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1155 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1156 return NT_STATUS_NOT_A_REPARSE_POINT;
1159 case FSCTL_GET_SHADOW_COPY_DATA:
1162 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1163 * and return their volume names. If max_data_count is 16, then it is just
1164 * asking for the number of volumes and length of the combined names.
1166 * pdata is the data allocated by our caller, but that uses
1167 * total_data_count (which is 0 in our case) rather than max_data_count.
1168 * Allocate the correct amount and return the pointer to let
1169 * it be deallocated when we return.
1171 struct shadow_copy_data *shadow_data = NULL;
1172 bool labels = False;
1173 uint32_t labels_data_count = 0;
1175 char *cur_pdata = NULL;
1177 if (max_out_len < 16) {
1178 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1180 return NT_STATUS_INVALID_PARAMETER;
1183 if (max_out_len > 16) {
1187 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1188 if (shadow_data == NULL) {
1189 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1190 return NT_STATUS_NO_MEMORY;
1194 * Call the VFS routine to actually do the work.
1196 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1199 /* broken module didn't set errno on error */
1200 status = NT_STATUS_UNSUCCESSFUL;
1202 status = map_nt_error_from_unix(errno);
1203 if (NT_STATUS_EQUAL(status,
1204 NT_STATUS_NOT_SUPPORTED)) {
1208 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1209 "connectpath %s, failed - %s.\n",
1210 fsp->conn->connectpath,
1211 nt_errstr(status)));
1212 TALLOC_FREE(shadow_data);
1216 labels_data_count = (shadow_data->num_volumes * 2 *
1217 sizeof(SHADOW_COPY_LABEL)) + 2;
1222 *out_len = 12 + labels_data_count;
1225 if (max_out_len < *out_len) {
1226 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1227 max_out_len, *out_len));
1228 TALLOC_FREE(shadow_data);
1229 return NT_STATUS_BUFFER_TOO_SMALL;
1232 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1233 if (cur_pdata == NULL) {
1234 TALLOC_FREE(shadow_data);
1235 return NT_STATUS_NO_MEMORY;
1238 *out_data = cur_pdata;
1240 /* num_volumes 4 bytes */
1241 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1244 /* num_labels 4 bytes */
1245 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1248 /* needed_data_count 4 bytes */
1249 SIVAL(cur_pdata, 8, labels_data_count);
1253 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1254 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1255 if (labels && shadow_data->labels) {
1256 for (i=0; i<shadow_data->num_volumes; i++) {
1258 status = srvstr_push(cur_pdata, req_flags,
1259 cur_pdata, shadow_data->labels[i],
1260 2 * sizeof(SHADOW_COPY_LABEL),
1261 STR_UNICODE|STR_TERMINATE, &len);
1262 if (!NT_STATUS_IS_OK(status)) {
1263 TALLOC_FREE(*out_data);
1264 TALLOC_FREE(shadow_data);
1267 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1268 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1272 TALLOC_FREE(shadow_data);
1274 return NT_STATUS_OK;
1277 case FSCTL_FIND_FILES_BY_SID:
1279 /* pretend this succeeded -
1281 * we have to send back a list with all files owned by this SID
1283 * but I have to check that --metze
1289 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1290 fsp_fnum_dbg(fsp)));
1293 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1294 return NT_STATUS_INVALID_PARAMETER;
1297 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1299 /* unknown 4 bytes: this is not the length of the sid :-( */
1300 /*unknown = IVAL(pdata,0);*/
1302 if (!sid_parse(_in_data + 4, sid_len, &sid)) {
1303 return NT_STATUS_INVALID_PARAMETER;
1305 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1307 if (!sid_to_uid(&sid, &uid)) {
1308 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1309 sid_string_dbg(&sid),
1310 (unsigned long)sid_len));
1314 /* we can take a look at the find source :-)
1316 * find ./ -uid $uid -name '*' is what we need here
1319 * and send 4bytes len and then NULL terminated unicode strings
1322 * but I don't know how to deal with the paged results
1323 * (maybe we can hang the result anywhere in the fsp struct)
1325 * but I don't know how to deal with the paged results
1326 * (maybe we can hang the result anywhere in the fsp struct)
1328 * we don't send all files at once
1329 * and at the next we should *not* start from the beginning,
1330 * so we have to cache the result
1335 /* this works for now... */
1336 return NT_STATUS_OK;
1339 case FSCTL_QUERY_ALLOCATED_RANGES:
1341 /* FIXME: This is just a dummy reply, telling that all of the
1342 * file is allocated. MKS cp needs that.
1343 * Adding the real allocated ranges via FIEMAP on Linux
1344 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1345 * this FSCTL correct for sparse files.
1347 uint64_t offset, length;
1348 char *out_data_tmp = NULL;
1351 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1353 return NT_STATUS_INVALID_PARAMETER;
1356 if (max_out_len < 16) {
1357 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1359 return NT_STATUS_INVALID_PARAMETER;
1362 offset = BVAL(in_data,0);
1363 length = BVAL(in_data,8);
1365 if (offset + length < offset) {
1366 /* No 64-bit integer wrap. */
1367 return NT_STATUS_INVALID_PARAMETER;
1370 /* Shouldn't this be SMB_VFS_STAT ... ? */
1371 status = vfs_stat_fsp(fsp);
1372 if (!NT_STATUS_IS_OK(status)) {
1377 out_data_tmp = talloc_array(ctx, char, *out_len);
1378 if (out_data_tmp == NULL) {
1379 DEBUG(10, ("unable to allocate memory for response\n"));
1380 return NT_STATUS_NO_MEMORY;
1383 if (offset > fsp->fsp_name->st.st_ex_size ||
1384 fsp->fsp_name->st.st_ex_size == 0 ||
1386 memset(out_data_tmp, 0, *out_len);
1388 uint64_t end = offset + length;
1389 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1390 SBVAL(out_data_tmp, 0, 0);
1391 SBVAL(out_data_tmp, 8, end);
1394 *out_data = out_data_tmp;
1396 return NT_STATUS_OK;
1399 case FSCTL_IS_VOLUME_DIRTY:
1401 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1402 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1404 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1405 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1407 return NT_STATUS_INVALID_PARAMETER;
1412 * Only print once ... unfortunately there could be lots of
1413 * different FSCTLs that are called.
1415 if (!vfswrap_logged_ioctl_message) {
1416 vfswrap_logged_ioctl_message = true;
1417 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1418 __func__, function));
1422 return NT_STATUS_NOT_SUPPORTED;
1425 struct vfs_cc_state {
1430 static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *handle,
1431 TALLOC_CTX *mem_ctx,
1432 struct tevent_context *ev,
1433 struct files_struct *src_fsp,
1435 struct files_struct *dest_fsp,
1439 struct tevent_req *req;
1440 struct vfs_cc_state *vfs_cc_state;
1443 DEBUG(10, ("performing server side copy chunk of length %lu\n",
1444 (unsigned long)num));
1446 req = tevent_req_create(mem_ctx, &vfs_cc_state, struct vfs_cc_state);
1451 vfs_cc_state->buf = talloc_array(vfs_cc_state, uint8_t,
1452 MIN(num, 8*1024*1024));
1453 if (tevent_req_nomem(vfs_cc_state->buf, req)) {
1454 return tevent_req_post(req, ev);
1457 status = vfs_stat_fsp(src_fsp);
1458 if (tevent_req_nterror(req, status)) {
1459 return tevent_req_post(req, ev);
1462 if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
1464 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1465 * If the SourceOffset or SourceOffset + Length extends beyond
1466 * the end of file, the server SHOULD<240> treat this as a
1467 * STATUS_END_OF_FILE error.
1469 * <240> Section 3.3.5.15.6: Windows servers will return
1470 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1472 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1473 return tevent_req_post(req, ev);
1476 /* could use 2.6.33+ sendfile here to do this in kernel */
1477 while (vfs_cc_state->copied < num) {
1479 struct lock_struct lck;
1482 off_t this_num = MIN(talloc_array_length(vfs_cc_state->buf),
1483 num - vfs_cc_state->copied);
1485 if (src_fsp->op == NULL) {
1486 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1487 return tevent_req_post(req, ev);
1489 init_strict_lock_struct(src_fsp,
1490 src_fsp->op->global->open_persistent_id,
1496 if (!SMB_VFS_STRICT_LOCK(src_fsp->conn, src_fsp, &lck)) {
1497 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1498 return tevent_req_post(req, ev);
1501 ret = SMB_VFS_PREAD(src_fsp, vfs_cc_state->buf,
1504 saved_errno = errno;
1507 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1510 errno = saved_errno;
1511 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1512 return tevent_req_post(req, ev);
1514 if (ret != this_num) {
1515 /* zero tolerance for short reads */
1516 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1517 return tevent_req_post(req, ev);
1522 if (dest_fsp->op == NULL) {
1523 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1524 return tevent_req_post(req, ev);
1527 init_strict_lock_struct(dest_fsp,
1528 dest_fsp->op->global->open_persistent_id,
1534 if (!SMB_VFS_STRICT_LOCK(dest_fsp->conn, dest_fsp, &lck)) {
1535 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1536 return tevent_req_post(req, ev);
1539 ret = SMB_VFS_PWRITE(dest_fsp, vfs_cc_state->buf,
1540 this_num, dest_off);
1542 saved_errno = errno;
1545 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1548 errno = saved_errno;
1549 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1550 return tevent_req_post(req, ev);
1552 if (ret != this_num) {
1553 /* zero tolerance for short writes */
1554 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1555 return tevent_req_post(req, ev);
1559 vfs_cc_state->copied += this_num;
1562 tevent_req_done(req);
1563 return tevent_req_post(req, ev);
1566 static NTSTATUS vfswrap_copy_chunk_recv(struct vfs_handle_struct *handle,
1567 struct tevent_req *req,
1570 struct vfs_cc_state *vfs_cc_state = tevent_req_data(req,
1571 struct vfs_cc_state);
1574 if (tevent_req_is_nterror(req, &status)) {
1575 DEBUG(2, ("server side copy chunk failed: %s\n",
1576 nt_errstr(status)));
1578 tevent_req_received(req);
1582 *copied = vfs_cc_state->copied;
1583 DEBUG(10, ("server side copy chunk copied %lu\n",
1584 (unsigned long)*copied));
1585 tevent_req_received(req);
1587 return NT_STATUS_OK;
1590 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1591 TALLOC_CTX *mem_ctx,
1592 struct files_struct *fsp,
1593 struct smb_filename *smb_fname,
1594 uint16_t *_compression_fmt)
1596 return NT_STATUS_INVALID_DEVICE_REQUEST;
1599 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1600 TALLOC_CTX *mem_ctx,
1601 struct files_struct *fsp,
1602 uint16_t compression_fmt)
1604 return NT_STATUS_INVALID_DEVICE_REQUEST;
1607 /********************************************************************
1608 Given a stat buffer return the allocated size on disk, taking into
1609 account sparse files.
1610 ********************************************************************/
1611 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1612 struct files_struct *fsp,
1613 const SMB_STRUCT_STAT *sbuf)
1617 START_PROFILE(syscall_get_alloc_size);
1619 if(S_ISDIR(sbuf->st_ex_mode)) {
1624 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1625 /* The type of st_blocksize is blkcnt_t which *MUST* be
1626 signed (according to POSIX) and can be less than 64-bits.
1627 Ensure when we're converting to 64 bits wide we don't
1629 #if defined(SIZEOF_BLKCNT_T_8)
1630 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1631 #elif defined(SIZEOF_BLKCNT_T_4)
1633 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1634 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1637 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1641 * Some file systems do not allocate a block for very
1642 * small files. But for non-empty file should report a
1646 uint64_t filesize = get_file_size_stat(sbuf);
1648 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
1652 result = get_file_size_stat(sbuf);
1655 if (fsp && fsp->initial_allocation_size)
1656 result = MAX(result,fsp->initial_allocation_size);
1658 result = smb_roundup(handle->conn, result);
1661 END_PROFILE(syscall_get_alloc_size);
1665 static int vfswrap_unlink(vfs_handle_struct *handle,
1666 const struct smb_filename *smb_fname)
1670 START_PROFILE(syscall_unlink);
1672 if (smb_fname->stream_name) {
1676 result = unlink(smb_fname->base_name);
1679 END_PROFILE(syscall_unlink);
1683 static int vfswrap_chmod(vfs_handle_struct *handle, const char *path, mode_t mode)
1687 START_PROFILE(syscall_chmod);
1690 * We need to do this due to the fact that the default POSIX ACL
1691 * chmod modifies the ACL *mask* for the group owner, not the
1692 * group owner bits directly. JRA.
1697 int saved_errno = errno; /* We might get ENOSYS */
1698 if ((result = SMB_VFS_CHMOD_ACL(handle->conn, path, mode)) == 0) {
1699 END_PROFILE(syscall_chmod);
1702 /* Error - return the old errno. */
1703 errno = saved_errno;
1706 result = chmod(path, mode);
1707 END_PROFILE(syscall_chmod);
1711 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
1715 START_PROFILE(syscall_fchmod);
1718 * We need to do this due to the fact that the default POSIX ACL
1719 * chmod modifies the ACL *mask* for the group owner, not the
1720 * group owner bits directly. JRA.
1724 int saved_errno = errno; /* We might get ENOSYS */
1725 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
1726 END_PROFILE(syscall_fchmod);
1729 /* Error - return the old errno. */
1730 errno = saved_errno;
1733 #if defined(HAVE_FCHMOD)
1734 result = fchmod(fsp->fh->fd, mode);
1740 END_PROFILE(syscall_fchmod);
1744 static int vfswrap_chown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1748 START_PROFILE(syscall_chown);
1749 result = chown(path, uid, gid);
1750 END_PROFILE(syscall_chown);
1754 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
1759 START_PROFILE(syscall_fchown);
1760 result = fchown(fsp->fh->fd, uid, gid);
1761 END_PROFILE(syscall_fchown);
1769 static int vfswrap_lchown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1773 START_PROFILE(syscall_lchown);
1774 result = lchown(path, uid, gid);
1775 END_PROFILE(syscall_lchown);
1779 static int vfswrap_chdir(vfs_handle_struct *handle, const char *path)
1783 START_PROFILE(syscall_chdir);
1784 result = chdir(path);
1785 END_PROFILE(syscall_chdir);
1789 static char *vfswrap_getwd(vfs_handle_struct *handle)
1793 START_PROFILE(syscall_getwd);
1794 result = sys_getwd();
1795 END_PROFILE(syscall_getwd);
1799 /*********************************************************************
1800 nsec timestamp resolution call. Convert down to whatever the underlying
1801 system will support.
1802 **********************************************************************/
1804 static int vfswrap_ntimes(vfs_handle_struct *handle,
1805 const struct smb_filename *smb_fname,
1806 struct smb_file_time *ft)
1810 START_PROFILE(syscall_ntimes);
1812 if (smb_fname->stream_name) {
1818 if (null_timespec(ft->atime)) {
1819 ft->atime= smb_fname->st.st_ex_atime;
1822 if (null_timespec(ft->mtime)) {
1823 ft->mtime = smb_fname->st.st_ex_mtime;
1826 if (!null_timespec(ft->create_time)) {
1827 set_create_timespec_ea(handle->conn,
1832 if ((timespec_compare(&ft->atime,
1833 &smb_fname->st.st_ex_atime) == 0) &&
1834 (timespec_compare(&ft->mtime,
1835 &smb_fname->st.st_ex_mtime) == 0)) {
1840 #if defined(HAVE_UTIMENSAT)
1842 struct timespec ts[2];
1845 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
1847 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
1849 if (!((result == -1) && (errno == ENOSYS))) {
1853 #if defined(HAVE_UTIMES)
1855 struct timeval tv[2];
1856 tv[0] = convert_timespec_to_timeval(ft->atime);
1857 tv[1] = convert_timespec_to_timeval(ft->mtime);
1858 result = utimes(smb_fname->base_name, tv);
1860 result = utimes(smb_fname->base_name, NULL);
1862 if (!((result == -1) && (errno == ENOSYS))) {
1866 #if defined(HAVE_UTIME)
1868 struct utimbuf times;
1869 times.actime = convert_timespec_to_time_t(ft->atime);
1870 times.modtime = convert_timespec_to_time_t(ft->mtime);
1871 result = utime(smb_fname->base_name, ×);
1873 result = utime(smb_fname->base_name, NULL);
1875 if (!((result == -1) && (errno == ENOSYS))) {
1883 END_PROFILE(syscall_ntimes);
1887 /*********************************************************************
1888 A version of ftruncate that will write the space on disk if strict
1890 **********************************************************************/
1892 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1894 off_t space_to_write;
1895 uint64_t space_avail;
1896 uint64_t bsize,dfree,dsize;
1899 SMB_STRUCT_STAT *pst;
1901 status = vfs_stat_fsp(fsp);
1902 if (!NT_STATUS_IS_OK(status)) {
1905 pst = &fsp->fsp_name->st;
1908 if (S_ISFIFO(pst->st_ex_mode))
1912 if (pst->st_ex_size == len)
1915 /* Shrink - just ftruncate. */
1916 if (pst->st_ex_size > len)
1917 return ftruncate(fsp->fh->fd, len);
1919 space_to_write = len - pst->st_ex_size;
1921 /* for allocation try fallocate first. This can fail on some
1922 platforms e.g. when the filesystem doesn't support it and no
1923 emulation is being done by the libc (like on AIX with JFS1). In that
1924 case we do our own emulation. fallocate implementations can
1925 return ENOTSUP or EINVAL in cases like that. */
1926 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
1927 if (ret == -1 && errno == ENOSPC) {
1933 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
1934 "error %d. Falling back to slow manual allocation\n", errno));
1936 /* available disk space is enough or not? */
1937 space_avail = get_dfree_info(fsp->conn,
1938 fsp->fsp_name->base_name,
1939 &bsize, &dfree, &dsize);
1940 /* space_avail is 1k blocks */
1941 if (space_avail == (uint64_t)-1 ||
1942 ((uint64_t)space_to_write/1024 > space_avail) ) {
1947 /* Write out the real space on disk. */
1948 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
1956 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1959 SMB_STRUCT_STAT *pst;
1963 START_PROFILE(syscall_ftruncate);
1965 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
1966 result = strict_allocate_ftruncate(handle, fsp, len);
1967 END_PROFILE(syscall_ftruncate);
1971 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
1972 ftruncate if the system supports it. Then I discovered that
1973 you can have some filesystems that support ftruncate
1974 expansion and some that don't! On Linux fat can't do
1975 ftruncate extend but ext2 can. */
1977 result = ftruncate(fsp->fh->fd, len);
1979 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
1980 extend a file with ftruncate. Provide alternate implementation
1983 /* Do an fstat to see if the file is longer than the requested
1984 size in which case the ftruncate above should have
1985 succeeded or shorter, in which case seek to len - 1 and
1986 write 1 byte of zero */
1987 status = vfs_stat_fsp(fsp);
1988 if (!NT_STATUS_IS_OK(status)) {
1992 /* We need to update the files_struct after successful ftruncate */
1997 pst = &fsp->fsp_name->st;
2000 if (S_ISFIFO(pst->st_ex_mode)) {
2006 if (pst->st_ex_size == len) {
2011 if (pst->st_ex_size > len) {
2012 /* the ftruncate should have worked */
2016 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2024 END_PROFILE(syscall_ftruncate);
2028 static int vfswrap_fallocate(vfs_handle_struct *handle,
2036 START_PROFILE(syscall_fallocate);
2038 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2040 * posix_fallocate returns 0 on success, errno on error
2041 * and doesn't set errno. Make it behave like fallocate()
2042 * which returns -1, and sets errno on failure.
2049 /* sys_fallocate handles filtering of unsupported mode flags */
2050 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2052 END_PROFILE(syscall_fallocate);
2056 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2060 START_PROFILE(syscall_fcntl_lock);
2061 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2062 END_PROFILE(syscall_fcntl_lock);
2066 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2067 uint32_t share_mode, uint32_t access_mask)
2069 START_PROFILE(syscall_kernel_flock);
2070 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2071 END_PROFILE(syscall_kernel_flock);
2075 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2079 START_PROFILE(syscall_fcntl_getlock);
2080 result = fcntl_getlock(fsp->fh->fd, poffset, pcount, ptype, ppid);
2081 END_PROFILE(syscall_fcntl_getlock);
2085 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2090 START_PROFILE(syscall_linux_setlease);
2092 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2093 result = linux_setlease(fsp->fh->fd, leasetype);
2097 END_PROFILE(syscall_linux_setlease);
2101 static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2105 START_PROFILE(syscall_symlink);
2106 result = symlink(oldpath, newpath);
2107 END_PROFILE(syscall_symlink);
2111 static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
2115 START_PROFILE(syscall_readlink);
2116 result = readlink(path, buf, bufsiz);
2117 END_PROFILE(syscall_readlink);
2121 static int vfswrap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2125 START_PROFILE(syscall_link);
2126 result = link(oldpath, newpath);
2127 END_PROFILE(syscall_link);
2131 static int vfswrap_mknod(vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev)
2135 START_PROFILE(syscall_mknod);
2136 result = sys_mknod(pathname, mode, dev);
2137 END_PROFILE(syscall_mknod);
2141 static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
2145 START_PROFILE(syscall_realpath);
2146 #ifdef REALPATH_TAKES_NULL
2147 result = realpath(path, NULL);
2149 result = SMB_MALLOC_ARRAY(char, PATH_MAX+1);
2151 char *resolved_path = realpath(path, result);
2152 if (!resolved_path) {
2155 /* SMB_ASSERT(result == resolved_path) ? */
2156 result = resolved_path;
2160 END_PROFILE(syscall_realpath);
2164 static int vfswrap_chflags(vfs_handle_struct *handle, const char *path,
2168 return chflags(path, flags);
2175 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2176 const SMB_STRUCT_STAT *sbuf)
2180 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2184 key.devid = sbuf->st_ex_dev;
2185 key.inode = sbuf->st_ex_ino;
2186 /* key.extid is unused by default. */
2191 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2192 struct files_struct *fsp,
2194 TALLOC_CTX *mem_ctx,
2195 unsigned int *pnum_streams,
2196 struct stream_struct **pstreams)
2198 SMB_STRUCT_STAT sbuf;
2199 struct stream_struct *tmp_streams = NULL;
2202 if ((fsp != NULL) && (fsp->is_directory)) {
2204 * No default streams on directories
2209 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2210 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2213 struct smb_filename smb_fname;
2215 ZERO_STRUCT(smb_fname);
2216 smb_fname.base_name = discard_const_p(char, fname);
2218 if (lp_posix_pathnames()) {
2219 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname);
2221 ret = SMB_VFS_STAT(handle->conn, &smb_fname);
2223 sbuf = smb_fname.st;
2227 return map_nt_error_from_unix(errno);
2230 if (S_ISDIR(sbuf.st_ex_mode)) {
2234 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2235 (*pnum_streams) + 1);
2236 if (tmp_streams == NULL) {
2237 return NT_STATUS_NO_MEMORY;
2239 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2240 if (tmp_streams[*pnum_streams].name == NULL) {
2241 return NT_STATUS_NO_MEMORY;
2243 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2244 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2247 *pstreams = tmp_streams;
2249 return NT_STATUS_OK;
2252 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2255 TALLOC_CTX *mem_ctx,
2259 * Don't fall back to get_real_filename so callers can differentiate
2260 * between a full directory scan and an actual case-insensitive stat.
2266 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2269 return handle->conn->connectpath;
2272 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2273 struct byte_range_lock *br_lck,
2274 struct lock_struct *plock,
2277 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2279 /* Note: blr is not used in the default implementation. */
2280 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2283 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2284 struct messaging_context *msg_ctx,
2285 struct byte_range_lock *br_lck,
2286 const struct lock_struct *plock)
2288 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2290 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2293 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2294 struct byte_range_lock *br_lck,
2295 struct lock_struct *plock)
2297 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2299 /* Note: blr is not used in the default implementation. */
2300 return brl_lock_cancel_default(br_lck, plock);
2303 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2305 struct lock_struct *plock)
2307 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2308 plock->lock_type == WRITE_LOCK);
2310 return strict_lock_default(fsp, plock);
2313 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2315 struct lock_struct *plock)
2317 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2318 plock->lock_type == WRITE_LOCK);
2320 strict_unlock_default(fsp, plock);
2323 /* NT ACL operations. */
2325 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2327 uint32_t security_info,
2328 TALLOC_CTX *mem_ctx,
2329 struct security_descriptor **ppdesc)
2333 START_PROFILE(fget_nt_acl);
2334 result = posix_fget_nt_acl(fsp, security_info,
2336 END_PROFILE(fget_nt_acl);
2340 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2342 uint32_t security_info,
2343 TALLOC_CTX *mem_ctx,
2344 struct security_descriptor **ppdesc)
2348 START_PROFILE(get_nt_acl);
2349 result = posix_get_nt_acl(handle->conn, name, security_info,
2351 END_PROFILE(get_nt_acl);
2355 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2359 START_PROFILE(fset_nt_acl);
2360 result = set_nt_acl(fsp, security_info_sent, psd);
2361 END_PROFILE(fset_nt_acl);
2365 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2366 struct smb_filename *file,
2367 struct security_acl *sacl,
2368 uint32_t access_requested,
2369 uint32_t access_denied)
2371 return NT_STATUS_OK; /* Nothing to do here ... */
2374 static int vfswrap_chmod_acl(vfs_handle_struct *handle, const char *name, mode_t mode)
2382 START_PROFILE(chmod_acl);
2383 result = chmod_acl(handle->conn, name, mode);
2384 END_PROFILE(chmod_acl);
2389 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2397 START_PROFILE(fchmod_acl);
2398 result = fchmod_acl(fsp, mode);
2399 END_PROFILE(fchmod_acl);
2404 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2406 SMB_ACL_TYPE_T type,
2407 TALLOC_CTX *mem_ctx)
2409 return sys_acl_get_file(handle, path_p, type, mem_ctx);
2412 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2414 TALLOC_CTX *mem_ctx)
2416 return sys_acl_get_fd(handle, fsp, mem_ctx);
2419 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2421 return sys_acl_set_file(handle, name, acltype, theacl);
2424 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2426 return sys_acl_set_fd(handle, fsp, theacl);
2429 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
2431 return sys_acl_delete_def_file(handle, path);
2434 /****************************************************************
2435 Extended attribute operations.
2436 *****************************************************************/
2438 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
2440 return getxattr(path, name, value, size);
2443 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2445 return fgetxattr(fsp->fh->fd, name, value, size);
2448 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
2450 return listxattr(path, list, size);
2453 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2455 return flistxattr(fsp->fh->fd, list, size);
2458 static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
2460 return removexattr(path, name);
2463 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2465 return fremovexattr(fsp->fh->fd, name);
2468 static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
2470 return setxattr(path, name, value, size, flags);
2473 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2475 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2478 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2483 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2484 const struct smb_filename *fname,
2485 SMB_STRUCT_STAT *sbuf)
2489 bool offline = false;
2491 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2495 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2496 #if defined(ENOTSUP)
2502 status = get_full_smb_filename(talloc_tos(), fname, &path);
2503 if (!NT_STATUS_IS_OK(status)) {
2504 errno = map_errno_from_nt_status(status);
2508 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2515 static int vfswrap_set_offline(struct vfs_handle_struct *handle,
2516 const struct smb_filename *fname)
2518 /* We don't know how to set offline bit by default, needs to be overriden in the vfs modules */
2519 #if defined(ENOTSUP)
2525 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2526 struct files_struct *fsp,
2527 TALLOC_CTX *mem_ctx,
2530 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2533 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2534 struct files_struct *fsp,
2535 const DATA_BLOB old_cookie,
2536 TALLOC_CTX *mem_ctx,
2537 DATA_BLOB *new_cookie)
2539 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2543 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2544 struct smb_request *smb1req,
2545 struct smbXsrv_open *op,
2546 const DATA_BLOB old_cookie,
2547 TALLOC_CTX *mem_ctx,
2548 struct files_struct **fsp,
2549 DATA_BLOB *new_cookie)
2551 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2552 old_cookie, mem_ctx,
2556 static struct vfs_fn_pointers vfs_default_fns = {
2557 /* Disk operations */
2559 .connect_fn = vfswrap_connect,
2560 .disconnect_fn = vfswrap_disconnect,
2561 .disk_free_fn = vfswrap_disk_free,
2562 .get_quota_fn = vfswrap_get_quota,
2563 .set_quota_fn = vfswrap_set_quota,
2564 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2565 .statvfs_fn = vfswrap_statvfs,
2566 .fs_capabilities_fn = vfswrap_fs_capabilities,
2567 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2568 .snap_check_path_fn = vfswrap_snap_check_path,
2569 .snap_create_fn = vfswrap_snap_create,
2570 .snap_delete_fn = vfswrap_snap_delete,
2572 /* Directory operations */
2574 .opendir_fn = vfswrap_opendir,
2575 .fdopendir_fn = vfswrap_fdopendir,
2576 .readdir_fn = vfswrap_readdir,
2577 .readdir_attr_fn = vfswrap_readdir_attr,
2578 .seekdir_fn = vfswrap_seekdir,
2579 .telldir_fn = vfswrap_telldir,
2580 .rewind_dir_fn = vfswrap_rewinddir,
2581 .mkdir_fn = vfswrap_mkdir,
2582 .rmdir_fn = vfswrap_rmdir,
2583 .closedir_fn = vfswrap_closedir,
2584 .init_search_op_fn = vfswrap_init_search_op,
2586 /* File operations */
2588 .open_fn = vfswrap_open,
2589 .create_file_fn = vfswrap_create_file,
2590 .close_fn = vfswrap_close,
2591 .read_fn = vfswrap_read,
2592 .pread_fn = vfswrap_pread,
2593 .pread_send_fn = vfswrap_pread_send,
2594 .pread_recv_fn = vfswrap_asys_ssize_t_recv,
2595 .write_fn = vfswrap_write,
2596 .pwrite_fn = vfswrap_pwrite,
2597 .pwrite_send_fn = vfswrap_pwrite_send,
2598 .pwrite_recv_fn = vfswrap_asys_ssize_t_recv,
2599 .lseek_fn = vfswrap_lseek,
2600 .sendfile_fn = vfswrap_sendfile,
2601 .recvfile_fn = vfswrap_recvfile,
2602 .rename_fn = vfswrap_rename,
2603 .fsync_fn = vfswrap_fsync,
2604 .fsync_send_fn = vfswrap_fsync_send,
2605 .fsync_recv_fn = vfswrap_asys_int_recv,
2606 .stat_fn = vfswrap_stat,
2607 .fstat_fn = vfswrap_fstat,
2608 .lstat_fn = vfswrap_lstat,
2609 .get_alloc_size_fn = vfswrap_get_alloc_size,
2610 .unlink_fn = vfswrap_unlink,
2611 .chmod_fn = vfswrap_chmod,
2612 .fchmod_fn = vfswrap_fchmod,
2613 .chown_fn = vfswrap_chown,
2614 .fchown_fn = vfswrap_fchown,
2615 .lchown_fn = vfswrap_lchown,
2616 .chdir_fn = vfswrap_chdir,
2617 .getwd_fn = vfswrap_getwd,
2618 .ntimes_fn = vfswrap_ntimes,
2619 .ftruncate_fn = vfswrap_ftruncate,
2620 .fallocate_fn = vfswrap_fallocate,
2621 .lock_fn = vfswrap_lock,
2622 .kernel_flock_fn = vfswrap_kernel_flock,
2623 .linux_setlease_fn = vfswrap_linux_setlease,
2624 .getlock_fn = vfswrap_getlock,
2625 .symlink_fn = vfswrap_symlink,
2626 .readlink_fn = vfswrap_readlink,
2627 .link_fn = vfswrap_link,
2628 .mknod_fn = vfswrap_mknod,
2629 .realpath_fn = vfswrap_realpath,
2630 .chflags_fn = vfswrap_chflags,
2631 .file_id_create_fn = vfswrap_file_id_create,
2632 .streaminfo_fn = vfswrap_streaminfo,
2633 .get_real_filename_fn = vfswrap_get_real_filename,
2634 .connectpath_fn = vfswrap_connectpath,
2635 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2636 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2637 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2638 .strict_lock_fn = vfswrap_strict_lock,
2639 .strict_unlock_fn = vfswrap_strict_unlock,
2640 .translate_name_fn = vfswrap_translate_name,
2641 .fsctl_fn = vfswrap_fsctl,
2642 .copy_chunk_send_fn = vfswrap_copy_chunk_send,
2643 .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
2644 .get_compression_fn = vfswrap_get_compression,
2645 .set_compression_fn = vfswrap_set_compression,
2647 /* NT ACL operations. */
2649 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2650 .get_nt_acl_fn = vfswrap_get_nt_acl,
2651 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2652 .audit_file_fn = vfswrap_audit_file,
2654 /* POSIX ACL operations. */
2656 .chmod_acl_fn = vfswrap_chmod_acl,
2657 .fchmod_acl_fn = vfswrap_fchmod_acl,
2659 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2660 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2661 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2662 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2663 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2664 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2665 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2667 /* EA operations. */
2668 .getxattr_fn = vfswrap_getxattr,
2669 .fgetxattr_fn = vfswrap_fgetxattr,
2670 .listxattr_fn = vfswrap_listxattr,
2671 .flistxattr_fn = vfswrap_flistxattr,
2672 .removexattr_fn = vfswrap_removexattr,
2673 .fremovexattr_fn = vfswrap_fremovexattr,
2674 .setxattr_fn = vfswrap_setxattr,
2675 .fsetxattr_fn = vfswrap_fsetxattr,
2677 /* aio operations */
2678 .aio_force_fn = vfswrap_aio_force,
2680 /* offline operations */
2681 .is_offline_fn = vfswrap_is_offline,
2682 .set_offline_fn = vfswrap_set_offline,
2684 /* durable handle operations */
2685 .durable_cookie_fn = vfswrap_durable_cookie,
2686 .durable_disconnect_fn = vfswrap_durable_disconnect,
2687 .durable_reconnect_fn = vfswrap_durable_reconnect,
2690 NTSTATUS vfs_default_init(void);
2691 NTSTATUS vfs_default_init(void)
2693 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
2694 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);