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 struct smb2_create_blob *svhdx = NULL;
569 * It might be empty ... and smb2_create_blob_find does not handle that
571 if (in_context_blobs) {
572 svhdx = smb2_create_blob_find(in_context_blobs,
573 SVHDX_OPEN_DEVICE_CONTEXT);
577 /* SharedVHD is not yet supported */
578 DEBUG(10, ("Shared VHD not yet supported, INVALID_DEVICE_REQUEST\n"));
579 return NT_STATUS_INVALID_DEVICE_REQUEST;
582 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
583 access_mask, share_access,
584 create_disposition, create_options,
585 file_attributes, oplock_request, lease,
586 allocation_size, private_flags,
588 pinfo, in_context_blobs, out_context_blobs);
591 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
595 START_PROFILE(syscall_close);
596 result = fd_close_posix(fsp);
597 END_PROFILE(syscall_close);
601 static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
605 START_PROFILE_BYTES(syscall_read, n);
606 result = sys_read(fsp->fh->fd, data, n);
607 END_PROFILE_BYTES(syscall_read);
611 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
612 size_t n, off_t offset)
616 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
617 START_PROFILE_BYTES(syscall_pread, n);
618 result = sys_pread(fsp->fh->fd, data, n, offset);
619 END_PROFILE_BYTES(syscall_pread);
621 if (result == -1 && errno == ESPIPE) {
622 /* Maintain the fiction that pipes can be seeked (sought?) on. */
623 result = SMB_VFS_READ(fsp, data, n);
627 #else /* HAVE_PREAD */
631 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
632 if (curr == -1 && errno == ESPIPE) {
633 /* Maintain the fiction that pipes can be seeked (sought?) on. */
634 result = SMB_VFS_READ(fsp, data, n);
639 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
644 result = SMB_VFS_READ(fsp, data, n);
647 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
650 #endif /* HAVE_PREAD */
655 static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
659 START_PROFILE_BYTES(syscall_write, n);
660 result = sys_write(fsp->fh->fd, data, n);
661 END_PROFILE_BYTES(syscall_write);
665 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
666 size_t n, off_t offset)
670 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
671 START_PROFILE_BYTES(syscall_pwrite, n);
672 result = sys_pwrite(fsp->fh->fd, data, n, offset);
673 END_PROFILE_BYTES(syscall_pwrite);
675 if (result == -1 && errno == ESPIPE) {
676 /* Maintain the fiction that pipes can be sought on. */
677 result = SMB_VFS_WRITE(fsp, data, n);
680 #else /* HAVE_PWRITE */
684 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
689 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
693 result = SMB_VFS_WRITE(fsp, data, n);
696 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
699 #endif /* HAVE_PWRITE */
704 static void vfswrap_asys_finished(struct tevent_context *ev,
705 struct tevent_fd *fde,
706 uint16_t flags, void *p);
708 static bool vfswrap_init_asys_ctx(struct smbd_server_connection *conn)
710 struct asys_context *ctx;
711 struct tevent_fd *fde;
715 if (conn->asys_ctx != NULL) {
719 ret = asys_context_init(&ctx, aio_pending_size);
721 DEBUG(1, ("asys_context_init failed: %s\n", strerror(ret)));
725 fd = asys_signalfd(ctx);
727 ret = set_blocking(fd, false);
729 DBG_WARNING("set_blocking failed: %s\n", strerror(errno));
733 fde = tevent_add_fd(conn->ev_ctx, conn, fd, TEVENT_FD_READ,
734 vfswrap_asys_finished, ctx);
736 DEBUG(1, ("tevent_add_fd failed\n"));
740 conn->asys_ctx = ctx;
741 conn->asys_fde = fde;
745 asys_context_destroy(ctx);
749 struct vfswrap_asys_state {
750 struct asys_context *asys_ctx;
751 struct tevent_req *req;
754 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
755 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
758 static int vfswrap_asys_state_destructor(struct vfswrap_asys_state *s)
760 asys_cancel(s->asys_ctx, s->req);
764 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
766 struct tevent_context *ev,
767 struct files_struct *fsp,
769 size_t n, off_t offset)
771 struct tevent_req *req;
772 struct vfswrap_asys_state *state;
775 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
779 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
781 return tevent_req_post(req, ev);
783 state->asys_ctx = handle->conn->sconn->asys_ctx;
786 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
787 state->profile_bytes, n);
788 ret = asys_pread(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
790 tevent_req_error(req, ret);
791 return tevent_req_post(req, ev);
793 talloc_set_destructor(state, vfswrap_asys_state_destructor);
798 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
800 struct tevent_context *ev,
801 struct files_struct *fsp,
803 size_t n, off_t offset)
805 struct tevent_req *req;
806 struct vfswrap_asys_state *state;
809 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
813 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
815 return tevent_req_post(req, ev);
817 state->asys_ctx = handle->conn->sconn->asys_ctx;
820 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
821 state->profile_bytes, n);
822 ret = asys_pwrite(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
824 tevent_req_error(req, ret);
825 return tevent_req_post(req, ev);
827 talloc_set_destructor(state, vfswrap_asys_state_destructor);
832 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
834 struct tevent_context *ev,
835 struct files_struct *fsp)
837 struct tevent_req *req;
838 struct vfswrap_asys_state *state;
841 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
845 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
847 return tevent_req_post(req, ev);
849 state->asys_ctx = handle->conn->sconn->asys_ctx;
852 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
853 state->profile_basic);
854 ret = asys_fsync(state->asys_ctx, fsp->fh->fd, req);
856 tevent_req_error(req, ret);
857 return tevent_req_post(req, ev);
859 talloc_set_destructor(state, vfswrap_asys_state_destructor);
864 static void vfswrap_asys_finished(struct tevent_context *ev,
865 struct tevent_fd *fde,
866 uint16_t flags, void *p)
868 struct asys_context *asys_ctx = (struct asys_context *)p;
869 struct asys_result results[outstanding_aio_calls];
872 if ((flags & TEVENT_FD_READ) == 0) {
876 ret = asys_results(asys_ctx, results, outstanding_aio_calls);
878 DEBUG(1, ("asys_results returned %s\n", strerror(-ret)));
882 for (i=0; i<ret; i++) {
883 struct asys_result *result = &results[i];
884 struct tevent_req *req;
885 struct vfswrap_asys_state *state;
887 if ((result->ret == -1) && (result->err == ECANCELED)) {
891 req = talloc_get_type_abort(result->private_data,
893 state = tevent_req_data(req, struct vfswrap_asys_state);
895 talloc_set_destructor(state, NULL);
897 SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
898 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
899 state->ret = result->ret;
900 state->err = result->err;
901 tevent_req_defer_callback(req, ev);
902 tevent_req_done(req);
906 static ssize_t vfswrap_asys_ssize_t_recv(struct tevent_req *req, int *err)
908 struct vfswrap_asys_state *state = tevent_req_data(
909 req, struct vfswrap_asys_state);
911 if (tevent_req_is_unix_error(req, err)) {
918 static int vfswrap_asys_int_recv(struct tevent_req *req, int *err)
920 struct vfswrap_asys_state *state = tevent_req_data(
921 req, struct vfswrap_asys_state);
923 if (tevent_req_is_unix_error(req, err)) {
930 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
934 START_PROFILE(syscall_lseek);
936 /* Cope with 'stat' file opens. */
937 if (fsp->fh->fd != -1)
938 result = lseek(fsp->fh->fd, offset, whence);
941 * We want to maintain the fiction that we can seek
942 * on a fifo for file system purposes. This allows
943 * people to set up UNIX fifo's that feed data to Windows
947 if((result == -1) && (errno == ESPIPE)) {
952 END_PROFILE(syscall_lseek);
956 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
957 off_t offset, size_t n)
961 START_PROFILE_BYTES(syscall_sendfile, n);
962 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
963 END_PROFILE_BYTES(syscall_sendfile);
967 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
975 START_PROFILE_BYTES(syscall_recvfile, n);
976 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
977 END_PROFILE_BYTES(syscall_recvfile);
981 static int vfswrap_rename(vfs_handle_struct *handle,
982 const struct smb_filename *smb_fname_src,
983 const struct smb_filename *smb_fname_dst)
987 START_PROFILE(syscall_rename);
989 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
994 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
997 END_PROFILE(syscall_rename);
1001 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
1006 START_PROFILE(syscall_fsync);
1007 result = fsync(fsp->fh->fd);
1008 END_PROFILE(syscall_fsync);
1015 static int vfswrap_stat(vfs_handle_struct *handle,
1016 struct smb_filename *smb_fname)
1020 START_PROFILE(syscall_stat);
1022 if (smb_fname->stream_name) {
1027 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1028 lp_fake_directory_create_times(SNUM(handle->conn)));
1030 END_PROFILE(syscall_stat);
1034 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1038 START_PROFILE(syscall_fstat);
1039 result = sys_fstat(fsp->fh->fd,
1040 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1041 END_PROFILE(syscall_fstat);
1045 static int vfswrap_lstat(vfs_handle_struct *handle,
1046 struct smb_filename *smb_fname)
1050 START_PROFILE(syscall_lstat);
1052 if (smb_fname->stream_name) {
1057 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1058 lp_fake_directory_create_times(SNUM(handle->conn)));
1060 END_PROFILE(syscall_lstat);
1064 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1066 enum vfs_translate_direction direction,
1067 TALLOC_CTX *mem_ctx,
1070 return NT_STATUS_NONE_MAPPED;
1074 * Implement the default fsctl operation.
1076 static bool vfswrap_logged_ioctl_message = false;
1078 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1079 struct files_struct *fsp,
1082 uint16_t req_flags, /* Needed for UNICODE ... */
1083 const uint8_t *_in_data,
1085 uint8_t **_out_data,
1086 uint32_t max_out_len,
1089 const char *in_data = (const char *)_in_data;
1090 char **out_data = (char **)_out_data;
1094 case FSCTL_SET_SPARSE:
1096 bool set_sparse = true;
1098 if (in_len >= 1 && in_data[0] == 0) {
1102 status = file_set_sparse(handle->conn, fsp, set_sparse);
1104 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1105 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1106 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1107 nt_errstr(status)));
1112 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1114 unsigned char objid[16];
1115 char *return_data = NULL;
1117 /* This should return the object-id on this file.
1118 * I think I'll make this be the inode+dev. JRA.
1121 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1122 fsp_fnum_dbg(fsp)));
1124 *out_len = MIN(max_out_len, 64);
1126 /* Hmmm, will this cause problems if less data asked for? */
1127 return_data = talloc_array(ctx, char, 64);
1128 if (return_data == NULL) {
1129 return NT_STATUS_NO_MEMORY;
1132 /* For backwards compatibility only store the dev/inode. */
1133 push_file_id_16(return_data, &fsp->file_id);
1134 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1135 push_file_id_16(return_data+32, &fsp->file_id);
1136 memset(return_data+48, 0, 16);
1137 *out_data = return_data;
1138 return NT_STATUS_OK;
1141 case FSCTL_GET_REPARSE_POINT:
1143 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1144 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1145 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1146 return NT_STATUS_NOT_A_REPARSE_POINT;
1149 case FSCTL_SET_REPARSE_POINT:
1151 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1152 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1153 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1154 return NT_STATUS_NOT_A_REPARSE_POINT;
1157 case FSCTL_GET_SHADOW_COPY_DATA:
1160 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1161 * and return their volume names. If max_data_count is 16, then it is just
1162 * asking for the number of volumes and length of the combined names.
1164 * pdata is the data allocated by our caller, but that uses
1165 * total_data_count (which is 0 in our case) rather than max_data_count.
1166 * Allocate the correct amount and return the pointer to let
1167 * it be deallocated when we return.
1169 struct shadow_copy_data *shadow_data = NULL;
1170 bool labels = False;
1171 uint32_t labels_data_count = 0;
1173 char *cur_pdata = NULL;
1175 if (max_out_len < 16) {
1176 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1178 return NT_STATUS_INVALID_PARAMETER;
1181 if (max_out_len > 16) {
1185 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1186 if (shadow_data == NULL) {
1187 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1188 return NT_STATUS_NO_MEMORY;
1192 * Call the VFS routine to actually do the work.
1194 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1197 /* broken module didn't set errno on error */
1198 status = NT_STATUS_UNSUCCESSFUL;
1200 status = map_nt_error_from_unix(errno);
1201 if (NT_STATUS_EQUAL(status,
1202 NT_STATUS_NOT_SUPPORTED)) {
1206 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1207 "connectpath %s, failed - %s.\n",
1208 fsp->conn->connectpath,
1209 nt_errstr(status)));
1210 TALLOC_FREE(shadow_data);
1214 labels_data_count = (shadow_data->num_volumes * 2 *
1215 sizeof(SHADOW_COPY_LABEL)) + 2;
1220 *out_len = 12 + labels_data_count;
1223 if (max_out_len < *out_len) {
1224 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1225 max_out_len, *out_len));
1226 TALLOC_FREE(shadow_data);
1227 return NT_STATUS_BUFFER_TOO_SMALL;
1230 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1231 if (cur_pdata == NULL) {
1232 TALLOC_FREE(shadow_data);
1233 return NT_STATUS_NO_MEMORY;
1236 *out_data = cur_pdata;
1238 /* num_volumes 4 bytes */
1239 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1242 /* num_labels 4 bytes */
1243 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1246 /* needed_data_count 4 bytes */
1247 SIVAL(cur_pdata, 8, labels_data_count);
1251 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1252 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1253 if (labels && shadow_data->labels) {
1254 for (i=0; i<shadow_data->num_volumes; i++) {
1256 status = srvstr_push(cur_pdata, req_flags,
1257 cur_pdata, shadow_data->labels[i],
1258 2 * sizeof(SHADOW_COPY_LABEL),
1259 STR_UNICODE|STR_TERMINATE, &len);
1260 if (!NT_STATUS_IS_OK(status)) {
1261 TALLOC_FREE(*out_data);
1262 TALLOC_FREE(shadow_data);
1265 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1266 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1270 TALLOC_FREE(shadow_data);
1272 return NT_STATUS_OK;
1275 case FSCTL_FIND_FILES_BY_SID:
1277 /* pretend this succeeded -
1279 * we have to send back a list with all files owned by this SID
1281 * but I have to check that --metze
1287 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1288 fsp_fnum_dbg(fsp)));
1291 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1292 return NT_STATUS_INVALID_PARAMETER;
1295 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1297 /* unknown 4 bytes: this is not the length of the sid :-( */
1298 /*unknown = IVAL(pdata,0);*/
1300 if (!sid_parse(_in_data + 4, sid_len, &sid)) {
1301 return NT_STATUS_INVALID_PARAMETER;
1303 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1305 if (!sid_to_uid(&sid, &uid)) {
1306 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1307 sid_string_dbg(&sid),
1308 (unsigned long)sid_len));
1312 /* we can take a look at the find source :-)
1314 * find ./ -uid $uid -name '*' is what we need here
1317 * and send 4bytes len and then NULL terminated unicode strings
1320 * but I don't know how to deal with the paged results
1321 * (maybe we can hang the result anywhere in the fsp struct)
1323 * but I don't know how to deal with the paged results
1324 * (maybe we can hang the result anywhere in the fsp struct)
1326 * we don't send all files at once
1327 * and at the next we should *not* start from the beginning,
1328 * so we have to cache the result
1333 /* this works for now... */
1334 return NT_STATUS_OK;
1337 case FSCTL_QUERY_ALLOCATED_RANGES:
1339 /* FIXME: This is just a dummy reply, telling that all of the
1340 * file is allocated. MKS cp needs that.
1341 * Adding the real allocated ranges via FIEMAP on Linux
1342 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1343 * this FSCTL correct for sparse files.
1345 uint64_t offset, length;
1346 char *out_data_tmp = NULL;
1349 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1351 return NT_STATUS_INVALID_PARAMETER;
1354 if (max_out_len < 16) {
1355 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1357 return NT_STATUS_INVALID_PARAMETER;
1360 offset = BVAL(in_data,0);
1361 length = BVAL(in_data,8);
1363 if (offset + length < offset) {
1364 /* No 64-bit integer wrap. */
1365 return NT_STATUS_INVALID_PARAMETER;
1368 /* Shouldn't this be SMB_VFS_STAT ... ? */
1369 status = vfs_stat_fsp(fsp);
1370 if (!NT_STATUS_IS_OK(status)) {
1375 out_data_tmp = talloc_array(ctx, char, *out_len);
1376 if (out_data_tmp == NULL) {
1377 DEBUG(10, ("unable to allocate memory for response\n"));
1378 return NT_STATUS_NO_MEMORY;
1381 if (offset > fsp->fsp_name->st.st_ex_size ||
1382 fsp->fsp_name->st.st_ex_size == 0 ||
1384 memset(out_data_tmp, 0, *out_len);
1386 uint64_t end = offset + length;
1387 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1388 SBVAL(out_data_tmp, 0, 0);
1389 SBVAL(out_data_tmp, 8, end);
1392 *out_data = out_data_tmp;
1394 return NT_STATUS_OK;
1397 case FSCTL_IS_VOLUME_DIRTY:
1399 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1400 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1402 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1403 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1405 return NT_STATUS_INVALID_PARAMETER;
1410 * Only print once ... unfortunately there could be lots of
1411 * different FSCTLs that are called.
1413 if (!vfswrap_logged_ioctl_message) {
1414 vfswrap_logged_ioctl_message = true;
1415 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1416 __func__, function));
1420 return NT_STATUS_NOT_SUPPORTED;
1423 struct vfs_cc_state {
1428 static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *handle,
1429 TALLOC_CTX *mem_ctx,
1430 struct tevent_context *ev,
1431 struct files_struct *src_fsp,
1433 struct files_struct *dest_fsp,
1437 struct tevent_req *req;
1438 struct vfs_cc_state *vfs_cc_state;
1441 DEBUG(10, ("performing server side copy chunk of length %lu\n",
1442 (unsigned long)num));
1444 req = tevent_req_create(mem_ctx, &vfs_cc_state, struct vfs_cc_state);
1449 vfs_cc_state->buf = talloc_array(vfs_cc_state, uint8_t,
1450 MIN(num, 8*1024*1024));
1451 if (tevent_req_nomem(vfs_cc_state->buf, req)) {
1452 return tevent_req_post(req, ev);
1455 status = vfs_stat_fsp(src_fsp);
1456 if (tevent_req_nterror(req, status)) {
1457 return tevent_req_post(req, ev);
1460 if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
1462 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1463 * If the SourceOffset or SourceOffset + Length extends beyond
1464 * the end of file, the server SHOULD<240> treat this as a
1465 * STATUS_END_OF_FILE error.
1467 * <240> Section 3.3.5.15.6: Windows servers will return
1468 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1470 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1471 return tevent_req_post(req, ev);
1474 /* could use 2.6.33+ sendfile here to do this in kernel */
1475 while (vfs_cc_state->copied < num) {
1477 struct lock_struct lck;
1480 off_t this_num = MIN(talloc_array_length(vfs_cc_state->buf),
1481 num - vfs_cc_state->copied);
1483 if (src_fsp->op == NULL) {
1484 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1485 return tevent_req_post(req, ev);
1487 init_strict_lock_struct(src_fsp,
1488 src_fsp->op->global->open_persistent_id,
1494 if (!SMB_VFS_STRICT_LOCK(src_fsp->conn, src_fsp, &lck)) {
1495 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1496 return tevent_req_post(req, ev);
1499 ret = SMB_VFS_PREAD(src_fsp, vfs_cc_state->buf,
1502 saved_errno = errno;
1505 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1508 errno = saved_errno;
1509 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1510 return tevent_req_post(req, ev);
1512 if (ret != this_num) {
1513 /* zero tolerance for short reads */
1514 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1515 return tevent_req_post(req, ev);
1520 if (dest_fsp->op == NULL) {
1521 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1522 return tevent_req_post(req, ev);
1525 init_strict_lock_struct(dest_fsp,
1526 dest_fsp->op->global->open_persistent_id,
1532 if (!SMB_VFS_STRICT_LOCK(dest_fsp->conn, dest_fsp, &lck)) {
1533 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1534 return tevent_req_post(req, ev);
1537 ret = SMB_VFS_PWRITE(dest_fsp, vfs_cc_state->buf,
1538 this_num, dest_off);
1540 saved_errno = errno;
1543 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1546 errno = saved_errno;
1547 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1548 return tevent_req_post(req, ev);
1550 if (ret != this_num) {
1551 /* zero tolerance for short writes */
1552 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1553 return tevent_req_post(req, ev);
1557 vfs_cc_state->copied += this_num;
1560 tevent_req_done(req);
1561 return tevent_req_post(req, ev);
1564 static NTSTATUS vfswrap_copy_chunk_recv(struct vfs_handle_struct *handle,
1565 struct tevent_req *req,
1568 struct vfs_cc_state *vfs_cc_state = tevent_req_data(req,
1569 struct vfs_cc_state);
1572 if (tevent_req_is_nterror(req, &status)) {
1573 DEBUG(2, ("server side copy chunk failed: %s\n",
1574 nt_errstr(status)));
1576 tevent_req_received(req);
1580 *copied = vfs_cc_state->copied;
1581 DEBUG(10, ("server side copy chunk copied %lu\n",
1582 (unsigned long)*copied));
1583 tevent_req_received(req);
1585 return NT_STATUS_OK;
1588 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1589 TALLOC_CTX *mem_ctx,
1590 struct files_struct *fsp,
1591 struct smb_filename *smb_fname,
1592 uint16_t *_compression_fmt)
1594 return NT_STATUS_INVALID_DEVICE_REQUEST;
1597 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1598 TALLOC_CTX *mem_ctx,
1599 struct files_struct *fsp,
1600 uint16_t compression_fmt)
1602 return NT_STATUS_INVALID_DEVICE_REQUEST;
1605 /********************************************************************
1606 Given a stat buffer return the allocated size on disk, taking into
1607 account sparse files.
1608 ********************************************************************/
1609 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1610 struct files_struct *fsp,
1611 const SMB_STRUCT_STAT *sbuf)
1615 START_PROFILE(syscall_get_alloc_size);
1617 if(S_ISDIR(sbuf->st_ex_mode)) {
1622 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1623 /* The type of st_blocksize is blkcnt_t which *MUST* be
1624 signed (according to POSIX) and can be less than 64-bits.
1625 Ensure when we're converting to 64 bits wide we don't
1627 #if defined(SIZEOF_BLKCNT_T_8)
1628 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1629 #elif defined(SIZEOF_BLKCNT_T_4)
1631 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1632 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1635 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1639 * Some file systems do not allocate a block for very
1640 * small files. But for non-empty file should report a
1644 uint64_t filesize = get_file_size_stat(sbuf);
1646 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
1650 result = get_file_size_stat(sbuf);
1653 if (fsp && fsp->initial_allocation_size)
1654 result = MAX(result,fsp->initial_allocation_size);
1656 result = smb_roundup(handle->conn, result);
1659 END_PROFILE(syscall_get_alloc_size);
1663 static int vfswrap_unlink(vfs_handle_struct *handle,
1664 const struct smb_filename *smb_fname)
1668 START_PROFILE(syscall_unlink);
1670 if (smb_fname->stream_name) {
1674 result = unlink(smb_fname->base_name);
1677 END_PROFILE(syscall_unlink);
1681 static int vfswrap_chmod(vfs_handle_struct *handle, const char *path, mode_t mode)
1685 START_PROFILE(syscall_chmod);
1688 * We need to do this due to the fact that the default POSIX ACL
1689 * chmod modifies the ACL *mask* for the group owner, not the
1690 * group owner bits directly. JRA.
1695 int saved_errno = errno; /* We might get ENOSYS */
1696 if ((result = SMB_VFS_CHMOD_ACL(handle->conn, path, mode)) == 0) {
1697 END_PROFILE(syscall_chmod);
1700 /* Error - return the old errno. */
1701 errno = saved_errno;
1704 result = chmod(path, mode);
1705 END_PROFILE(syscall_chmod);
1709 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
1713 START_PROFILE(syscall_fchmod);
1716 * We need to do this due to the fact that the default POSIX ACL
1717 * chmod modifies the ACL *mask* for the group owner, not the
1718 * group owner bits directly. JRA.
1722 int saved_errno = errno; /* We might get ENOSYS */
1723 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
1724 END_PROFILE(syscall_fchmod);
1727 /* Error - return the old errno. */
1728 errno = saved_errno;
1731 #if defined(HAVE_FCHMOD)
1732 result = fchmod(fsp->fh->fd, mode);
1738 END_PROFILE(syscall_fchmod);
1742 static int vfswrap_chown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1746 START_PROFILE(syscall_chown);
1747 result = chown(path, uid, gid);
1748 END_PROFILE(syscall_chown);
1752 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
1757 START_PROFILE(syscall_fchown);
1758 result = fchown(fsp->fh->fd, uid, gid);
1759 END_PROFILE(syscall_fchown);
1767 static int vfswrap_lchown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1771 START_PROFILE(syscall_lchown);
1772 result = lchown(path, uid, gid);
1773 END_PROFILE(syscall_lchown);
1777 static int vfswrap_chdir(vfs_handle_struct *handle, const char *path)
1781 START_PROFILE(syscall_chdir);
1782 result = chdir(path);
1783 END_PROFILE(syscall_chdir);
1787 static char *vfswrap_getwd(vfs_handle_struct *handle)
1791 START_PROFILE(syscall_getwd);
1792 result = sys_getwd();
1793 END_PROFILE(syscall_getwd);
1797 /*********************************************************************
1798 nsec timestamp resolution call. Convert down to whatever the underlying
1799 system will support.
1800 **********************************************************************/
1802 static int vfswrap_ntimes(vfs_handle_struct *handle,
1803 const struct smb_filename *smb_fname,
1804 struct smb_file_time *ft)
1808 START_PROFILE(syscall_ntimes);
1810 if (smb_fname->stream_name) {
1816 if (null_timespec(ft->atime)) {
1817 ft->atime= smb_fname->st.st_ex_atime;
1820 if (null_timespec(ft->mtime)) {
1821 ft->mtime = smb_fname->st.st_ex_mtime;
1824 if (!null_timespec(ft->create_time)) {
1825 set_create_timespec_ea(handle->conn,
1830 if ((timespec_compare(&ft->atime,
1831 &smb_fname->st.st_ex_atime) == 0) &&
1832 (timespec_compare(&ft->mtime,
1833 &smb_fname->st.st_ex_mtime) == 0)) {
1838 #if defined(HAVE_UTIMENSAT)
1840 struct timespec ts[2];
1843 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
1845 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
1847 if (!((result == -1) && (errno == ENOSYS))) {
1851 #if defined(HAVE_UTIMES)
1853 struct timeval tv[2];
1854 tv[0] = convert_timespec_to_timeval(ft->atime);
1855 tv[1] = convert_timespec_to_timeval(ft->mtime);
1856 result = utimes(smb_fname->base_name, tv);
1858 result = utimes(smb_fname->base_name, NULL);
1860 if (!((result == -1) && (errno == ENOSYS))) {
1864 #if defined(HAVE_UTIME)
1866 struct utimbuf times;
1867 times.actime = convert_timespec_to_time_t(ft->atime);
1868 times.modtime = convert_timespec_to_time_t(ft->mtime);
1869 result = utime(smb_fname->base_name, ×);
1871 result = utime(smb_fname->base_name, NULL);
1873 if (!((result == -1) && (errno == ENOSYS))) {
1881 END_PROFILE(syscall_ntimes);
1885 /*********************************************************************
1886 A version of ftruncate that will write the space on disk if strict
1888 **********************************************************************/
1890 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1892 off_t space_to_write;
1893 uint64_t space_avail;
1894 uint64_t bsize,dfree,dsize;
1897 SMB_STRUCT_STAT *pst;
1899 status = vfs_stat_fsp(fsp);
1900 if (!NT_STATUS_IS_OK(status)) {
1903 pst = &fsp->fsp_name->st;
1906 if (S_ISFIFO(pst->st_ex_mode))
1910 if (pst->st_ex_size == len)
1913 /* Shrink - just ftruncate. */
1914 if (pst->st_ex_size > len)
1915 return ftruncate(fsp->fh->fd, len);
1917 space_to_write = len - pst->st_ex_size;
1919 /* for allocation try fallocate first. This can fail on some
1920 platforms e.g. when the filesystem doesn't support it and no
1921 emulation is being done by the libc (like on AIX with JFS1). In that
1922 case we do our own emulation. fallocate implementations can
1923 return ENOTSUP or EINVAL in cases like that. */
1924 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
1925 if (ret == -1 && errno == ENOSPC) {
1931 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
1932 "error %d. Falling back to slow manual allocation\n", errno));
1934 /* available disk space is enough or not? */
1935 space_avail = get_dfree_info(fsp->conn,
1936 fsp->fsp_name->base_name,
1937 &bsize, &dfree, &dsize);
1938 /* space_avail is 1k blocks */
1939 if (space_avail == (uint64_t)-1 ||
1940 ((uint64_t)space_to_write/1024 > space_avail) ) {
1945 /* Write out the real space on disk. */
1946 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
1954 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1957 SMB_STRUCT_STAT *pst;
1961 START_PROFILE(syscall_ftruncate);
1963 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
1964 result = strict_allocate_ftruncate(handle, fsp, len);
1965 END_PROFILE(syscall_ftruncate);
1969 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
1970 ftruncate if the system supports it. Then I discovered that
1971 you can have some filesystems that support ftruncate
1972 expansion and some that don't! On Linux fat can't do
1973 ftruncate extend but ext2 can. */
1975 result = ftruncate(fsp->fh->fd, len);
1977 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
1978 extend a file with ftruncate. Provide alternate implementation
1981 /* Do an fstat to see if the file is longer than the requested
1982 size in which case the ftruncate above should have
1983 succeeded or shorter, in which case seek to len - 1 and
1984 write 1 byte of zero */
1985 status = vfs_stat_fsp(fsp);
1986 if (!NT_STATUS_IS_OK(status)) {
1990 /* We need to update the files_struct after successful ftruncate */
1995 pst = &fsp->fsp_name->st;
1998 if (S_ISFIFO(pst->st_ex_mode)) {
2004 if (pst->st_ex_size == len) {
2009 if (pst->st_ex_size > len) {
2010 /* the ftruncate should have worked */
2014 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2022 END_PROFILE(syscall_ftruncate);
2026 static int vfswrap_fallocate(vfs_handle_struct *handle,
2034 START_PROFILE(syscall_fallocate);
2036 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2038 * posix_fallocate returns 0 on success, errno on error
2039 * and doesn't set errno. Make it behave like fallocate()
2040 * which returns -1, and sets errno on failure.
2047 /* sys_fallocate handles filtering of unsupported mode flags */
2048 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2050 END_PROFILE(syscall_fallocate);
2054 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2058 START_PROFILE(syscall_fcntl_lock);
2059 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2060 END_PROFILE(syscall_fcntl_lock);
2064 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2065 uint32_t share_mode, uint32_t access_mask)
2067 START_PROFILE(syscall_kernel_flock);
2068 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2069 END_PROFILE(syscall_kernel_flock);
2073 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2077 START_PROFILE(syscall_fcntl_getlock);
2078 result = fcntl_getlock(fsp->fh->fd, poffset, pcount, ptype, ppid);
2079 END_PROFILE(syscall_fcntl_getlock);
2083 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2088 START_PROFILE(syscall_linux_setlease);
2090 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2091 result = linux_setlease(fsp->fh->fd, leasetype);
2095 END_PROFILE(syscall_linux_setlease);
2099 static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2103 START_PROFILE(syscall_symlink);
2104 result = symlink(oldpath, newpath);
2105 END_PROFILE(syscall_symlink);
2109 static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
2113 START_PROFILE(syscall_readlink);
2114 result = readlink(path, buf, bufsiz);
2115 END_PROFILE(syscall_readlink);
2119 static int vfswrap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2123 START_PROFILE(syscall_link);
2124 result = link(oldpath, newpath);
2125 END_PROFILE(syscall_link);
2129 static int vfswrap_mknod(vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev)
2133 START_PROFILE(syscall_mknod);
2134 result = sys_mknod(pathname, mode, dev);
2135 END_PROFILE(syscall_mknod);
2139 static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
2143 START_PROFILE(syscall_realpath);
2144 #ifdef REALPATH_TAKES_NULL
2145 result = realpath(path, NULL);
2147 result = SMB_MALLOC_ARRAY(char, PATH_MAX+1);
2149 char *resolved_path = realpath(path, result);
2150 if (!resolved_path) {
2153 /* SMB_ASSERT(result == resolved_path) ? */
2154 result = resolved_path;
2158 END_PROFILE(syscall_realpath);
2162 static int vfswrap_chflags(vfs_handle_struct *handle, const char *path,
2166 return chflags(path, flags);
2173 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2174 const SMB_STRUCT_STAT *sbuf)
2178 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2182 key.devid = sbuf->st_ex_dev;
2183 key.inode = sbuf->st_ex_ino;
2184 /* key.extid is unused by default. */
2189 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2190 struct files_struct *fsp,
2192 TALLOC_CTX *mem_ctx,
2193 unsigned int *pnum_streams,
2194 struct stream_struct **pstreams)
2196 SMB_STRUCT_STAT sbuf;
2197 struct stream_struct *tmp_streams = NULL;
2200 if ((fsp != NULL) && (fsp->is_directory)) {
2202 * No default streams on directories
2207 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2208 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2211 struct smb_filename smb_fname;
2213 ZERO_STRUCT(smb_fname);
2214 smb_fname.base_name = discard_const_p(char, fname);
2216 if (lp_posix_pathnames()) {
2217 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname);
2219 ret = SMB_VFS_STAT(handle->conn, &smb_fname);
2221 sbuf = smb_fname.st;
2225 return map_nt_error_from_unix(errno);
2228 if (S_ISDIR(sbuf.st_ex_mode)) {
2232 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2233 (*pnum_streams) + 1);
2234 if (tmp_streams == NULL) {
2235 return NT_STATUS_NO_MEMORY;
2237 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2238 if (tmp_streams[*pnum_streams].name == NULL) {
2239 return NT_STATUS_NO_MEMORY;
2241 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2242 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2245 *pstreams = tmp_streams;
2247 return NT_STATUS_OK;
2250 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2253 TALLOC_CTX *mem_ctx,
2257 * Don't fall back to get_real_filename so callers can differentiate
2258 * between a full directory scan and an actual case-insensitive stat.
2264 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2267 return handle->conn->connectpath;
2270 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2271 struct byte_range_lock *br_lck,
2272 struct lock_struct *plock,
2275 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2277 /* Note: blr is not used in the default implementation. */
2278 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2281 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2282 struct messaging_context *msg_ctx,
2283 struct byte_range_lock *br_lck,
2284 const struct lock_struct *plock)
2286 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2288 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2291 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2292 struct byte_range_lock *br_lck,
2293 struct lock_struct *plock)
2295 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2297 /* Note: blr is not used in the default implementation. */
2298 return brl_lock_cancel_default(br_lck, plock);
2301 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2303 struct lock_struct *plock)
2305 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2306 plock->lock_type == WRITE_LOCK);
2308 return strict_lock_default(fsp, plock);
2311 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2313 struct lock_struct *plock)
2315 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2316 plock->lock_type == WRITE_LOCK);
2318 strict_unlock_default(fsp, plock);
2321 /* NT ACL operations. */
2323 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2325 uint32_t security_info,
2326 TALLOC_CTX *mem_ctx,
2327 struct security_descriptor **ppdesc)
2331 START_PROFILE(fget_nt_acl);
2332 result = posix_fget_nt_acl(fsp, security_info,
2334 END_PROFILE(fget_nt_acl);
2338 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2340 uint32_t security_info,
2341 TALLOC_CTX *mem_ctx,
2342 struct security_descriptor **ppdesc)
2346 START_PROFILE(get_nt_acl);
2347 result = posix_get_nt_acl(handle->conn, name, security_info,
2349 END_PROFILE(get_nt_acl);
2353 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2357 START_PROFILE(fset_nt_acl);
2358 result = set_nt_acl(fsp, security_info_sent, psd);
2359 END_PROFILE(fset_nt_acl);
2363 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2364 struct smb_filename *file,
2365 struct security_acl *sacl,
2366 uint32_t access_requested,
2367 uint32_t access_denied)
2369 return NT_STATUS_OK; /* Nothing to do here ... */
2372 static int vfswrap_chmod_acl(vfs_handle_struct *handle, const char *name, mode_t mode)
2380 START_PROFILE(chmod_acl);
2381 result = chmod_acl(handle->conn, name, mode);
2382 END_PROFILE(chmod_acl);
2387 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2395 START_PROFILE(fchmod_acl);
2396 result = fchmod_acl(fsp, mode);
2397 END_PROFILE(fchmod_acl);
2402 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2404 SMB_ACL_TYPE_T type,
2405 TALLOC_CTX *mem_ctx)
2407 return sys_acl_get_file(handle, path_p, type, mem_ctx);
2410 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2412 TALLOC_CTX *mem_ctx)
2414 return sys_acl_get_fd(handle, fsp, mem_ctx);
2417 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2419 return sys_acl_set_file(handle, name, acltype, theacl);
2422 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2424 return sys_acl_set_fd(handle, fsp, theacl);
2427 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
2429 return sys_acl_delete_def_file(handle, path);
2432 /****************************************************************
2433 Extended attribute operations.
2434 *****************************************************************/
2436 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
2438 return getxattr(path, name, value, size);
2441 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2443 return fgetxattr(fsp->fh->fd, name, value, size);
2446 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
2448 return listxattr(path, list, size);
2451 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2453 return flistxattr(fsp->fh->fd, list, size);
2456 static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
2458 return removexattr(path, name);
2461 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2463 return fremovexattr(fsp->fh->fd, name);
2466 static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
2468 return setxattr(path, name, value, size, flags);
2471 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2473 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2476 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2481 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2482 const struct smb_filename *fname,
2483 SMB_STRUCT_STAT *sbuf)
2487 bool offline = false;
2489 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2493 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2494 #if defined(ENOTSUP)
2500 status = get_full_smb_filename(talloc_tos(), fname, &path);
2501 if (!NT_STATUS_IS_OK(status)) {
2502 errno = map_errno_from_nt_status(status);
2506 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2513 static int vfswrap_set_offline(struct vfs_handle_struct *handle,
2514 const struct smb_filename *fname)
2516 /* We don't know how to set offline bit by default, needs to be overriden in the vfs modules */
2517 #if defined(ENOTSUP)
2523 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2524 struct files_struct *fsp,
2525 TALLOC_CTX *mem_ctx,
2528 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2531 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2532 struct files_struct *fsp,
2533 const DATA_BLOB old_cookie,
2534 TALLOC_CTX *mem_ctx,
2535 DATA_BLOB *new_cookie)
2537 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2541 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2542 struct smb_request *smb1req,
2543 struct smbXsrv_open *op,
2544 const DATA_BLOB old_cookie,
2545 TALLOC_CTX *mem_ctx,
2546 struct files_struct **fsp,
2547 DATA_BLOB *new_cookie)
2549 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2550 old_cookie, mem_ctx,
2554 static struct vfs_fn_pointers vfs_default_fns = {
2555 /* Disk operations */
2557 .connect_fn = vfswrap_connect,
2558 .disconnect_fn = vfswrap_disconnect,
2559 .disk_free_fn = vfswrap_disk_free,
2560 .get_quota_fn = vfswrap_get_quota,
2561 .set_quota_fn = vfswrap_set_quota,
2562 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2563 .statvfs_fn = vfswrap_statvfs,
2564 .fs_capabilities_fn = vfswrap_fs_capabilities,
2565 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2566 .snap_check_path_fn = vfswrap_snap_check_path,
2567 .snap_create_fn = vfswrap_snap_create,
2568 .snap_delete_fn = vfswrap_snap_delete,
2570 /* Directory operations */
2572 .opendir_fn = vfswrap_opendir,
2573 .fdopendir_fn = vfswrap_fdopendir,
2574 .readdir_fn = vfswrap_readdir,
2575 .readdir_attr_fn = vfswrap_readdir_attr,
2576 .seekdir_fn = vfswrap_seekdir,
2577 .telldir_fn = vfswrap_telldir,
2578 .rewind_dir_fn = vfswrap_rewinddir,
2579 .mkdir_fn = vfswrap_mkdir,
2580 .rmdir_fn = vfswrap_rmdir,
2581 .closedir_fn = vfswrap_closedir,
2582 .init_search_op_fn = vfswrap_init_search_op,
2584 /* File operations */
2586 .open_fn = vfswrap_open,
2587 .create_file_fn = vfswrap_create_file,
2588 .close_fn = vfswrap_close,
2589 .read_fn = vfswrap_read,
2590 .pread_fn = vfswrap_pread,
2591 .pread_send_fn = vfswrap_pread_send,
2592 .pread_recv_fn = vfswrap_asys_ssize_t_recv,
2593 .write_fn = vfswrap_write,
2594 .pwrite_fn = vfswrap_pwrite,
2595 .pwrite_send_fn = vfswrap_pwrite_send,
2596 .pwrite_recv_fn = vfswrap_asys_ssize_t_recv,
2597 .lseek_fn = vfswrap_lseek,
2598 .sendfile_fn = vfswrap_sendfile,
2599 .recvfile_fn = vfswrap_recvfile,
2600 .rename_fn = vfswrap_rename,
2601 .fsync_fn = vfswrap_fsync,
2602 .fsync_send_fn = vfswrap_fsync_send,
2603 .fsync_recv_fn = vfswrap_asys_int_recv,
2604 .stat_fn = vfswrap_stat,
2605 .fstat_fn = vfswrap_fstat,
2606 .lstat_fn = vfswrap_lstat,
2607 .get_alloc_size_fn = vfswrap_get_alloc_size,
2608 .unlink_fn = vfswrap_unlink,
2609 .chmod_fn = vfswrap_chmod,
2610 .fchmod_fn = vfswrap_fchmod,
2611 .chown_fn = vfswrap_chown,
2612 .fchown_fn = vfswrap_fchown,
2613 .lchown_fn = vfswrap_lchown,
2614 .chdir_fn = vfswrap_chdir,
2615 .getwd_fn = vfswrap_getwd,
2616 .ntimes_fn = vfswrap_ntimes,
2617 .ftruncate_fn = vfswrap_ftruncate,
2618 .fallocate_fn = vfswrap_fallocate,
2619 .lock_fn = vfswrap_lock,
2620 .kernel_flock_fn = vfswrap_kernel_flock,
2621 .linux_setlease_fn = vfswrap_linux_setlease,
2622 .getlock_fn = vfswrap_getlock,
2623 .symlink_fn = vfswrap_symlink,
2624 .readlink_fn = vfswrap_readlink,
2625 .link_fn = vfswrap_link,
2626 .mknod_fn = vfswrap_mknod,
2627 .realpath_fn = vfswrap_realpath,
2628 .chflags_fn = vfswrap_chflags,
2629 .file_id_create_fn = vfswrap_file_id_create,
2630 .streaminfo_fn = vfswrap_streaminfo,
2631 .get_real_filename_fn = vfswrap_get_real_filename,
2632 .connectpath_fn = vfswrap_connectpath,
2633 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2634 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2635 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2636 .strict_lock_fn = vfswrap_strict_lock,
2637 .strict_unlock_fn = vfswrap_strict_unlock,
2638 .translate_name_fn = vfswrap_translate_name,
2639 .fsctl_fn = vfswrap_fsctl,
2640 .copy_chunk_send_fn = vfswrap_copy_chunk_send,
2641 .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
2642 .get_compression_fn = vfswrap_get_compression,
2643 .set_compression_fn = vfswrap_set_compression,
2645 /* NT ACL operations. */
2647 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2648 .get_nt_acl_fn = vfswrap_get_nt_acl,
2649 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2650 .audit_file_fn = vfswrap_audit_file,
2652 /* POSIX ACL operations. */
2654 .chmod_acl_fn = vfswrap_chmod_acl,
2655 .fchmod_acl_fn = vfswrap_fchmod_acl,
2657 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2658 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2659 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2660 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2661 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2662 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2663 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2665 /* EA operations. */
2666 .getxattr_fn = vfswrap_getxattr,
2667 .fgetxattr_fn = vfswrap_fgetxattr,
2668 .listxattr_fn = vfswrap_listxattr,
2669 .flistxattr_fn = vfswrap_flistxattr,
2670 .removexattr_fn = vfswrap_removexattr,
2671 .fremovexattr_fn = vfswrap_fremovexattr,
2672 .setxattr_fn = vfswrap_setxattr,
2673 .fsetxattr_fn = vfswrap_fsetxattr,
2675 /* aio operations */
2676 .aio_force_fn = vfswrap_aio_force,
2678 /* offline operations */
2679 .is_offline_fn = vfswrap_is_offline,
2680 .set_offline_fn = vfswrap_set_offline,
2682 /* durable handle operations */
2683 .durable_cookie_fn = vfswrap_durable_cookie,
2684 .durable_disconnect_fn = vfswrap_durable_disconnect,
2685 .durable_reconnect_fn = vfswrap_durable_reconnect,
2688 NTSTATUS vfs_default_init(void);
2689 NTSTATUS vfs_default_init(void)
2691 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
2692 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);