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,
61 if (sys_fsusage(path, dfree, dsize) != 0) {
69 static int vfswrap_get_quota(struct vfs_handle_struct *handle, const char *path,
70 enum SMB_QUOTA_TYPE qtype, unid_t id,
73 #ifdef HAVE_SYS_QUOTAS
76 START_PROFILE(syscall_get_quota);
77 result = sys_get_quota(path, qtype, id, qt);
78 END_PROFILE(syscall_get_quota);
86 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
88 #ifdef HAVE_SYS_QUOTAS
91 START_PROFILE(syscall_set_quota);
92 result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
93 END_PROFILE(syscall_set_quota);
101 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
102 struct files_struct *fsp,
103 struct shadow_copy_data *shadow_copy_data,
107 return -1; /* Not implemented. */
110 static int vfswrap_statvfs(struct vfs_handle_struct *handle, const char *path, vfs_statvfs_struct *statbuf)
112 return sys_statvfs(path, statbuf);
115 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
116 enum timestamp_set_resolution *p_ts_res)
118 connection_struct *conn = handle->conn;
119 uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
120 struct smb_filename *smb_fname_cpath = NULL;
121 struct vfs_statvfs_struct statbuf;
124 ZERO_STRUCT(statbuf);
125 ret = sys_statvfs(conn->connectpath, &statbuf);
127 caps = statbuf.FsCapabilities;
130 *p_ts_res = TIMESTAMP_SET_SECONDS;
132 /* Work out what timestamp resolution we can
133 * use when setting a timestamp. */
135 smb_fname_cpath = synthetic_smb_fname(talloc_tos(), conn->connectpath,
137 if (smb_fname_cpath == NULL) {
141 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
143 TALLOC_FREE(smb_fname_cpath);
147 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
148 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
149 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
150 /* If any of the normal UNIX directory timestamps
151 * have a non-zero tv_nsec component assume
152 * we might be able to set sub-second timestamps.
153 * See what filetime set primitives we have.
155 #if defined(HAVE_UTIMENSAT)
156 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
157 #elif defined(HAVE_UTIMES)
158 /* utimes allows msec timestamps to be set. */
159 *p_ts_res = TIMESTAMP_SET_MSEC;
160 #elif defined(HAVE_UTIME)
161 /* utime only allows sec timestamps to be set. */
162 *p_ts_res = TIMESTAMP_SET_SECONDS;
165 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
167 "available on share %s, directory %s\n",
168 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
169 lp_servicename(talloc_tos(), conn->params->service),
170 conn->connectpath ));
172 TALLOC_FREE(smb_fname_cpath);
176 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
177 struct dfs_GetDFSReferral *r)
179 struct junction_map *junction = NULL;
181 bool self_referral = false;
182 char *pathnamep = NULL;
183 char *local_dfs_path = NULL;
186 uint16_t max_referral_level = r->in.req.max_referral_level;
189 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
192 /* get the junction entry */
193 if (r->in.req.servername == NULL) {
194 return NT_STATUS_NOT_FOUND;
198 * Trim pathname sent by client so it begins with only one backslash.
199 * Two backslashes confuse some dfs clients
202 local_dfs_path = talloc_strdup(r, r->in.req.servername);
203 if (local_dfs_path == NULL) {
204 return NT_STATUS_NO_MEMORY;
206 pathnamep = local_dfs_path;
207 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
208 IS_DIRECTORY_SEP(pathnamep[1])) {
212 junction = talloc_zero(r, struct junction_map);
213 if (junction == NULL) {
214 return NT_STATUS_NO_MEMORY;
217 /* The following call can change cwd. */
218 status = get_referred_path(r, pathnamep,
219 !handle->conn->sconn->using_smb2,
220 junction, &consumedcnt, &self_referral);
221 if (!NT_STATUS_IS_OK(status)) {
222 vfs_ChDir(handle->conn, handle->conn->connectpath);
225 vfs_ChDir(handle->conn, handle->conn->connectpath);
227 if (!self_referral) {
228 pathnamep[consumedcnt] = '\0';
231 dbgtext("Path %s to alternate path(s):",
233 for (i=0; i < junction->referral_count; i++) {
235 junction->referral_list[i].alternate_path);
241 if (r->in.req.max_referral_level <= 2) {
242 max_referral_level = 2;
244 if (r->in.req.max_referral_level >= 3) {
245 max_referral_level = 3;
248 r->out.resp = talloc_zero(r, struct dfs_referral_resp);
249 if (r->out.resp == NULL) {
250 return NT_STATUS_NO_MEMORY;
253 r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
254 r->out.resp->nb_referrals = junction->referral_count;
256 r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
258 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
261 r->out.resp->referral_entries = talloc_zero_array(r,
262 struct dfs_referral_type,
263 r->out.resp->nb_referrals);
264 if (r->out.resp->referral_entries == NULL) {
265 return NT_STATUS_NO_MEMORY;
268 switch (max_referral_level) {
270 for(i=0; i < junction->referral_count; i++) {
271 struct referral *ref = &junction->referral_list[i];
272 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
273 struct dfs_referral_type *t =
274 &r->out.resp->referral_entries[i];
275 struct dfs_referral_v2 *v2 = &t->referral.v2;
278 v2->size = VERSION2_REFERRAL_SIZE;
280 v2->server_type = DFS_SERVER_ROOT;
282 v2->server_type = DFS_SERVER_NON_ROOT;
285 v2->proximity = ref->proximity;
287 v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
288 if (v2->DFS_path == NULL) {
289 return NT_STATUS_NO_MEMORY;
291 v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
292 if (v2->DFS_alt_path == NULL) {
293 return NT_STATUS_NO_MEMORY;
295 v2->netw_address = talloc_strdup(mem_ctx,
296 ref->alternate_path);
297 if (v2->netw_address == NULL) {
298 return NT_STATUS_NO_MEMORY;
304 for(i=0; i < junction->referral_count; i++) {
305 struct referral *ref = &junction->referral_list[i];
306 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
307 struct dfs_referral_type *t =
308 &r->out.resp->referral_entries[i];
309 struct dfs_referral_v3 *v3 = &t->referral.v3;
310 struct dfs_normal_referral *r1 = &v3->referrals.r1;
313 v3->size = VERSION3_REFERRAL_SIZE;
315 v3->server_type = DFS_SERVER_ROOT;
317 v3->server_type = DFS_SERVER_NON_ROOT;
321 r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
322 if (r1->DFS_path == NULL) {
323 return NT_STATUS_NO_MEMORY;
325 r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
326 if (r1->DFS_alt_path == NULL) {
327 return NT_STATUS_NO_MEMORY;
329 r1->netw_address = talloc_strdup(mem_ctx,
330 ref->alternate_path);
331 if (r1->netw_address == NULL) {
332 return NT_STATUS_NO_MEMORY;
337 DEBUG(0,("Invalid dfs referral version: %d\n",
338 max_referral_level));
339 return NT_STATUS_INVALID_LEVEL;
343 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
349 static NTSTATUS vfswrap_snap_check_path(struct vfs_handle_struct *handle,
351 const char *service_path,
354 return NT_STATUS_NOT_SUPPORTED;
357 static NTSTATUS vfswrap_snap_create(struct vfs_handle_struct *handle,
359 const char *base_volume,
365 return NT_STATUS_NOT_SUPPORTED;
368 static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle,
373 return NT_STATUS_NOT_SUPPORTED;
376 /* Directory operations */
378 static DIR *vfswrap_opendir(vfs_handle_struct *handle,
379 const struct smb_filename *smb_fname,
385 START_PROFILE(syscall_opendir);
386 result = opendir(smb_fname->base_name);
387 END_PROFILE(syscall_opendir);
391 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
398 START_PROFILE(syscall_fdopendir);
399 result = sys_fdopendir(fsp->fh->fd);
400 END_PROFILE(syscall_fdopendir);
405 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
407 SMB_STRUCT_STAT *sbuf)
409 struct dirent *result;
411 START_PROFILE(syscall_readdir);
412 result = readdir(dirp);
413 END_PROFILE(syscall_readdir);
415 /* Default Posix readdir() does not give us stat info.
416 * Set to invalid to indicate we didn't return this info. */
417 SET_STAT_INVALID(*sbuf);
418 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
419 if (result != NULL) {
420 /* See if we can efficiently return this. */
422 int flags = AT_SYMLINK_NOFOLLOW;
423 int ret = fstatat(dirfd(dirp),
428 * As this is an optimization,
429 * ignore it if we stat'ed a
430 * symlink. Make the caller
431 * do it again as we don't
432 * know if they wanted the link
433 * info, or its target info.
435 if ((ret == 0) && (!S_ISLNK(st.st_mode))) {
436 init_stat_ex_from_stat(sbuf,
438 lp_fake_directory_create_times(
439 SNUM(handle->conn)));
447 static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
448 const struct smb_filename *fname,
450 struct readdir_attr_data **attr_data)
452 return NT_STATUS_NOT_SUPPORTED;
455 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
457 START_PROFILE(syscall_seekdir);
458 seekdir(dirp, offset);
459 END_PROFILE(syscall_seekdir);
462 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
465 START_PROFILE(syscall_telldir);
466 result = telldir(dirp);
467 END_PROFILE(syscall_telldir);
471 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
473 START_PROFILE(syscall_rewinddir);
475 END_PROFILE(syscall_rewinddir);
478 static int vfswrap_mkdir(vfs_handle_struct *handle,
479 const struct smb_filename *smb_fname,
483 bool has_dacl = False;
484 const char *path = smb_fname->base_name;
487 START_PROFILE(syscall_mkdir);
489 if (lp_inherit_acls(SNUM(handle->conn))
490 && parent_dirname(talloc_tos(), path, &parent, NULL)
491 && (has_dacl = directory_has_default_acl(handle->conn, parent))) {
492 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
497 result = mkdir(path, mode);
499 if (result == 0 && !has_dacl) {
501 * We need to do this as the default behavior of POSIX ACLs
502 * is to set the mask to be the requested group permission
503 * bits, not the group permission bits to be the requested
504 * group permission bits. This is not what we want, as it will
505 * mess up any inherited ACL bits that were set. JRA.
507 int saved_errno = errno; /* We may get ENOSYS */
508 if ((SMB_VFS_CHMOD_ACL(handle->conn, smb_fname, mode) == -1) &&
514 END_PROFILE(syscall_mkdir);
518 static int vfswrap_rmdir(vfs_handle_struct *handle,
519 const struct smb_filename *smb_fname)
523 START_PROFILE(syscall_rmdir);
524 result = rmdir(smb_fname->base_name);
525 END_PROFILE(syscall_rmdir);
529 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
533 START_PROFILE(syscall_closedir);
534 result = closedir(dirp);
535 END_PROFILE(syscall_closedir);
539 static void vfswrap_init_search_op(vfs_handle_struct *handle,
542 /* Default behavior is a NOOP */
545 /* File operations */
547 static int vfswrap_open(vfs_handle_struct *handle,
548 struct smb_filename *smb_fname,
549 files_struct *fsp, int flags, mode_t mode)
553 START_PROFILE(syscall_open);
555 if (smb_fname->stream_name) {
560 result = open(smb_fname->base_name, flags, mode);
562 END_PROFILE(syscall_open);
566 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
567 struct smb_request *req,
568 uint16_t root_dir_fid,
569 struct smb_filename *smb_fname,
570 uint32_t access_mask,
571 uint32_t share_access,
572 uint32_t create_disposition,
573 uint32_t create_options,
574 uint32_t file_attributes,
575 uint32_t oplock_request,
576 struct smb2_lease *lease,
577 uint64_t allocation_size,
578 uint32_t private_flags,
579 struct security_descriptor *sd,
580 struct ea_list *ea_list,
581 files_struct **result,
583 const struct smb2_create_blobs *in_context_blobs,
584 struct smb2_create_blobs *out_context_blobs)
586 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
587 access_mask, share_access,
588 create_disposition, create_options,
589 file_attributes, oplock_request, lease,
590 allocation_size, private_flags,
592 pinfo, in_context_blobs, out_context_blobs);
595 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
599 START_PROFILE(syscall_close);
600 result = fd_close_posix(fsp);
601 END_PROFILE(syscall_close);
605 static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
609 START_PROFILE_BYTES(syscall_read, n);
610 result = sys_read(fsp->fh->fd, data, n);
611 END_PROFILE_BYTES(syscall_read);
615 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
616 size_t n, off_t offset)
620 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
621 START_PROFILE_BYTES(syscall_pread, n);
622 result = sys_pread(fsp->fh->fd, data, n, offset);
623 END_PROFILE_BYTES(syscall_pread);
625 if (result == -1 && errno == ESPIPE) {
626 /* Maintain the fiction that pipes can be seeked (sought?) on. */
627 result = SMB_VFS_READ(fsp, data, n);
631 #else /* HAVE_PREAD */
635 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
636 if (curr == -1 && errno == ESPIPE) {
637 /* Maintain the fiction that pipes can be seeked (sought?) on. */
638 result = SMB_VFS_READ(fsp, data, n);
643 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
648 result = SMB_VFS_READ(fsp, data, n);
651 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
654 #endif /* HAVE_PREAD */
659 static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
663 START_PROFILE_BYTES(syscall_write, n);
664 result = sys_write(fsp->fh->fd, data, n);
665 END_PROFILE_BYTES(syscall_write);
669 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
670 size_t n, off_t offset)
674 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
675 START_PROFILE_BYTES(syscall_pwrite, n);
676 result = sys_pwrite(fsp->fh->fd, data, n, offset);
677 END_PROFILE_BYTES(syscall_pwrite);
679 if (result == -1 && errno == ESPIPE) {
680 /* Maintain the fiction that pipes can be sought on. */
681 result = SMB_VFS_WRITE(fsp, data, n);
684 #else /* HAVE_PWRITE */
688 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
693 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
697 result = SMB_VFS_WRITE(fsp, data, n);
700 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
703 #endif /* HAVE_PWRITE */
708 static void vfswrap_asys_finished(struct tevent_context *ev,
709 struct tevent_fd *fde,
710 uint16_t flags, void *p);
712 static bool vfswrap_init_asys_ctx(struct smbd_server_connection *conn)
714 struct asys_context *ctx;
715 struct tevent_fd *fde;
719 if (conn->asys_ctx != NULL) {
723 ret = asys_context_init(&ctx, lp_aio_max_threads());
725 DEBUG(1, ("asys_context_init failed: %s\n", strerror(ret)));
729 fd = asys_signalfd(ctx);
731 ret = set_blocking(fd, false);
733 DBG_WARNING("set_blocking failed: %s\n", strerror(errno));
737 fde = tevent_add_fd(conn->ev_ctx, conn, fd, TEVENT_FD_READ,
738 vfswrap_asys_finished, ctx);
740 DEBUG(1, ("tevent_add_fd failed\n"));
744 conn->asys_ctx = ctx;
745 conn->asys_fde = fde;
749 asys_context_destroy(ctx);
753 struct vfswrap_asys_state {
754 struct asys_context *asys_ctx;
755 struct tevent_req *req;
757 struct vfs_aio_state vfs_aio_state;
758 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
759 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
762 static int vfswrap_asys_state_destructor(struct vfswrap_asys_state *s)
764 asys_cancel(s->asys_ctx, s->req);
768 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
770 struct tevent_context *ev,
771 struct files_struct *fsp,
773 size_t n, off_t offset)
775 struct tevent_req *req;
776 struct vfswrap_asys_state *state;
779 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
783 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
785 return tevent_req_post(req, ev);
787 state->asys_ctx = handle->conn->sconn->asys_ctx;
790 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
791 state->profile_bytes, n);
792 ret = asys_pread(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
794 tevent_req_error(req, ret);
795 return tevent_req_post(req, ev);
797 talloc_set_destructor(state, vfswrap_asys_state_destructor);
802 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
804 struct tevent_context *ev,
805 struct files_struct *fsp,
807 size_t n, off_t offset)
809 struct tevent_req *req;
810 struct vfswrap_asys_state *state;
813 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
817 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
819 return tevent_req_post(req, ev);
821 state->asys_ctx = handle->conn->sconn->asys_ctx;
824 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
825 state->profile_bytes, n);
826 ret = asys_pwrite(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
828 tevent_req_error(req, ret);
829 return tevent_req_post(req, ev);
831 talloc_set_destructor(state, vfswrap_asys_state_destructor);
836 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
838 struct tevent_context *ev,
839 struct files_struct *fsp)
841 struct tevent_req *req;
842 struct vfswrap_asys_state *state;
845 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
849 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
851 return tevent_req_post(req, ev);
853 state->asys_ctx = handle->conn->sconn->asys_ctx;
856 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
857 state->profile_basic);
858 ret = asys_fsync(state->asys_ctx, fsp->fh->fd, req);
860 tevent_req_error(req, ret);
861 return tevent_req_post(req, ev);
863 talloc_set_destructor(state, vfswrap_asys_state_destructor);
868 static void vfswrap_asys_finished(struct tevent_context *ev,
869 struct tevent_fd *fde,
870 uint16_t flags, void *p)
872 struct asys_context *asys_ctx = (struct asys_context *)p;
873 struct asys_result results[get_outstanding_aio_calls()];
876 if ((flags & TEVENT_FD_READ) == 0) {
880 ret = asys_results(asys_ctx, results, get_outstanding_aio_calls());
882 DEBUG(1, ("asys_results returned %s\n", strerror(-ret)));
886 for (i=0; i<ret; i++) {
887 struct asys_result *result = &results[i];
888 struct tevent_req *req;
889 struct vfswrap_asys_state *state;
891 if ((result->ret == -1) && (result->err == ECANCELED)) {
895 req = talloc_get_type_abort(result->private_data,
897 state = tevent_req_data(req, struct vfswrap_asys_state);
899 talloc_set_destructor(state, NULL);
901 SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
902 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
903 state->ret = result->ret;
904 state->vfs_aio_state.error = result->err;
905 state->vfs_aio_state.duration = result->duration;
906 tevent_req_defer_callback(req, ev);
907 tevent_req_done(req);
911 static ssize_t vfswrap_asys_ssize_t_recv(struct tevent_req *req,
912 struct vfs_aio_state *vfs_aio_state)
914 struct vfswrap_asys_state *state = tevent_req_data(
915 req, struct vfswrap_asys_state);
917 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
920 *vfs_aio_state = state->vfs_aio_state;
924 static int vfswrap_asys_int_recv(struct tevent_req *req,
925 struct vfs_aio_state *vfs_aio_state)
927 struct vfswrap_asys_state *state = tevent_req_data(
928 req, struct vfswrap_asys_state);
930 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
933 *vfs_aio_state = state->vfs_aio_state;
937 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
941 START_PROFILE(syscall_lseek);
943 /* Cope with 'stat' file opens. */
944 if (fsp->fh->fd != -1)
945 result = lseek(fsp->fh->fd, offset, whence);
948 * We want to maintain the fiction that we can seek
949 * on a fifo for file system purposes. This allows
950 * people to set up UNIX fifo's that feed data to Windows
954 if((result == -1) && (errno == ESPIPE)) {
959 END_PROFILE(syscall_lseek);
963 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
964 off_t offset, size_t n)
968 START_PROFILE_BYTES(syscall_sendfile, n);
969 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
970 END_PROFILE_BYTES(syscall_sendfile);
974 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
982 START_PROFILE_BYTES(syscall_recvfile, n);
983 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
984 END_PROFILE_BYTES(syscall_recvfile);
988 static int vfswrap_rename(vfs_handle_struct *handle,
989 const struct smb_filename *smb_fname_src,
990 const struct smb_filename *smb_fname_dst)
994 START_PROFILE(syscall_rename);
996 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
1001 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
1004 END_PROFILE(syscall_rename);
1008 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
1013 START_PROFILE(syscall_fsync);
1014 result = fsync(fsp->fh->fd);
1015 END_PROFILE(syscall_fsync);
1022 static int vfswrap_stat(vfs_handle_struct *handle,
1023 struct smb_filename *smb_fname)
1027 START_PROFILE(syscall_stat);
1029 if (smb_fname->stream_name) {
1034 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1035 lp_fake_directory_create_times(SNUM(handle->conn)));
1037 END_PROFILE(syscall_stat);
1041 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1045 START_PROFILE(syscall_fstat);
1046 result = sys_fstat(fsp->fh->fd,
1047 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1048 END_PROFILE(syscall_fstat);
1052 static int vfswrap_lstat(vfs_handle_struct *handle,
1053 struct smb_filename *smb_fname)
1057 START_PROFILE(syscall_lstat);
1059 if (smb_fname->stream_name) {
1064 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1065 lp_fake_directory_create_times(SNUM(handle->conn)));
1067 END_PROFILE(syscall_lstat);
1071 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1073 enum vfs_translate_direction direction,
1074 TALLOC_CTX *mem_ctx,
1077 return NT_STATUS_NONE_MAPPED;
1081 * Implement the default fsctl operation.
1083 static bool vfswrap_logged_ioctl_message = false;
1085 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1086 struct files_struct *fsp,
1089 uint16_t req_flags, /* Needed for UNICODE ... */
1090 const uint8_t *_in_data,
1092 uint8_t **_out_data,
1093 uint32_t max_out_len,
1096 const char *in_data = (const char *)_in_data;
1097 char **out_data = (char **)_out_data;
1101 case FSCTL_SET_SPARSE:
1103 bool set_sparse = true;
1105 if (in_len >= 1 && in_data[0] == 0) {
1109 status = file_set_sparse(handle->conn, fsp, set_sparse);
1111 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1112 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1113 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1114 nt_errstr(status)));
1119 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1121 unsigned char objid[16];
1122 char *return_data = NULL;
1124 /* This should return the object-id on this file.
1125 * I think I'll make this be the inode+dev. JRA.
1128 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1129 fsp_fnum_dbg(fsp)));
1131 *out_len = MIN(max_out_len, 64);
1133 /* Hmmm, will this cause problems if less data asked for? */
1134 return_data = talloc_array(ctx, char, 64);
1135 if (return_data == NULL) {
1136 return NT_STATUS_NO_MEMORY;
1139 /* For backwards compatibility only store the dev/inode. */
1140 push_file_id_16(return_data, &fsp->file_id);
1141 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1142 push_file_id_16(return_data+32, &fsp->file_id);
1143 memset(return_data+48, 0, 16);
1144 *out_data = return_data;
1145 return NT_STATUS_OK;
1148 case FSCTL_GET_REPARSE_POINT:
1150 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1151 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1152 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1153 return NT_STATUS_NOT_A_REPARSE_POINT;
1156 case FSCTL_SET_REPARSE_POINT:
1158 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1159 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1160 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1161 return NT_STATUS_NOT_A_REPARSE_POINT;
1164 case FSCTL_GET_SHADOW_COPY_DATA:
1167 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1168 * and return their volume names. If max_data_count is 16, then it is just
1169 * asking for the number of volumes and length of the combined names.
1171 * pdata is the data allocated by our caller, but that uses
1172 * total_data_count (which is 0 in our case) rather than max_data_count.
1173 * Allocate the correct amount and return the pointer to let
1174 * it be deallocated when we return.
1176 struct shadow_copy_data *shadow_data = NULL;
1177 bool labels = False;
1178 uint32_t labels_data_count = 0;
1180 char *cur_pdata = NULL;
1182 if (max_out_len < 16) {
1183 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1185 return NT_STATUS_INVALID_PARAMETER;
1188 if (max_out_len > 16) {
1192 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1193 if (shadow_data == NULL) {
1194 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1195 return NT_STATUS_NO_MEMORY;
1199 * Call the VFS routine to actually do the work.
1201 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1204 /* broken module didn't set errno on error */
1205 status = NT_STATUS_UNSUCCESSFUL;
1207 status = map_nt_error_from_unix(errno);
1208 if (NT_STATUS_EQUAL(status,
1209 NT_STATUS_NOT_SUPPORTED)) {
1213 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1214 "connectpath %s, failed - %s.\n",
1215 fsp->conn->connectpath,
1216 nt_errstr(status)));
1217 TALLOC_FREE(shadow_data);
1221 labels_data_count = (shadow_data->num_volumes * 2 *
1222 sizeof(SHADOW_COPY_LABEL)) + 2;
1227 *out_len = 12 + labels_data_count;
1230 if (max_out_len < *out_len) {
1231 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1232 max_out_len, *out_len));
1233 TALLOC_FREE(shadow_data);
1234 return NT_STATUS_BUFFER_TOO_SMALL;
1237 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1238 if (cur_pdata == NULL) {
1239 TALLOC_FREE(shadow_data);
1240 return NT_STATUS_NO_MEMORY;
1243 *out_data = cur_pdata;
1245 /* num_volumes 4 bytes */
1246 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1249 /* num_labels 4 bytes */
1250 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1253 /* needed_data_count 4 bytes */
1254 SIVAL(cur_pdata, 8, labels_data_count);
1258 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1259 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1260 if (labels && shadow_data->labels) {
1261 for (i=0; i<shadow_data->num_volumes; i++) {
1263 status = srvstr_push(cur_pdata, req_flags,
1264 cur_pdata, shadow_data->labels[i],
1265 2 * sizeof(SHADOW_COPY_LABEL),
1266 STR_UNICODE|STR_TERMINATE, &len);
1267 if (!NT_STATUS_IS_OK(status)) {
1268 TALLOC_FREE(*out_data);
1269 TALLOC_FREE(shadow_data);
1272 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1273 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1277 TALLOC_FREE(shadow_data);
1279 return NT_STATUS_OK;
1282 case FSCTL_FIND_FILES_BY_SID:
1284 /* pretend this succeeded -
1286 * we have to send back a list with all files owned by this SID
1288 * but I have to check that --metze
1294 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1295 fsp_fnum_dbg(fsp)));
1298 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1299 return NT_STATUS_INVALID_PARAMETER;
1302 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1304 /* unknown 4 bytes: this is not the length of the sid :-( */
1305 /*unknown = IVAL(pdata,0);*/
1307 if (!sid_parse(_in_data + 4, sid_len, &sid)) {
1308 return NT_STATUS_INVALID_PARAMETER;
1310 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1312 if (!sid_to_uid(&sid, &uid)) {
1313 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1314 sid_string_dbg(&sid),
1315 (unsigned long)sid_len));
1319 /* we can take a look at the find source :-)
1321 * find ./ -uid $uid -name '*' is what we need here
1324 * and send 4bytes len and then NULL terminated unicode strings
1327 * but I don't know how to deal with the paged results
1328 * (maybe we can hang the result anywhere in the fsp struct)
1330 * but I don't know how to deal with the paged results
1331 * (maybe we can hang the result anywhere in the fsp struct)
1333 * we don't send all files at once
1334 * and at the next we should *not* start from the beginning,
1335 * so we have to cache the result
1340 /* this works for now... */
1341 return NT_STATUS_OK;
1344 case FSCTL_QUERY_ALLOCATED_RANGES:
1346 /* FIXME: This is just a dummy reply, telling that all of the
1347 * file is allocated. MKS cp needs that.
1348 * Adding the real allocated ranges via FIEMAP on Linux
1349 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1350 * this FSCTL correct for sparse files.
1352 uint64_t offset, length;
1353 char *out_data_tmp = NULL;
1356 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1358 return NT_STATUS_INVALID_PARAMETER;
1361 if (max_out_len < 16) {
1362 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1364 return NT_STATUS_INVALID_PARAMETER;
1367 offset = BVAL(in_data,0);
1368 length = BVAL(in_data,8);
1370 if (offset + length < offset) {
1371 /* No 64-bit integer wrap. */
1372 return NT_STATUS_INVALID_PARAMETER;
1375 /* Shouldn't this be SMB_VFS_STAT ... ? */
1376 status = vfs_stat_fsp(fsp);
1377 if (!NT_STATUS_IS_OK(status)) {
1382 out_data_tmp = talloc_array(ctx, char, *out_len);
1383 if (out_data_tmp == NULL) {
1384 DEBUG(10, ("unable to allocate memory for response\n"));
1385 return NT_STATUS_NO_MEMORY;
1388 if (offset > fsp->fsp_name->st.st_ex_size ||
1389 fsp->fsp_name->st.st_ex_size == 0 ||
1391 memset(out_data_tmp, 0, *out_len);
1393 uint64_t end = offset + length;
1394 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1395 SBVAL(out_data_tmp, 0, 0);
1396 SBVAL(out_data_tmp, 8, end);
1399 *out_data = out_data_tmp;
1401 return NT_STATUS_OK;
1404 case FSCTL_IS_VOLUME_DIRTY:
1406 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1407 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1409 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1410 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1412 return NT_STATUS_INVALID_PARAMETER;
1417 * Only print once ... unfortunately there could be lots of
1418 * different FSCTLs that are called.
1420 if (!vfswrap_logged_ioctl_message) {
1421 vfswrap_logged_ioctl_message = true;
1422 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1423 __func__, function));
1427 return NT_STATUS_NOT_SUPPORTED;
1430 struct vfs_cc_state {
1435 static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *handle,
1436 TALLOC_CTX *mem_ctx,
1437 struct tevent_context *ev,
1438 struct files_struct *src_fsp,
1440 struct files_struct *dest_fsp,
1444 struct tevent_req *req;
1445 struct vfs_cc_state *vfs_cc_state;
1448 DEBUG(10, ("performing server side copy chunk of length %lu\n",
1449 (unsigned long)num));
1451 req = tevent_req_create(mem_ctx, &vfs_cc_state, struct vfs_cc_state);
1456 vfs_cc_state->buf = talloc_array(vfs_cc_state, uint8_t,
1457 MIN(num, 8*1024*1024));
1458 if (tevent_req_nomem(vfs_cc_state->buf, req)) {
1459 return tevent_req_post(req, ev);
1462 status = vfs_stat_fsp(src_fsp);
1463 if (tevent_req_nterror(req, status)) {
1464 return tevent_req_post(req, ev);
1467 if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
1469 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1470 * If the SourceOffset or SourceOffset + Length extends beyond
1471 * the end of file, the server SHOULD<240> treat this as a
1472 * STATUS_END_OF_FILE error.
1474 * <240> Section 3.3.5.15.6: Windows servers will return
1475 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1477 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1478 return tevent_req_post(req, ev);
1481 /* could use 2.6.33+ sendfile here to do this in kernel */
1482 while (vfs_cc_state->copied < num) {
1484 struct lock_struct lck;
1487 off_t this_num = MIN(talloc_array_length(vfs_cc_state->buf),
1488 num - vfs_cc_state->copied);
1490 if (src_fsp->op == NULL) {
1491 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1492 return tevent_req_post(req, ev);
1494 init_strict_lock_struct(src_fsp,
1495 src_fsp->op->global->open_persistent_id,
1501 if (!SMB_VFS_STRICT_LOCK(src_fsp->conn, src_fsp, &lck)) {
1502 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1503 return tevent_req_post(req, ev);
1506 ret = SMB_VFS_PREAD(src_fsp, vfs_cc_state->buf,
1509 saved_errno = errno;
1512 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1515 errno = saved_errno;
1516 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1517 return tevent_req_post(req, ev);
1519 if (ret != this_num) {
1520 /* zero tolerance for short reads */
1521 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1522 return tevent_req_post(req, ev);
1527 if (dest_fsp->op == NULL) {
1528 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1529 return tevent_req_post(req, ev);
1532 init_strict_lock_struct(dest_fsp,
1533 dest_fsp->op->global->open_persistent_id,
1539 if (!SMB_VFS_STRICT_LOCK(dest_fsp->conn, dest_fsp, &lck)) {
1540 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1541 return tevent_req_post(req, ev);
1544 ret = SMB_VFS_PWRITE(dest_fsp, vfs_cc_state->buf,
1545 this_num, dest_off);
1547 saved_errno = errno;
1550 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1553 errno = saved_errno;
1554 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1555 return tevent_req_post(req, ev);
1557 if (ret != this_num) {
1558 /* zero tolerance for short writes */
1559 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1560 return tevent_req_post(req, ev);
1564 vfs_cc_state->copied += this_num;
1567 tevent_req_done(req);
1568 return tevent_req_post(req, ev);
1571 static NTSTATUS vfswrap_copy_chunk_recv(struct vfs_handle_struct *handle,
1572 struct tevent_req *req,
1575 struct vfs_cc_state *vfs_cc_state = tevent_req_data(req,
1576 struct vfs_cc_state);
1579 if (tevent_req_is_nterror(req, &status)) {
1580 DEBUG(2, ("server side copy chunk failed: %s\n",
1581 nt_errstr(status)));
1583 tevent_req_received(req);
1587 *copied = vfs_cc_state->copied;
1588 DEBUG(10, ("server side copy chunk copied %lu\n",
1589 (unsigned long)*copied));
1590 tevent_req_received(req);
1592 return NT_STATUS_OK;
1595 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1596 TALLOC_CTX *mem_ctx,
1597 struct files_struct *fsp,
1598 struct smb_filename *smb_fname,
1599 uint16_t *_compression_fmt)
1601 return NT_STATUS_INVALID_DEVICE_REQUEST;
1604 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1605 TALLOC_CTX *mem_ctx,
1606 struct files_struct *fsp,
1607 uint16_t compression_fmt)
1609 return NT_STATUS_INVALID_DEVICE_REQUEST;
1612 /********************************************************************
1613 Given a stat buffer return the allocated size on disk, taking into
1614 account sparse files.
1615 ********************************************************************/
1616 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1617 struct files_struct *fsp,
1618 const SMB_STRUCT_STAT *sbuf)
1622 START_PROFILE(syscall_get_alloc_size);
1624 if(S_ISDIR(sbuf->st_ex_mode)) {
1629 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1630 /* The type of st_blocksize is blkcnt_t which *MUST* be
1631 signed (according to POSIX) and can be less than 64-bits.
1632 Ensure when we're converting to 64 bits wide we don't
1634 #if defined(SIZEOF_BLKCNT_T_8)
1635 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1636 #elif defined(SIZEOF_BLKCNT_T_4)
1638 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1639 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1642 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1646 * Some file systems do not allocate a block for very
1647 * small files. But for non-empty file should report a
1651 uint64_t filesize = get_file_size_stat(sbuf);
1653 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
1657 result = get_file_size_stat(sbuf);
1660 if (fsp && fsp->initial_allocation_size)
1661 result = MAX(result,fsp->initial_allocation_size);
1663 result = smb_roundup(handle->conn, result);
1666 END_PROFILE(syscall_get_alloc_size);
1670 static int vfswrap_unlink(vfs_handle_struct *handle,
1671 const struct smb_filename *smb_fname)
1675 START_PROFILE(syscall_unlink);
1677 if (smb_fname->stream_name) {
1681 result = unlink(smb_fname->base_name);
1684 END_PROFILE(syscall_unlink);
1688 static int vfswrap_chmod(vfs_handle_struct *handle,
1689 const struct smb_filename *smb_fname,
1694 START_PROFILE(syscall_chmod);
1697 * We need to do this due to the fact that the default POSIX ACL
1698 * chmod modifies the ACL *mask* for the group owner, not the
1699 * group owner bits directly. JRA.
1704 int saved_errno = errno; /* We might get ENOSYS */
1705 result = SMB_VFS_CHMOD_ACL(handle->conn,
1709 END_PROFILE(syscall_chmod);
1712 /* Error - return the old errno. */
1713 errno = saved_errno;
1716 result = chmod(smb_fname->base_name, mode);
1717 END_PROFILE(syscall_chmod);
1721 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
1725 START_PROFILE(syscall_fchmod);
1728 * We need to do this due to the fact that the default POSIX ACL
1729 * chmod modifies the ACL *mask* for the group owner, not the
1730 * group owner bits directly. JRA.
1734 int saved_errno = errno; /* We might get ENOSYS */
1735 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
1736 END_PROFILE(syscall_fchmod);
1739 /* Error - return the old errno. */
1740 errno = saved_errno;
1743 #if defined(HAVE_FCHMOD)
1744 result = fchmod(fsp->fh->fd, mode);
1750 END_PROFILE(syscall_fchmod);
1754 static int vfswrap_chown(vfs_handle_struct *handle,
1755 const struct smb_filename *smb_fname,
1761 START_PROFILE(syscall_chown);
1762 result = chown(smb_fname->base_name, uid, gid);
1763 END_PROFILE(syscall_chown);
1767 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
1772 START_PROFILE(syscall_fchown);
1773 result = fchown(fsp->fh->fd, uid, gid);
1774 END_PROFILE(syscall_fchown);
1782 static int vfswrap_lchown(vfs_handle_struct *handle,
1783 const struct smb_filename *smb_fname,
1789 START_PROFILE(syscall_lchown);
1790 result = lchown(smb_fname->base_name, uid, gid);
1791 END_PROFILE(syscall_lchown);
1795 static int vfswrap_chdir(vfs_handle_struct *handle, const char *path)
1799 START_PROFILE(syscall_chdir);
1800 result = chdir(path);
1801 END_PROFILE(syscall_chdir);
1805 static char *vfswrap_getwd(vfs_handle_struct *handle)
1809 START_PROFILE(syscall_getwd);
1810 result = sys_getwd();
1811 END_PROFILE(syscall_getwd);
1815 /*********************************************************************
1816 nsec timestamp resolution call. Convert down to whatever the underlying
1817 system will support.
1818 **********************************************************************/
1820 static int vfswrap_ntimes(vfs_handle_struct *handle,
1821 const struct smb_filename *smb_fname,
1822 struct smb_file_time *ft)
1826 START_PROFILE(syscall_ntimes);
1828 if (smb_fname->stream_name) {
1834 if (null_timespec(ft->atime)) {
1835 ft->atime= smb_fname->st.st_ex_atime;
1838 if (null_timespec(ft->mtime)) {
1839 ft->mtime = smb_fname->st.st_ex_mtime;
1842 if (!null_timespec(ft->create_time)) {
1843 set_create_timespec_ea(handle->conn,
1848 if ((timespec_compare(&ft->atime,
1849 &smb_fname->st.st_ex_atime) == 0) &&
1850 (timespec_compare(&ft->mtime,
1851 &smb_fname->st.st_ex_mtime) == 0)) {
1856 #if defined(HAVE_UTIMENSAT)
1858 struct timespec ts[2];
1861 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
1863 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
1865 if (!((result == -1) && (errno == ENOSYS))) {
1869 #if defined(HAVE_UTIMES)
1871 struct timeval tv[2];
1872 tv[0] = convert_timespec_to_timeval(ft->atime);
1873 tv[1] = convert_timespec_to_timeval(ft->mtime);
1874 result = utimes(smb_fname->base_name, tv);
1876 result = utimes(smb_fname->base_name, NULL);
1878 if (!((result == -1) && (errno == ENOSYS))) {
1882 #if defined(HAVE_UTIME)
1884 struct utimbuf times;
1885 times.actime = convert_timespec_to_time_t(ft->atime);
1886 times.modtime = convert_timespec_to_time_t(ft->mtime);
1887 result = utime(smb_fname->base_name, ×);
1889 result = utime(smb_fname->base_name, NULL);
1891 if (!((result == -1) && (errno == ENOSYS))) {
1899 END_PROFILE(syscall_ntimes);
1903 /*********************************************************************
1904 A version of ftruncate that will write the space on disk if strict
1906 **********************************************************************/
1908 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1910 off_t space_to_write;
1911 uint64_t space_avail;
1912 uint64_t bsize,dfree,dsize;
1915 SMB_STRUCT_STAT *pst;
1917 status = vfs_stat_fsp(fsp);
1918 if (!NT_STATUS_IS_OK(status)) {
1921 pst = &fsp->fsp_name->st;
1924 if (S_ISFIFO(pst->st_ex_mode))
1928 if (pst->st_ex_size == len)
1931 /* Shrink - just ftruncate. */
1932 if (pst->st_ex_size > len)
1933 return ftruncate(fsp->fh->fd, len);
1935 space_to_write = len - pst->st_ex_size;
1937 /* for allocation try fallocate first. This can fail on some
1938 platforms e.g. when the filesystem doesn't support it and no
1939 emulation is being done by the libc (like on AIX with JFS1). In that
1940 case we do our own emulation. fallocate implementations can
1941 return ENOTSUP or EINVAL in cases like that. */
1942 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
1943 if (ret == -1 && errno == ENOSPC) {
1949 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
1950 "error %d. Falling back to slow manual allocation\n", errno));
1952 /* available disk space is enough or not? */
1953 space_avail = get_dfree_info(fsp->conn,
1954 fsp->fsp_name->base_name,
1955 &bsize, &dfree, &dsize);
1956 /* space_avail is 1k blocks */
1957 if (space_avail == (uint64_t)-1 ||
1958 ((uint64_t)space_to_write/1024 > space_avail) ) {
1963 /* Write out the real space on disk. */
1964 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
1972 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1975 SMB_STRUCT_STAT *pst;
1979 START_PROFILE(syscall_ftruncate);
1981 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
1982 result = strict_allocate_ftruncate(handle, fsp, len);
1983 END_PROFILE(syscall_ftruncate);
1987 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
1988 ftruncate if the system supports it. Then I discovered that
1989 you can have some filesystems that support ftruncate
1990 expansion and some that don't! On Linux fat can't do
1991 ftruncate extend but ext2 can. */
1993 result = ftruncate(fsp->fh->fd, len);
1995 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
1996 extend a file with ftruncate. Provide alternate implementation
1999 /* Do an fstat to see if the file is longer than the requested
2000 size in which case the ftruncate above should have
2001 succeeded or shorter, in which case seek to len - 1 and
2002 write 1 byte of zero */
2003 status = vfs_stat_fsp(fsp);
2004 if (!NT_STATUS_IS_OK(status)) {
2008 /* We need to update the files_struct after successful ftruncate */
2013 pst = &fsp->fsp_name->st;
2016 if (S_ISFIFO(pst->st_ex_mode)) {
2022 if (pst->st_ex_size == len) {
2027 if (pst->st_ex_size > len) {
2028 /* the ftruncate should have worked */
2032 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2040 END_PROFILE(syscall_ftruncate);
2044 static int vfswrap_fallocate(vfs_handle_struct *handle,
2052 START_PROFILE(syscall_fallocate);
2054 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2056 * posix_fallocate returns 0 on success, errno on error
2057 * and doesn't set errno. Make it behave like fallocate()
2058 * which returns -1, and sets errno on failure.
2065 /* sys_fallocate handles filtering of unsupported mode flags */
2066 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2068 END_PROFILE(syscall_fallocate);
2072 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2076 START_PROFILE(syscall_fcntl_lock);
2077 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2078 END_PROFILE(syscall_fcntl_lock);
2082 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2083 uint32_t share_mode, uint32_t access_mask)
2085 START_PROFILE(syscall_kernel_flock);
2086 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2087 END_PROFILE(syscall_kernel_flock);
2091 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2095 START_PROFILE(syscall_fcntl_getlock);
2096 result = fcntl_getlock(fsp->fh->fd, poffset, pcount, ptype, ppid);
2097 END_PROFILE(syscall_fcntl_getlock);
2101 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2106 START_PROFILE(syscall_linux_setlease);
2108 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2109 result = linux_setlease(fsp->fh->fd, leasetype);
2113 END_PROFILE(syscall_linux_setlease);
2117 static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2121 START_PROFILE(syscall_symlink);
2122 result = symlink(oldpath, newpath);
2123 END_PROFILE(syscall_symlink);
2127 static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
2131 START_PROFILE(syscall_readlink);
2132 result = readlink(path, buf, bufsiz);
2133 END_PROFILE(syscall_readlink);
2137 static int vfswrap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2141 START_PROFILE(syscall_link);
2142 result = link(oldpath, newpath);
2143 END_PROFILE(syscall_link);
2147 static int vfswrap_mknod(vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev)
2151 START_PROFILE(syscall_mknod);
2152 result = sys_mknod(pathname, mode, dev);
2153 END_PROFILE(syscall_mknod);
2157 static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
2161 START_PROFILE(syscall_realpath);
2162 result = sys_realpath(path);
2163 END_PROFILE(syscall_realpath);
2167 static int vfswrap_chflags(vfs_handle_struct *handle, const char *path,
2171 return chflags(path, flags);
2178 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2179 const SMB_STRUCT_STAT *sbuf)
2183 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2187 key.devid = sbuf->st_ex_dev;
2188 key.inode = sbuf->st_ex_ino;
2189 /* key.extid is unused by default. */
2194 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2195 struct files_struct *fsp,
2196 const struct smb_filename *smb_fname,
2197 TALLOC_CTX *mem_ctx,
2198 unsigned int *pnum_streams,
2199 struct stream_struct **pstreams)
2201 SMB_STRUCT_STAT sbuf;
2202 struct stream_struct *tmp_streams = NULL;
2205 if ((fsp != NULL) && (fsp->is_directory)) {
2207 * No default streams on directories
2212 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2213 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2216 struct smb_filename smb_fname_cp;
2218 ZERO_STRUCT(smb_fname_cp);
2219 smb_fname_cp.base_name = discard_const_p(char,
2220 smb_fname->base_name);
2221 smb_fname_cp.flags = smb_fname->flags;
2223 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
2224 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2226 ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2228 sbuf = smb_fname_cp.st;
2232 return map_nt_error_from_unix(errno);
2235 if (S_ISDIR(sbuf.st_ex_mode)) {
2239 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2240 (*pnum_streams) + 1);
2241 if (tmp_streams == NULL) {
2242 return NT_STATUS_NO_MEMORY;
2244 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2245 if (tmp_streams[*pnum_streams].name == NULL) {
2246 return NT_STATUS_NO_MEMORY;
2248 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2249 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2252 *pstreams = tmp_streams;
2254 return NT_STATUS_OK;
2257 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2260 TALLOC_CTX *mem_ctx,
2264 * Don't fall back to get_real_filename so callers can differentiate
2265 * between a full directory scan and an actual case-insensitive stat.
2271 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2274 return handle->conn->connectpath;
2277 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2278 struct byte_range_lock *br_lck,
2279 struct lock_struct *plock,
2282 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2284 /* Note: blr is not used in the default implementation. */
2285 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2288 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2289 struct messaging_context *msg_ctx,
2290 struct byte_range_lock *br_lck,
2291 const struct lock_struct *plock)
2293 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2295 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2298 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2299 struct byte_range_lock *br_lck,
2300 struct lock_struct *plock)
2302 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2304 /* Note: blr is not used in the default implementation. */
2305 return brl_lock_cancel_default(br_lck, plock);
2308 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2310 struct lock_struct *plock)
2312 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2313 plock->lock_type == WRITE_LOCK);
2315 return strict_lock_default(fsp, plock);
2318 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2320 struct lock_struct *plock)
2322 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2323 plock->lock_type == WRITE_LOCK);
2325 strict_unlock_default(fsp, plock);
2328 /* NT ACL operations. */
2330 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2332 uint32_t security_info,
2333 TALLOC_CTX *mem_ctx,
2334 struct security_descriptor **ppdesc)
2338 START_PROFILE(fget_nt_acl);
2339 result = posix_fget_nt_acl(fsp, security_info,
2341 END_PROFILE(fget_nt_acl);
2345 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2346 const struct smb_filename *smb_fname,
2347 uint32_t security_info,
2348 TALLOC_CTX *mem_ctx,
2349 struct security_descriptor **ppdesc)
2353 START_PROFILE(get_nt_acl);
2354 result = posix_get_nt_acl(handle->conn,
2359 END_PROFILE(get_nt_acl);
2363 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2367 START_PROFILE(fset_nt_acl);
2368 result = set_nt_acl(fsp, security_info_sent, psd);
2369 END_PROFILE(fset_nt_acl);
2373 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2374 struct smb_filename *file,
2375 struct security_acl *sacl,
2376 uint32_t access_requested,
2377 uint32_t access_denied)
2379 return NT_STATUS_OK; /* Nothing to do here ... */
2382 static int vfswrap_chmod_acl(vfs_handle_struct *handle,
2383 const struct smb_filename *smb_fname,
2392 START_PROFILE(chmod_acl);
2393 result = chmod_acl(handle->conn, smb_fname->base_name, mode);
2394 END_PROFILE(chmod_acl);
2399 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2407 START_PROFILE(fchmod_acl);
2408 result = fchmod_acl(fsp, mode);
2409 END_PROFILE(fchmod_acl);
2414 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2416 SMB_ACL_TYPE_T type,
2417 TALLOC_CTX *mem_ctx)
2419 return sys_acl_get_file(handle, path_p, type, mem_ctx);
2422 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2424 TALLOC_CTX *mem_ctx)
2426 return sys_acl_get_fd(handle, fsp, mem_ctx);
2429 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2431 return sys_acl_set_file(handle, name, acltype, theacl);
2434 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2436 return sys_acl_set_fd(handle, fsp, theacl);
2439 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
2441 return sys_acl_delete_def_file(handle, path);
2444 /****************************************************************
2445 Extended attribute operations.
2446 *****************************************************************/
2448 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
2450 return getxattr(path, name, value, size);
2453 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2455 return fgetxattr(fsp->fh->fd, name, value, size);
2458 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
2460 return listxattr(path, list, size);
2463 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2465 return flistxattr(fsp->fh->fd, list, size);
2468 static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
2470 return removexattr(path, name);
2473 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2475 return fremovexattr(fsp->fh->fd, name);
2478 static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
2480 return setxattr(path, name, value, size, flags);
2483 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2485 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2488 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2493 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2494 const struct smb_filename *fname,
2495 SMB_STRUCT_STAT *sbuf)
2499 bool offline = false;
2501 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2505 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2506 #if defined(ENOTSUP)
2512 status = get_full_smb_filename(talloc_tos(), fname, &path);
2513 if (!NT_STATUS_IS_OK(status)) {
2514 errno = map_errno_from_nt_status(status);
2518 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2525 static int vfswrap_set_offline(struct vfs_handle_struct *handle,
2526 const struct smb_filename *fname)
2528 /* We don't know how to set offline bit by default, needs to be overriden in the vfs modules */
2529 #if defined(ENOTSUP)
2535 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2536 struct files_struct *fsp,
2537 TALLOC_CTX *mem_ctx,
2540 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2543 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2544 struct files_struct *fsp,
2545 const DATA_BLOB old_cookie,
2546 TALLOC_CTX *mem_ctx,
2547 DATA_BLOB *new_cookie)
2549 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2553 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2554 struct smb_request *smb1req,
2555 struct smbXsrv_open *op,
2556 const DATA_BLOB old_cookie,
2557 TALLOC_CTX *mem_ctx,
2558 struct files_struct **fsp,
2559 DATA_BLOB *new_cookie)
2561 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2562 old_cookie, mem_ctx,
2566 static struct vfs_fn_pointers vfs_default_fns = {
2567 /* Disk operations */
2569 .connect_fn = vfswrap_connect,
2570 .disconnect_fn = vfswrap_disconnect,
2571 .disk_free_fn = vfswrap_disk_free,
2572 .get_quota_fn = vfswrap_get_quota,
2573 .set_quota_fn = vfswrap_set_quota,
2574 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2575 .statvfs_fn = vfswrap_statvfs,
2576 .fs_capabilities_fn = vfswrap_fs_capabilities,
2577 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2578 .snap_check_path_fn = vfswrap_snap_check_path,
2579 .snap_create_fn = vfswrap_snap_create,
2580 .snap_delete_fn = vfswrap_snap_delete,
2582 /* Directory operations */
2584 .opendir_fn = vfswrap_opendir,
2585 .fdopendir_fn = vfswrap_fdopendir,
2586 .readdir_fn = vfswrap_readdir,
2587 .readdir_attr_fn = vfswrap_readdir_attr,
2588 .seekdir_fn = vfswrap_seekdir,
2589 .telldir_fn = vfswrap_telldir,
2590 .rewind_dir_fn = vfswrap_rewinddir,
2591 .mkdir_fn = vfswrap_mkdir,
2592 .rmdir_fn = vfswrap_rmdir,
2593 .closedir_fn = vfswrap_closedir,
2594 .init_search_op_fn = vfswrap_init_search_op,
2596 /* File operations */
2598 .open_fn = vfswrap_open,
2599 .create_file_fn = vfswrap_create_file,
2600 .close_fn = vfswrap_close,
2601 .read_fn = vfswrap_read,
2602 .pread_fn = vfswrap_pread,
2603 .pread_send_fn = vfswrap_pread_send,
2604 .pread_recv_fn = vfswrap_asys_ssize_t_recv,
2605 .write_fn = vfswrap_write,
2606 .pwrite_fn = vfswrap_pwrite,
2607 .pwrite_send_fn = vfswrap_pwrite_send,
2608 .pwrite_recv_fn = vfswrap_asys_ssize_t_recv,
2609 .lseek_fn = vfswrap_lseek,
2610 .sendfile_fn = vfswrap_sendfile,
2611 .recvfile_fn = vfswrap_recvfile,
2612 .rename_fn = vfswrap_rename,
2613 .fsync_fn = vfswrap_fsync,
2614 .fsync_send_fn = vfswrap_fsync_send,
2615 .fsync_recv_fn = vfswrap_asys_int_recv,
2616 .stat_fn = vfswrap_stat,
2617 .fstat_fn = vfswrap_fstat,
2618 .lstat_fn = vfswrap_lstat,
2619 .get_alloc_size_fn = vfswrap_get_alloc_size,
2620 .unlink_fn = vfswrap_unlink,
2621 .chmod_fn = vfswrap_chmod,
2622 .fchmod_fn = vfswrap_fchmod,
2623 .chown_fn = vfswrap_chown,
2624 .fchown_fn = vfswrap_fchown,
2625 .lchown_fn = vfswrap_lchown,
2626 .chdir_fn = vfswrap_chdir,
2627 .getwd_fn = vfswrap_getwd,
2628 .ntimes_fn = vfswrap_ntimes,
2629 .ftruncate_fn = vfswrap_ftruncate,
2630 .fallocate_fn = vfswrap_fallocate,
2631 .lock_fn = vfswrap_lock,
2632 .kernel_flock_fn = vfswrap_kernel_flock,
2633 .linux_setlease_fn = vfswrap_linux_setlease,
2634 .getlock_fn = vfswrap_getlock,
2635 .symlink_fn = vfswrap_symlink,
2636 .readlink_fn = vfswrap_readlink,
2637 .link_fn = vfswrap_link,
2638 .mknod_fn = vfswrap_mknod,
2639 .realpath_fn = vfswrap_realpath,
2640 .chflags_fn = vfswrap_chflags,
2641 .file_id_create_fn = vfswrap_file_id_create,
2642 .streaminfo_fn = vfswrap_streaminfo,
2643 .get_real_filename_fn = vfswrap_get_real_filename,
2644 .connectpath_fn = vfswrap_connectpath,
2645 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2646 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2647 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2648 .strict_lock_fn = vfswrap_strict_lock,
2649 .strict_unlock_fn = vfswrap_strict_unlock,
2650 .translate_name_fn = vfswrap_translate_name,
2651 .fsctl_fn = vfswrap_fsctl,
2652 .copy_chunk_send_fn = vfswrap_copy_chunk_send,
2653 .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
2654 .get_compression_fn = vfswrap_get_compression,
2655 .set_compression_fn = vfswrap_set_compression,
2657 /* NT ACL operations. */
2659 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2660 .get_nt_acl_fn = vfswrap_get_nt_acl,
2661 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2662 .audit_file_fn = vfswrap_audit_file,
2664 /* POSIX ACL operations. */
2666 .chmod_acl_fn = vfswrap_chmod_acl,
2667 .fchmod_acl_fn = vfswrap_fchmod_acl,
2669 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2670 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2671 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2672 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2673 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2674 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2675 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2677 /* EA operations. */
2678 .getxattr_fn = vfswrap_getxattr,
2679 .fgetxattr_fn = vfswrap_fgetxattr,
2680 .listxattr_fn = vfswrap_listxattr,
2681 .flistxattr_fn = vfswrap_flistxattr,
2682 .removexattr_fn = vfswrap_removexattr,
2683 .fremovexattr_fn = vfswrap_fremovexattr,
2684 .setxattr_fn = vfswrap_setxattr,
2685 .fsetxattr_fn = vfswrap_fsetxattr,
2687 /* aio operations */
2688 .aio_force_fn = vfswrap_aio_force,
2690 /* offline operations */
2691 .is_offline_fn = vfswrap_is_offline,
2692 .set_offline_fn = vfswrap_set_offline,
2694 /* durable handle operations */
2695 .durable_cookie_fn = vfswrap_durable_cookie,
2696 .durable_disconnect_fn = vfswrap_durable_disconnect,
2697 .durable_reconnect_fn = vfswrap_durable_reconnect,
2700 NTSTATUS vfs_default_init(void);
2701 NTSTATUS vfs_default_init(void)
2703 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
2704 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);