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"
37 #define DBGC_CLASS DBGC_VFS
39 /* Check for NULL pointer parameters in vfswrap_* functions */
41 /* We don't want to have NULL function pointers lying around. Someone
42 is sure to try and execute them. These stubs are used to prevent
45 static int vfswrap_connect(vfs_handle_struct *handle, const char *service, const char *user)
47 return 0; /* Return >= 0 for success */
50 static void vfswrap_disconnect(vfs_handle_struct *handle)
56 static uint64_t vfswrap_disk_free(vfs_handle_struct *handle, const char *path, bool small_query, uint64_t *bsize,
57 uint64_t *dfree, uint64_t *dsize)
61 result = sys_disk_free(handle->conn, path, small_query, bsize, dfree, dsize);
65 static int vfswrap_get_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
67 #ifdef HAVE_SYS_QUOTAS
70 START_PROFILE(syscall_get_quota);
71 result = sys_get_quota(handle->conn->connectpath, qtype, id, qt);
72 END_PROFILE(syscall_get_quota);
80 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
82 #ifdef HAVE_SYS_QUOTAS
85 START_PROFILE(syscall_set_quota);
86 result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
87 END_PROFILE(syscall_set_quota);
95 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
96 struct files_struct *fsp,
97 struct shadow_copy_data *shadow_copy_data,
101 return -1; /* Not implemented. */
104 static int vfswrap_statvfs(struct vfs_handle_struct *handle, const char *path, vfs_statvfs_struct *statbuf)
106 return sys_statvfs(path, statbuf);
109 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
110 enum timestamp_set_resolution *p_ts_res)
112 connection_struct *conn = handle->conn;
113 uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
114 struct smb_filename *smb_fname_cpath = NULL;
115 struct vfs_statvfs_struct statbuf;
118 ZERO_STRUCT(statbuf);
119 ret = sys_statvfs(conn->connectpath, &statbuf);
121 caps = statbuf.FsCapabilities;
124 *p_ts_res = TIMESTAMP_SET_SECONDS;
126 /* Work out what timestamp resolution we can
127 * use when setting a timestamp. */
129 smb_fname_cpath = synthetic_smb_fname(talloc_tos(), conn->connectpath,
131 if (smb_fname_cpath == NULL) {
135 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
137 TALLOC_FREE(smb_fname_cpath);
141 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
142 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
143 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
144 /* If any of the normal UNIX directory timestamps
145 * have a non-zero tv_nsec component assume
146 * we might be able to set sub-second timestamps.
147 * See what filetime set primitives we have.
149 #if defined(HAVE_UTIMENSAT)
150 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
151 #elif defined(HAVE_UTIMES)
152 /* utimes allows msec timestamps to be set. */
153 *p_ts_res = TIMESTAMP_SET_MSEC;
154 #elif defined(HAVE_UTIME)
155 /* utime only allows sec timestamps to be set. */
156 *p_ts_res = TIMESTAMP_SET_SECONDS;
159 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
161 "available on share %s, directory %s\n",
162 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
163 lp_servicename(talloc_tos(), conn->params->service),
164 conn->connectpath ));
166 TALLOC_FREE(smb_fname_cpath);
170 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
171 struct dfs_GetDFSReferral *r)
173 struct junction_map *junction = NULL;
175 bool self_referral = false;
176 char *pathnamep = NULL;
177 char *local_dfs_path = NULL;
180 uint16_t max_referral_level = r->in.req.max_referral_level;
183 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
186 /* get the junction entry */
187 if (r->in.req.servername == NULL) {
188 return NT_STATUS_NOT_FOUND;
192 * Trim pathname sent by client so it begins with only one backslash.
193 * Two backslashes confuse some dfs clients
196 local_dfs_path = talloc_strdup(r, r->in.req.servername);
197 if (local_dfs_path == NULL) {
198 return NT_STATUS_NO_MEMORY;
200 pathnamep = local_dfs_path;
201 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
202 IS_DIRECTORY_SEP(pathnamep[1])) {
206 junction = talloc_zero(r, struct junction_map);
207 if (junction == NULL) {
208 return NT_STATUS_NO_MEMORY;
211 /* The following call can change cwd. */
212 status = get_referred_path(r, pathnamep,
213 !handle->conn->sconn->using_smb2,
214 junction, &consumedcnt, &self_referral);
215 if (!NT_STATUS_IS_OK(status)) {
216 vfs_ChDir(handle->conn, handle->conn->connectpath);
219 vfs_ChDir(handle->conn, handle->conn->connectpath);
221 if (!self_referral) {
222 pathnamep[consumedcnt] = '\0';
225 dbgtext("setup_dfs_referral: Path %s to "
226 "alternate path(s):",
228 for (i=0; i < junction->referral_count; i++) {
230 junction->referral_list[i].alternate_path);
236 if (r->in.req.max_referral_level <= 2) {
237 max_referral_level = 2;
239 if (r->in.req.max_referral_level >= 3) {
240 max_referral_level = 3;
243 r->out.resp = talloc_zero(r, struct dfs_referral_resp);
244 if (r->out.resp == NULL) {
245 return NT_STATUS_NO_MEMORY;
248 r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
249 r->out.resp->nb_referrals = junction->referral_count;
251 r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
253 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
256 r->out.resp->referral_entries = talloc_zero_array(r,
257 struct dfs_referral_type,
258 r->out.resp->nb_referrals);
259 if (r->out.resp->referral_entries == NULL) {
260 return NT_STATUS_NO_MEMORY;
263 switch (max_referral_level) {
265 for(i=0; i < junction->referral_count; i++) {
266 struct referral *ref = &junction->referral_list[i];
267 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
268 struct dfs_referral_type *t =
269 &r->out.resp->referral_entries[i];
270 struct dfs_referral_v2 *v2 = &t->referral.v2;
273 v2->size = VERSION2_REFERRAL_SIZE;
275 v2->server_type = DFS_SERVER_ROOT;
277 v2->server_type = DFS_SERVER_NON_ROOT;
280 v2->proximity = ref->proximity;
282 v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
283 if (v2->DFS_path == NULL) {
284 return NT_STATUS_NO_MEMORY;
286 v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
287 if (v2->DFS_alt_path == NULL) {
288 return NT_STATUS_NO_MEMORY;
290 v2->netw_address = talloc_strdup(mem_ctx,
291 ref->alternate_path);
292 if (v2->netw_address == NULL) {
293 return NT_STATUS_NO_MEMORY;
299 for(i=0; i < junction->referral_count; i++) {
300 struct referral *ref = &junction->referral_list[i];
301 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
302 struct dfs_referral_type *t =
303 &r->out.resp->referral_entries[i];
304 struct dfs_referral_v3 *v3 = &t->referral.v3;
305 struct dfs_normal_referral *r1 = &v3->referrals.r1;
308 v3->size = VERSION3_REFERRAL_SIZE;
310 v3->server_type = DFS_SERVER_ROOT;
312 v3->server_type = DFS_SERVER_NON_ROOT;
316 r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
317 if (r1->DFS_path == NULL) {
318 return NT_STATUS_NO_MEMORY;
320 r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
321 if (r1->DFS_alt_path == NULL) {
322 return NT_STATUS_NO_MEMORY;
324 r1->netw_address = talloc_strdup(mem_ctx,
325 ref->alternate_path);
326 if (r1->netw_address == NULL) {
327 return NT_STATUS_NO_MEMORY;
332 DEBUG(0,("setup_dfs_referral: Invalid dfs referral "
334 max_referral_level));
335 return NT_STATUS_INVALID_LEVEL;
339 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
345 /* Directory operations */
347 static DIR *vfswrap_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr)
351 START_PROFILE(syscall_opendir);
352 result = opendir(fname);
353 END_PROFILE(syscall_opendir);
357 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
364 START_PROFILE(syscall_fdopendir);
365 result = sys_fdopendir(fsp->fh->fd);
366 END_PROFILE(syscall_fdopendir);
371 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
373 SMB_STRUCT_STAT *sbuf)
375 struct dirent *result;
377 START_PROFILE(syscall_readdir);
378 result = readdir(dirp);
379 END_PROFILE(syscall_readdir);
381 /* Default Posix readdir() does not give us stat info.
382 * Set to invalid to indicate we didn't return this info. */
383 SET_STAT_INVALID(*sbuf);
384 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
385 if (result != NULL) {
386 /* See if we can efficiently return this. */
388 int flags = (lp_posix_pathnames() ?
389 AT_SYMLINK_NOFOLLOW : 0);
390 int ret = fstatat(dirfd(dirp),
395 init_stat_ex_from_stat(sbuf,
397 lp_fake_directory_create_times(
398 SNUM(handle->conn)));
406 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
408 START_PROFILE(syscall_seekdir);
409 seekdir(dirp, offset);
410 END_PROFILE(syscall_seekdir);
413 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
416 START_PROFILE(syscall_telldir);
417 result = telldir(dirp);
418 END_PROFILE(syscall_telldir);
422 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
424 START_PROFILE(syscall_rewinddir);
426 END_PROFILE(syscall_rewinddir);
429 static int vfswrap_mkdir(vfs_handle_struct *handle, const char *path, mode_t mode)
432 bool has_dacl = False;
435 START_PROFILE(syscall_mkdir);
437 if (lp_inherit_acls(SNUM(handle->conn))
438 && parent_dirname(talloc_tos(), path, &parent, NULL)
439 && (has_dacl = directory_has_default_acl(handle->conn, parent)))
440 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
444 result = mkdir(path, mode);
446 if (result == 0 && !has_dacl) {
448 * We need to do this as the default behavior of POSIX ACLs
449 * is to set the mask to be the requested group permission
450 * bits, not the group permission bits to be the requested
451 * group permission bits. This is not what we want, as it will
452 * mess up any inherited ACL bits that were set. JRA.
454 int saved_errno = errno; /* We may get ENOSYS */
455 if ((SMB_VFS_CHMOD_ACL(handle->conn, path, mode) == -1) && (errno == ENOSYS))
459 END_PROFILE(syscall_mkdir);
463 static int vfswrap_rmdir(vfs_handle_struct *handle, const char *path)
467 START_PROFILE(syscall_rmdir);
468 result = rmdir(path);
469 END_PROFILE(syscall_rmdir);
473 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
477 START_PROFILE(syscall_closedir);
478 result = closedir(dirp);
479 END_PROFILE(syscall_closedir);
483 static void vfswrap_init_search_op(vfs_handle_struct *handle,
486 /* Default behavior is a NOOP */
489 /* File operations */
491 static int vfswrap_open(vfs_handle_struct *handle,
492 struct smb_filename *smb_fname,
493 files_struct *fsp, int flags, mode_t mode)
497 START_PROFILE(syscall_open);
499 if (smb_fname->stream_name) {
504 result = open(smb_fname->base_name, flags, mode);
506 END_PROFILE(syscall_open);
510 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
511 struct smb_request *req,
512 uint16_t root_dir_fid,
513 struct smb_filename *smb_fname,
514 uint32_t access_mask,
515 uint32_t share_access,
516 uint32_t create_disposition,
517 uint32_t create_options,
518 uint32_t file_attributes,
519 uint32_t oplock_request,
520 uint64_t allocation_size,
521 uint32_t private_flags,
522 struct security_descriptor *sd,
523 struct ea_list *ea_list,
524 files_struct **result,
527 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
528 access_mask, share_access,
529 create_disposition, create_options,
530 file_attributes, oplock_request,
531 allocation_size, private_flags,
536 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
540 START_PROFILE(syscall_close);
541 result = fd_close_posix(fsp);
542 END_PROFILE(syscall_close);
546 static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
550 START_PROFILE_BYTES(syscall_read, n);
551 result = sys_read(fsp->fh->fd, data, n);
552 END_PROFILE(syscall_read);
556 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
557 size_t n, off_t offset)
561 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
562 START_PROFILE_BYTES(syscall_pread, n);
563 result = sys_pread(fsp->fh->fd, data, n, offset);
564 END_PROFILE(syscall_pread);
566 if (result == -1 && errno == ESPIPE) {
567 /* Maintain the fiction that pipes can be seeked (sought?) on. */
568 result = SMB_VFS_READ(fsp, data, n);
572 #else /* HAVE_PREAD */
576 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
577 if (curr == -1 && errno == ESPIPE) {
578 /* Maintain the fiction that pipes can be seeked (sought?) on. */
579 result = SMB_VFS_READ(fsp, data, n);
584 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
589 result = SMB_VFS_READ(fsp, data, n);
592 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
595 #endif /* HAVE_PREAD */
600 static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
604 START_PROFILE_BYTES(syscall_write, n);
605 result = sys_write(fsp->fh->fd, data, n);
606 END_PROFILE(syscall_write);
610 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
611 size_t n, off_t offset)
615 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
616 START_PROFILE_BYTES(syscall_pwrite, n);
617 result = sys_pwrite(fsp->fh->fd, data, n, offset);
618 END_PROFILE(syscall_pwrite);
620 if (result == -1 && errno == ESPIPE) {
621 /* Maintain the fiction that pipes can be sought on. */
622 result = SMB_VFS_WRITE(fsp, data, n);
625 #else /* HAVE_PWRITE */
629 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
634 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
638 result = SMB_VFS_WRITE(fsp, data, n);
641 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
644 #endif /* HAVE_PWRITE */
649 static void vfswrap_asys_finished(struct tevent_context *ev,
650 struct tevent_fd *fde,
651 uint16_t flags, void *p);
653 static bool vfswrap_init_asys_ctx(struct smbXsrv_connection *conn)
658 if (conn->asys_ctx != NULL) {
661 ret = asys_context_init(&conn->asys_ctx, aio_pending_size);
663 DEBUG(1, ("asys_context_init failed: %s\n", strerror(ret)));
667 fd = asys_signalfd(conn->asys_ctx);
669 set_blocking(fd, false);
671 conn->asys_fde = tevent_add_fd(conn->ev_ctx, conn, fd,
673 vfswrap_asys_finished,
675 if (conn->asys_fde == NULL) {
676 DEBUG(1, ("tevent_add_fd failed\n"));
677 asys_context_destroy(conn->asys_ctx);
678 conn->asys_ctx = NULL;
684 struct vfswrap_asys_state {
685 struct asys_context *asys_ctx;
686 struct tevent_req *req;
691 static int vfswrap_asys_state_destructor(struct vfswrap_asys_state *s)
693 asys_cancel(s->asys_ctx, s->req);
697 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
699 struct tevent_context *ev,
700 struct files_struct *fsp,
702 size_t n, off_t offset)
704 struct tevent_req *req;
705 struct vfswrap_asys_state *state;
708 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
712 if (!vfswrap_init_asys_ctx(handle->conn->sconn->conn)) {
714 return tevent_req_post(req, ev);
716 state->asys_ctx = handle->conn->sconn->conn->asys_ctx;
719 ret = asys_pread(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
721 tevent_req_error(req, ret);
722 return tevent_req_post(req, ev);
724 talloc_set_destructor(state, vfswrap_asys_state_destructor);
729 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
731 struct tevent_context *ev,
732 struct files_struct *fsp,
734 size_t n, off_t offset)
736 struct tevent_req *req;
737 struct vfswrap_asys_state *state;
740 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
744 if (!vfswrap_init_asys_ctx(handle->conn->sconn->conn)) {
746 return tevent_req_post(req, ev);
748 state->asys_ctx = handle->conn->sconn->conn->asys_ctx;
751 ret = asys_pwrite(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
753 tevent_req_error(req, ret);
754 return tevent_req_post(req, ev);
756 talloc_set_destructor(state, vfswrap_asys_state_destructor);
761 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
763 struct tevent_context *ev,
764 struct files_struct *fsp)
766 struct tevent_req *req;
767 struct vfswrap_asys_state *state;
770 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
774 if (!vfswrap_init_asys_ctx(handle->conn->sconn->conn)) {
776 return tevent_req_post(req, ev);
778 state->asys_ctx = handle->conn->sconn->conn->asys_ctx;
781 ret = asys_fsync(state->asys_ctx, fsp->fh->fd, req);
783 tevent_req_error(req, ret);
784 return tevent_req_post(req, ev);
786 talloc_set_destructor(state, vfswrap_asys_state_destructor);
791 static void vfswrap_asys_finished(struct tevent_context *ev,
792 struct tevent_fd *fde,
793 uint16_t flags, void *p)
795 struct asys_context *asys_ctx = (struct asys_context *)p;
797 if ((flags & TEVENT_FD_READ) == 0) {
802 struct tevent_req *req;
803 struct vfswrap_asys_state *state;
804 struct asys_result result;
807 res = asys_results(asys_ctx, &result, 1);
809 DEBUG(1, ("asys_result returned %s\n",
817 if ((result.ret == -1) && (result.err == ECANCELED)) {
821 req = talloc_get_type_abort(result.private_data,
823 state = tevent_req_data(req, struct vfswrap_asys_state);
825 talloc_set_destructor(state, NULL);
827 state->ret = result.ret;
828 state->err = result.err;
829 tevent_req_defer_callback(req, ev);
830 tevent_req_done(req);
834 static ssize_t vfswrap_asys_ssize_t_recv(struct tevent_req *req, int *err)
836 struct vfswrap_asys_state *state = tevent_req_data(
837 req, struct vfswrap_asys_state);
839 if (tevent_req_is_unix_error(req, err)) {
846 static int vfswrap_asys_int_recv(struct tevent_req *req, int *err)
848 struct vfswrap_asys_state *state = tevent_req_data(
849 req, struct vfswrap_asys_state);
851 if (tevent_req_is_unix_error(req, err)) {
858 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
862 START_PROFILE(syscall_lseek);
864 /* Cope with 'stat' file opens. */
865 if (fsp->fh->fd != -1)
866 result = lseek(fsp->fh->fd, offset, whence);
869 * We want to maintain the fiction that we can seek
870 * on a fifo for file system purposes. This allows
871 * people to set up UNIX fifo's that feed data to Windows
875 if((result == -1) && (errno == ESPIPE)) {
880 END_PROFILE(syscall_lseek);
884 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
885 off_t offset, size_t n)
889 START_PROFILE_BYTES(syscall_sendfile, n);
890 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
891 END_PROFILE(syscall_sendfile);
895 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
903 START_PROFILE_BYTES(syscall_recvfile, n);
904 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
905 END_PROFILE(syscall_recvfile);
909 static int vfswrap_rename(vfs_handle_struct *handle,
910 const struct smb_filename *smb_fname_src,
911 const struct smb_filename *smb_fname_dst)
915 START_PROFILE(syscall_rename);
917 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
922 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
925 END_PROFILE(syscall_rename);
929 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
934 START_PROFILE(syscall_fsync);
935 result = fsync(fsp->fh->fd);
936 END_PROFILE(syscall_fsync);
943 static int vfswrap_stat(vfs_handle_struct *handle,
944 struct smb_filename *smb_fname)
948 START_PROFILE(syscall_stat);
950 if (smb_fname->stream_name) {
955 result = sys_stat(smb_fname->base_name, &smb_fname->st,
956 lp_fake_directory_create_times(SNUM(handle->conn)));
958 END_PROFILE(syscall_stat);
962 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
966 START_PROFILE(syscall_fstat);
967 result = sys_fstat(fsp->fh->fd,
968 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
969 END_PROFILE(syscall_fstat);
973 static int vfswrap_lstat(vfs_handle_struct *handle,
974 struct smb_filename *smb_fname)
978 START_PROFILE(syscall_lstat);
980 if (smb_fname->stream_name) {
985 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
986 lp_fake_directory_create_times(SNUM(handle->conn)));
988 END_PROFILE(syscall_lstat);
992 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
994 enum vfs_translate_direction direction,
998 return NT_STATUS_NONE_MAPPED;
1002 * Implement the default fsctl operation.
1004 static bool vfswrap_logged_ioctl_message = false;
1006 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1007 struct files_struct *fsp,
1010 uint16_t req_flags, /* Needed for UNICODE ... */
1011 const uint8_t *_in_data,
1013 uint8_t **_out_data,
1014 uint32_t max_out_len,
1017 const char *in_data = (const char *)_in_data;
1018 char **out_data = (char **)_out_data;
1022 case FSCTL_SET_SPARSE:
1024 bool set_sparse = true;
1026 if (in_len >= 1 && in_data[0] == 0) {
1030 status = file_set_sparse(handle->conn, fsp, set_sparse);
1032 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1033 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1034 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1035 nt_errstr(status)));
1040 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1042 unsigned char objid[16];
1043 char *return_data = NULL;
1045 /* This should return the object-id on this file.
1046 * I think I'll make this be the inode+dev. JRA.
1049 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1050 fsp_fnum_dbg(fsp)));
1052 *out_len = MIN(max_out_len, 64);
1054 /* Hmmm, will this cause problems if less data asked for? */
1055 return_data = talloc_array(ctx, char, 64);
1056 if (return_data == NULL) {
1057 return NT_STATUS_NO_MEMORY;
1060 /* For backwards compatibility only store the dev/inode. */
1061 push_file_id_16(return_data, &fsp->file_id);
1062 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1063 push_file_id_16(return_data+32, &fsp->file_id);
1064 memset(return_data+48, 0, 16);
1065 *out_data = return_data;
1066 return NT_STATUS_OK;
1069 case FSCTL_GET_REPARSE_POINT:
1071 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1072 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1073 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1074 return NT_STATUS_NOT_A_REPARSE_POINT;
1077 case FSCTL_SET_REPARSE_POINT:
1079 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1080 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1081 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1082 return NT_STATUS_NOT_A_REPARSE_POINT;
1085 case FSCTL_GET_SHADOW_COPY_DATA:
1088 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1089 * and return their volume names. If max_data_count is 16, then it is just
1090 * asking for the number of volumes and length of the combined names.
1092 * pdata is the data allocated by our caller, but that uses
1093 * total_data_count (which is 0 in our case) rather than max_data_count.
1094 * Allocate the correct amount and return the pointer to let
1095 * it be deallocated when we return.
1097 struct shadow_copy_data *shadow_data = NULL;
1098 bool labels = False;
1099 uint32 labels_data_count = 0;
1101 char *cur_pdata = NULL;
1103 if (max_out_len < 16) {
1104 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1106 return NT_STATUS_INVALID_PARAMETER;
1109 if (max_out_len > 16) {
1113 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1114 if (shadow_data == NULL) {
1115 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1116 return NT_STATUS_NO_MEMORY;
1120 * Call the VFS routine to actually do the work.
1122 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1125 /* broken module didn't set errno on error */
1126 status = NT_STATUS_UNSUCCESSFUL;
1128 status = map_nt_error_from_unix(errno);
1129 if (NT_STATUS_EQUAL(status,
1130 NT_STATUS_NOT_SUPPORTED)) {
1134 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1135 "connectpath %s, failed - %s.\n",
1136 fsp->conn->connectpath,
1137 nt_errstr(status)));
1138 TALLOC_FREE(shadow_data);
1142 labels_data_count = (shadow_data->num_volumes * 2 *
1143 sizeof(SHADOW_COPY_LABEL)) + 2;
1148 *out_len = 12 + labels_data_count;
1151 if (max_out_len < *out_len) {
1152 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1153 max_out_len, *out_len));
1154 TALLOC_FREE(shadow_data);
1155 return NT_STATUS_BUFFER_TOO_SMALL;
1158 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1159 if (cur_pdata == NULL) {
1160 TALLOC_FREE(shadow_data);
1161 return NT_STATUS_NO_MEMORY;
1164 *out_data = cur_pdata;
1166 /* num_volumes 4 bytes */
1167 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1170 /* num_labels 4 bytes */
1171 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1174 /* needed_data_count 4 bytes */
1175 SIVAL(cur_pdata, 8, labels_data_count);
1179 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1180 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1181 if (labels && shadow_data->labels) {
1182 for (i=0; i<shadow_data->num_volumes; i++) {
1183 srvstr_push(cur_pdata, req_flags,
1184 cur_pdata, shadow_data->labels[i],
1185 2 * sizeof(SHADOW_COPY_LABEL),
1186 STR_UNICODE|STR_TERMINATE);
1187 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1188 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1192 TALLOC_FREE(shadow_data);
1194 return NT_STATUS_OK;
1197 case FSCTL_FIND_FILES_BY_SID:
1199 /* pretend this succeeded -
1201 * we have to send back a list with all files owned by this SID
1203 * but I have to check that --metze
1209 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1210 fsp_fnum_dbg(fsp)));
1213 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1214 return NT_STATUS_INVALID_PARAMETER;
1217 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1219 /* unknown 4 bytes: this is not the length of the sid :-( */
1220 /*unknown = IVAL(pdata,0);*/
1222 if (!sid_parse(in_data + 4, sid_len, &sid)) {
1223 return NT_STATUS_INVALID_PARAMETER;
1225 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1227 if (!sid_to_uid(&sid, &uid)) {
1228 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1229 sid_string_dbg(&sid),
1230 (unsigned long)sid_len));
1234 /* we can take a look at the find source :-)
1236 * find ./ -uid $uid -name '*' is what we need here
1239 * and send 4bytes len and then NULL terminated unicode strings
1242 * but I don't know how to deal with the paged results
1243 * (maybe we can hang the result anywhere in the fsp struct)
1245 * but I don't know how to deal with the paged results
1246 * (maybe we can hang the result anywhere in the fsp struct)
1248 * we don't send all files at once
1249 * and at the next we should *not* start from the beginning,
1250 * so we have to cache the result
1255 /* this works for now... */
1256 return NT_STATUS_OK;
1259 case FSCTL_QUERY_ALLOCATED_RANGES:
1261 /* FIXME: This is just a dummy reply, telling that all of the
1262 * file is allocated. MKS cp needs that.
1263 * Adding the real allocated ranges via FIEMAP on Linux
1264 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1265 * this FSCTL correct for sparse files.
1267 uint64_t offset, length;
1268 char *out_data_tmp = NULL;
1271 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1273 return NT_STATUS_INVALID_PARAMETER;
1276 if (max_out_len < 16) {
1277 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1279 return NT_STATUS_INVALID_PARAMETER;
1282 offset = BVAL(in_data,0);
1283 length = BVAL(in_data,8);
1285 if (offset + length < offset) {
1286 /* No 64-bit integer wrap. */
1287 return NT_STATUS_INVALID_PARAMETER;
1290 /* Shouldn't this be SMB_VFS_STAT ... ? */
1291 status = vfs_stat_fsp(fsp);
1292 if (!NT_STATUS_IS_OK(status)) {
1297 out_data_tmp = talloc_array(ctx, char, *out_len);
1298 if (out_data_tmp == NULL) {
1299 DEBUG(10, ("unable to allocate memory for response\n"));
1300 return NT_STATUS_NO_MEMORY;
1303 if (offset > fsp->fsp_name->st.st_ex_size ||
1304 fsp->fsp_name->st.st_ex_size == 0 ||
1306 memset(out_data_tmp, 0, *out_len);
1308 uint64_t end = offset + length;
1309 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1310 SBVAL(out_data_tmp, 0, 0);
1311 SBVAL(out_data_tmp, 8, end);
1314 *out_data = out_data_tmp;
1316 return NT_STATUS_OK;
1319 case FSCTL_IS_VOLUME_DIRTY:
1321 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1322 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1324 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1325 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1327 return NT_STATUS_INVALID_PARAMETER;
1332 * Only print once ... unfortunately there could be lots of
1333 * different FSCTLs that are called.
1335 if (!vfswrap_logged_ioctl_message) {
1336 vfswrap_logged_ioctl_message = true;
1337 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1338 __func__, function));
1342 return NT_STATUS_NOT_SUPPORTED;
1345 struct vfs_cc_state {
1350 static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *handle,
1351 TALLOC_CTX *mem_ctx,
1352 struct tevent_context *ev,
1353 struct files_struct *src_fsp,
1355 struct files_struct *dest_fsp,
1359 struct tevent_req *req;
1360 struct vfs_cc_state *vfs_cc_state;
1363 DEBUG(10, ("performing server side copy chunk of length %lu\n",
1364 (unsigned long)num));
1366 req = tevent_req_create(mem_ctx, &vfs_cc_state, struct vfs_cc_state);
1371 status = vfs_stat_fsp(src_fsp);
1372 if (tevent_req_nterror(req, status)) {
1373 return tevent_req_post(req, ev);
1376 if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
1378 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1379 * If the SourceOffset or SourceOffset + Length extends beyond
1380 * the end of file, the server SHOULD<240> treat this as a
1381 * STATUS_END_OF_FILE error.
1383 * <240> Section 3.3.5.15.6: Windows servers will return
1384 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1386 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1387 return tevent_req_post(req, ev);
1390 /* could use 2.6.33+ sendfile here to do this in kernel */
1391 while (vfs_cc_state->copied < num) {
1393 struct lock_struct lck;
1396 off_t this_num = MIN(sizeof(vfs_cc_state->buf),
1397 num - vfs_cc_state->copied);
1399 init_strict_lock_struct(src_fsp,
1400 src_fsp->op->global->open_persistent_id,
1406 if (!SMB_VFS_STRICT_LOCK(src_fsp->conn, src_fsp, &lck)) {
1407 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1408 return tevent_req_post(req, ev);
1411 ret = SMB_VFS_PREAD(src_fsp, vfs_cc_state->buf,
1414 saved_errno = errno;
1417 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1420 errno = saved_errno;
1421 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1422 return tevent_req_post(req, ev);
1424 if (ret != this_num) {
1425 /* zero tolerance for short reads */
1426 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1427 return tevent_req_post(req, ev);
1432 init_strict_lock_struct(dest_fsp,
1433 dest_fsp->op->global->open_persistent_id,
1439 if (!SMB_VFS_STRICT_LOCK(dest_fsp->conn, dest_fsp, &lck)) {
1440 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1441 return tevent_req_post(req, ev);
1444 ret = SMB_VFS_PWRITE(dest_fsp, vfs_cc_state->buf,
1445 this_num, dest_off);
1447 saved_errno = errno;
1450 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1453 errno = saved_errno;
1454 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1455 return tevent_req_post(req, ev);
1457 if (ret != this_num) {
1458 /* zero tolerance for short writes */
1459 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1460 return tevent_req_post(req, ev);
1464 vfs_cc_state->copied += this_num;
1467 tevent_req_done(req);
1468 return tevent_req_post(req, ev);
1471 static NTSTATUS vfswrap_copy_chunk_recv(struct vfs_handle_struct *handle,
1472 struct tevent_req *req,
1475 struct vfs_cc_state *vfs_cc_state = tevent_req_data(req,
1476 struct vfs_cc_state);
1479 if (tevent_req_is_nterror(req, &status)) {
1480 DEBUG(2, ("server side copy chunk failed: %s\n",
1481 nt_errstr(status)));
1483 tevent_req_received(req);
1487 *copied = vfs_cc_state->copied;
1488 DEBUG(10, ("server side copy chunk copied %lu\n",
1489 (unsigned long)*copied));
1490 tevent_req_received(req);
1492 return NT_STATUS_OK;
1495 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1496 TALLOC_CTX *mem_ctx,
1497 struct files_struct *fsp,
1498 struct smb_filename *smb_fname,
1499 uint16_t *_compression_fmt)
1501 return NT_STATUS_INVALID_DEVICE_REQUEST;
1504 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1505 TALLOC_CTX *mem_ctx,
1506 struct files_struct *fsp,
1507 uint16_t compression_fmt)
1509 return NT_STATUS_INVALID_DEVICE_REQUEST;
1512 /********************************************************************
1513 Given a stat buffer return the allocated size on disk, taking into
1514 account sparse files.
1515 ********************************************************************/
1516 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1517 struct files_struct *fsp,
1518 const SMB_STRUCT_STAT *sbuf)
1522 START_PROFILE(syscall_get_alloc_size);
1524 if(S_ISDIR(sbuf->st_ex_mode)) {
1529 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1530 /* The type of st_blocksize is blkcnt_t which *MUST* be
1531 signed (according to POSIX) and can be less than 64-bits.
1532 Ensure when we're converting to 64 bits wide we don't
1534 #if defined(SIZEOF_BLKCNT_T_8)
1535 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1536 #elif defined(SIZEOF_BLKCNT_T_4)
1538 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1539 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1542 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1545 result = get_file_size_stat(sbuf);
1548 if (fsp && fsp->initial_allocation_size)
1549 result = MAX(result,fsp->initial_allocation_size);
1551 result = smb_roundup(handle->conn, result);
1554 END_PROFILE(syscall_get_alloc_size);
1558 static int vfswrap_unlink(vfs_handle_struct *handle,
1559 const struct smb_filename *smb_fname)
1563 START_PROFILE(syscall_unlink);
1565 if (smb_fname->stream_name) {
1569 result = unlink(smb_fname->base_name);
1572 END_PROFILE(syscall_unlink);
1576 static int vfswrap_chmod(vfs_handle_struct *handle, const char *path, mode_t mode)
1580 START_PROFILE(syscall_chmod);
1583 * We need to do this due to the fact that the default POSIX ACL
1584 * chmod modifies the ACL *mask* for the group owner, not the
1585 * group owner bits directly. JRA.
1590 int saved_errno = errno; /* We might get ENOSYS */
1591 if ((result = SMB_VFS_CHMOD_ACL(handle->conn, path, mode)) == 0) {
1592 END_PROFILE(syscall_chmod);
1595 /* Error - return the old errno. */
1596 errno = saved_errno;
1599 result = chmod(path, mode);
1600 END_PROFILE(syscall_chmod);
1604 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
1608 START_PROFILE(syscall_fchmod);
1611 * We need to do this due to the fact that the default POSIX ACL
1612 * chmod modifies the ACL *mask* for the group owner, not the
1613 * group owner bits directly. JRA.
1617 int saved_errno = errno; /* We might get ENOSYS */
1618 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
1619 END_PROFILE(syscall_fchmod);
1622 /* Error - return the old errno. */
1623 errno = saved_errno;
1626 #if defined(HAVE_FCHMOD)
1627 result = fchmod(fsp->fh->fd, mode);
1633 END_PROFILE(syscall_fchmod);
1637 static int vfswrap_chown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1641 START_PROFILE(syscall_chown);
1642 result = chown(path, uid, gid);
1643 END_PROFILE(syscall_chown);
1647 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
1652 START_PROFILE(syscall_fchown);
1653 result = fchown(fsp->fh->fd, uid, gid);
1654 END_PROFILE(syscall_fchown);
1662 static int vfswrap_lchown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1666 START_PROFILE(syscall_lchown);
1667 result = lchown(path, uid, gid);
1668 END_PROFILE(syscall_lchown);
1672 static int vfswrap_chdir(vfs_handle_struct *handle, const char *path)
1676 START_PROFILE(syscall_chdir);
1677 result = chdir(path);
1678 END_PROFILE(syscall_chdir);
1682 static char *vfswrap_getwd(vfs_handle_struct *handle)
1686 START_PROFILE(syscall_getwd);
1687 result = sys_getwd();
1688 END_PROFILE(syscall_getwd);
1692 /*********************************************************************
1693 nsec timestamp resolution call. Convert down to whatever the underlying
1694 system will support.
1695 **********************************************************************/
1697 static int vfswrap_ntimes(vfs_handle_struct *handle,
1698 const struct smb_filename *smb_fname,
1699 struct smb_file_time *ft)
1703 START_PROFILE(syscall_ntimes);
1705 if (smb_fname->stream_name) {
1711 if (null_timespec(ft->atime)) {
1712 ft->atime= smb_fname->st.st_ex_atime;
1715 if (null_timespec(ft->mtime)) {
1716 ft->mtime = smb_fname->st.st_ex_mtime;
1719 if (!null_timespec(ft->create_time)) {
1720 set_create_timespec_ea(handle->conn,
1725 if ((timespec_compare(&ft->atime,
1726 &smb_fname->st.st_ex_atime) == 0) &&
1727 (timespec_compare(&ft->mtime,
1728 &smb_fname->st.st_ex_mtime) == 0)) {
1733 #if defined(HAVE_UTIMENSAT)
1735 struct timespec ts[2];
1738 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
1740 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
1742 if (!((result == -1) && (errno == ENOSYS))) {
1746 #if defined(HAVE_UTIMES)
1748 struct timeval tv[2];
1749 tv[0] = convert_timespec_to_timeval(ft->atime);
1750 tv[1] = convert_timespec_to_timeval(ft->mtime);
1751 result = utimes(smb_fname->base_name, tv);
1753 result = utimes(smb_fname->base_name, NULL);
1755 if (!((result == -1) && (errno == ENOSYS))) {
1759 #if defined(HAVE_UTIME)
1761 struct utimbuf times;
1762 times.actime = convert_timespec_to_time_t(ft->atime);
1763 times.modtime = convert_timespec_to_time_t(ft->mtime);
1764 result = utime(smb_fname->base_name, ×);
1766 result = utime(smb_fname->base_name, NULL);
1768 if (!((result == -1) && (errno == ENOSYS))) {
1776 END_PROFILE(syscall_ntimes);
1780 /*********************************************************************
1781 A version of ftruncate that will write the space on disk if strict
1783 **********************************************************************/
1785 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1787 off_t space_to_write;
1788 uint64_t space_avail;
1789 uint64_t bsize,dfree,dsize;
1792 SMB_STRUCT_STAT *pst;
1794 status = vfs_stat_fsp(fsp);
1795 if (!NT_STATUS_IS_OK(status)) {
1798 pst = &fsp->fsp_name->st;
1801 if (S_ISFIFO(pst->st_ex_mode))
1805 if (pst->st_ex_size == len)
1808 /* Shrink - just ftruncate. */
1809 if (pst->st_ex_size > len)
1810 return ftruncate(fsp->fh->fd, len);
1812 space_to_write = len - pst->st_ex_size;
1814 /* for allocation try fallocate first. This can fail on some
1815 platforms e.g. when the filesystem doesn't support it and no
1816 emulation is being done by the libc (like on AIX with JFS1). In that
1817 case we do our own emulation. fallocate implementations can
1818 return ENOTSUP or EINVAL in cases like that. */
1819 ret = SMB_VFS_FALLOCATE(fsp, VFS_FALLOCATE_EXTEND_SIZE,
1820 pst->st_ex_size, space_to_write);
1821 if (ret == ENOSPC) {
1828 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
1829 "error %d. Falling back to slow manual allocation\n", ret));
1831 /* available disk space is enough or not? */
1832 space_avail = get_dfree_info(fsp->conn,
1833 fsp->fsp_name->base_name, false,
1834 &bsize,&dfree,&dsize);
1835 /* space_avail is 1k blocks */
1836 if (space_avail == (uint64_t)-1 ||
1837 ((uint64_t)space_to_write/1024 > space_avail) ) {
1842 /* Write out the real space on disk. */
1843 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
1852 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1855 SMB_STRUCT_STAT *pst;
1859 START_PROFILE(syscall_ftruncate);
1861 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
1862 result = strict_allocate_ftruncate(handle, fsp, len);
1863 END_PROFILE(syscall_ftruncate);
1867 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
1868 ftruncate if the system supports it. Then I discovered that
1869 you can have some filesystems that support ftruncate
1870 expansion and some that don't! On Linux fat can't do
1871 ftruncate extend but ext2 can. */
1873 result = ftruncate(fsp->fh->fd, len);
1877 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
1878 extend a file with ftruncate. Provide alternate implementation
1881 /* Do an fstat to see if the file is longer than the requested
1882 size in which case the ftruncate above should have
1883 succeeded or shorter, in which case seek to len - 1 and
1884 write 1 byte of zero */
1885 status = vfs_stat_fsp(fsp);
1886 if (!NT_STATUS_IS_OK(status)) {
1889 pst = &fsp->fsp_name->st;
1892 if (S_ISFIFO(pst->st_ex_mode)) {
1898 if (pst->st_ex_size == len) {
1903 if (pst->st_ex_size > len) {
1904 /* the ftruncate should have worked */
1908 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
1916 END_PROFILE(syscall_ftruncate);
1920 static int vfswrap_fallocate(vfs_handle_struct *handle,
1922 enum vfs_fallocate_mode mode,
1928 START_PROFILE(syscall_fallocate);
1929 if (mode == VFS_FALLOCATE_EXTEND_SIZE) {
1930 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
1931 } else if (mode == VFS_FALLOCATE_KEEP_SIZE) {
1932 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
1937 END_PROFILE(syscall_fallocate);
1941 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
1945 START_PROFILE(syscall_fcntl_lock);
1946 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
1947 END_PROFILE(syscall_fcntl_lock);
1951 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
1952 uint32 share_mode, uint32 access_mask)
1954 START_PROFILE(syscall_kernel_flock);
1955 kernel_flock(fsp->fh->fd, share_mode, access_mask);
1956 END_PROFILE(syscall_kernel_flock);
1960 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
1964 START_PROFILE(syscall_fcntl_getlock);
1965 result = fcntl_getlock(fsp->fh->fd, poffset, pcount, ptype, ppid);
1966 END_PROFILE(syscall_fcntl_getlock);
1970 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
1975 START_PROFILE(syscall_linux_setlease);
1977 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
1978 result = linux_setlease(fsp->fh->fd, leasetype);
1982 END_PROFILE(syscall_linux_setlease);
1986 static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
1990 START_PROFILE(syscall_symlink);
1991 result = symlink(oldpath, newpath);
1992 END_PROFILE(syscall_symlink);
1996 static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
2000 START_PROFILE(syscall_readlink);
2001 result = readlink(path, buf, bufsiz);
2002 END_PROFILE(syscall_readlink);
2006 static int vfswrap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2010 START_PROFILE(syscall_link);
2011 result = link(oldpath, newpath);
2012 END_PROFILE(syscall_link);
2016 static int vfswrap_mknod(vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev)
2020 START_PROFILE(syscall_mknod);
2021 result = sys_mknod(pathname, mode, dev);
2022 END_PROFILE(syscall_mknod);
2026 static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
2030 START_PROFILE(syscall_realpath);
2031 #ifdef REALPATH_TAKES_NULL
2032 result = realpath(path, NULL);
2034 result = SMB_MALLOC_ARRAY(char, PATH_MAX+1);
2036 char *resolved_path = realpath(path, result);
2037 if (!resolved_path) {
2040 /* SMB_ASSERT(result == resolved_path) ? */
2041 result = resolved_path;
2045 END_PROFILE(syscall_realpath);
2049 static NTSTATUS vfswrap_notify_watch(vfs_handle_struct *vfs_handle,
2050 struct sys_notify_context *ctx,
2053 uint32_t *subdir_filter,
2054 void (*callback)(struct sys_notify_context *ctx,
2056 struct notify_event *ev),
2057 void *private_data, void *handle)
2060 * So far inotify is the only supported default notify mechanism. If
2061 * another platform like the the BSD's or a proprietary Unix comes
2062 * along and wants another default, we can play the same trick we
2063 * played with Posix ACLs.
2065 * Until that is the case, hard-code inotify here.
2068 if (lp_kernel_change_notify(vfs_handle->conn->params)) {
2069 return inotify_watch(ctx, path, filter, subdir_filter,
2070 callback, private_data, handle);
2074 * Do nothing, leave everything to notify_internal.c
2076 return NT_STATUS_OK;
2079 static int vfswrap_chflags(vfs_handle_struct *handle, const char *path,
2083 return chflags(path, flags);
2090 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2091 const SMB_STRUCT_STAT *sbuf)
2095 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2099 key.devid = sbuf->st_ex_dev;
2100 key.inode = sbuf->st_ex_ino;
2101 /* key.extid is unused by default. */
2106 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2107 struct files_struct *fsp,
2109 TALLOC_CTX *mem_ctx,
2110 unsigned int *pnum_streams,
2111 struct stream_struct **pstreams)
2113 SMB_STRUCT_STAT sbuf;
2114 struct stream_struct *tmp_streams = NULL;
2117 if ((fsp != NULL) && (fsp->is_directory)) {
2119 * No default streams on directories
2124 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2125 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2128 struct smb_filename smb_fname;
2130 ZERO_STRUCT(smb_fname);
2131 smb_fname.base_name = discard_const_p(char, fname);
2133 if (lp_posix_pathnames()) {
2134 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname);
2136 ret = SMB_VFS_STAT(handle->conn, &smb_fname);
2138 sbuf = smb_fname.st;
2142 return map_nt_error_from_unix(errno);
2145 if (S_ISDIR(sbuf.st_ex_mode)) {
2149 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2150 (*pnum_streams) + 1);
2151 if (tmp_streams == NULL) {
2152 return NT_STATUS_NO_MEMORY;
2154 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2155 if (tmp_streams[*pnum_streams].name == NULL) {
2156 return NT_STATUS_NO_MEMORY;
2158 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2159 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2162 *pstreams = tmp_streams;
2164 return NT_STATUS_OK;
2167 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2170 TALLOC_CTX *mem_ctx,
2174 * Don't fall back to get_real_filename so callers can differentiate
2175 * between a full directory scan and an actual case-insensitive stat.
2181 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2184 return handle->conn->connectpath;
2187 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2188 struct byte_range_lock *br_lck,
2189 struct lock_struct *plock,
2191 struct blocking_lock_record *blr)
2193 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2195 /* Note: blr is not used in the default implementation. */
2196 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2199 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2200 struct messaging_context *msg_ctx,
2201 struct byte_range_lock *br_lck,
2202 const struct lock_struct *plock)
2204 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2206 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2209 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2210 struct byte_range_lock *br_lck,
2211 struct lock_struct *plock,
2212 struct blocking_lock_record *blr)
2214 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2216 /* Note: blr is not used in the default implementation. */
2217 return brl_lock_cancel_default(br_lck, plock);
2220 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2222 struct lock_struct *plock)
2224 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2225 plock->lock_type == WRITE_LOCK);
2227 return strict_lock_default(fsp, plock);
2230 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2232 struct lock_struct *plock)
2234 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2235 plock->lock_type == WRITE_LOCK);
2237 strict_unlock_default(fsp, plock);
2240 /* NT ACL operations. */
2242 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2244 uint32 security_info,
2245 TALLOC_CTX *mem_ctx,
2246 struct security_descriptor **ppdesc)
2250 START_PROFILE(fget_nt_acl);
2251 result = posix_fget_nt_acl(fsp, security_info,
2253 END_PROFILE(fget_nt_acl);
2257 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2259 uint32 security_info,
2260 TALLOC_CTX *mem_ctx,
2261 struct security_descriptor **ppdesc)
2265 START_PROFILE(get_nt_acl);
2266 result = posix_get_nt_acl(handle->conn, name, security_info,
2268 END_PROFILE(get_nt_acl);
2272 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32 security_info_sent, const struct security_descriptor *psd)
2276 START_PROFILE(fset_nt_acl);
2277 result = set_nt_acl(fsp, security_info_sent, psd);
2278 END_PROFILE(fset_nt_acl);
2282 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2283 struct smb_filename *file,
2284 struct security_acl *sacl,
2285 uint32_t access_requested,
2286 uint32_t access_denied)
2288 return NT_STATUS_OK; /* Nothing to do here ... */
2291 static int vfswrap_chmod_acl(vfs_handle_struct *handle, const char *name, mode_t mode)
2299 START_PROFILE(chmod_acl);
2300 result = chmod_acl(handle->conn, name, mode);
2301 END_PROFILE(chmod_acl);
2306 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2314 START_PROFILE(fchmod_acl);
2315 result = fchmod_acl(fsp, mode);
2316 END_PROFILE(fchmod_acl);
2321 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2323 SMB_ACL_TYPE_T type,
2324 TALLOC_CTX *mem_ctx)
2326 return sys_acl_get_file(handle, path_p, type, mem_ctx);
2329 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2331 TALLOC_CTX *mem_ctx)
2333 return sys_acl_get_fd(handle, fsp, mem_ctx);
2336 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2338 return sys_acl_set_file(handle, name, acltype, theacl);
2341 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2343 return sys_acl_set_fd(handle, fsp, theacl);
2346 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
2348 return sys_acl_delete_def_file(handle, path);
2351 /****************************************************************
2352 Extended attribute operations.
2353 *****************************************************************/
2355 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
2357 return getxattr(path, name, value, size);
2360 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2362 return fgetxattr(fsp->fh->fd, name, value, size);
2365 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
2367 return listxattr(path, list, size);
2370 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2372 return flistxattr(fsp->fh->fd, list, size);
2375 static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
2377 return removexattr(path, name);
2380 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2382 return fremovexattr(fsp->fh->fd, name);
2385 static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
2387 return setxattr(path, name, value, size, flags);
2390 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2392 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2395 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2400 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2401 const struct smb_filename *fname,
2402 SMB_STRUCT_STAT *sbuf)
2406 bool offline = false;
2408 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2412 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2413 #if defined(ENOTSUP)
2419 status = get_full_smb_filename(talloc_tos(), fname, &path);
2420 if (!NT_STATUS_IS_OK(status)) {
2421 errno = map_errno_from_nt_status(status);
2425 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2432 static int vfswrap_set_offline(struct vfs_handle_struct *handle,
2433 const struct smb_filename *fname)
2435 /* We don't know how to set offline bit by default, needs to be overriden in the vfs modules */
2436 #if defined(ENOTSUP)
2442 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2443 struct files_struct *fsp,
2444 TALLOC_CTX *mem_ctx,
2447 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2450 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2451 struct files_struct *fsp,
2452 const DATA_BLOB old_cookie,
2453 TALLOC_CTX *mem_ctx,
2454 DATA_BLOB *new_cookie)
2456 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2460 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2461 struct smb_request *smb1req,
2462 struct smbXsrv_open *op,
2463 const DATA_BLOB old_cookie,
2464 TALLOC_CTX *mem_ctx,
2465 struct files_struct **fsp,
2466 DATA_BLOB *new_cookie)
2468 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2469 old_cookie, mem_ctx,
2473 static struct vfs_fn_pointers vfs_default_fns = {
2474 /* Disk operations */
2476 .connect_fn = vfswrap_connect,
2477 .disconnect_fn = vfswrap_disconnect,
2478 .disk_free_fn = vfswrap_disk_free,
2479 .get_quota_fn = vfswrap_get_quota,
2480 .set_quota_fn = vfswrap_set_quota,
2481 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2482 .statvfs_fn = vfswrap_statvfs,
2483 .fs_capabilities_fn = vfswrap_fs_capabilities,
2484 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2486 /* Directory operations */
2488 .opendir_fn = vfswrap_opendir,
2489 .fdopendir_fn = vfswrap_fdopendir,
2490 .readdir_fn = vfswrap_readdir,
2491 .seekdir_fn = vfswrap_seekdir,
2492 .telldir_fn = vfswrap_telldir,
2493 .rewind_dir_fn = vfswrap_rewinddir,
2494 .mkdir_fn = vfswrap_mkdir,
2495 .rmdir_fn = vfswrap_rmdir,
2496 .closedir_fn = vfswrap_closedir,
2497 .init_search_op_fn = vfswrap_init_search_op,
2499 /* File operations */
2501 .open_fn = vfswrap_open,
2502 .create_file_fn = vfswrap_create_file,
2503 .close_fn = vfswrap_close,
2504 .read_fn = vfswrap_read,
2505 .pread_fn = vfswrap_pread,
2506 .pread_send_fn = vfswrap_pread_send,
2507 .pread_recv_fn = vfswrap_asys_ssize_t_recv,
2508 .write_fn = vfswrap_write,
2509 .pwrite_fn = vfswrap_pwrite,
2510 .pwrite_send_fn = vfswrap_pwrite_send,
2511 .pwrite_recv_fn = vfswrap_asys_ssize_t_recv,
2512 .lseek_fn = vfswrap_lseek,
2513 .sendfile_fn = vfswrap_sendfile,
2514 .recvfile_fn = vfswrap_recvfile,
2515 .rename_fn = vfswrap_rename,
2516 .fsync_fn = vfswrap_fsync,
2517 .fsync_send_fn = vfswrap_fsync_send,
2518 .fsync_recv_fn = vfswrap_asys_int_recv,
2519 .stat_fn = vfswrap_stat,
2520 .fstat_fn = vfswrap_fstat,
2521 .lstat_fn = vfswrap_lstat,
2522 .get_alloc_size_fn = vfswrap_get_alloc_size,
2523 .unlink_fn = vfswrap_unlink,
2524 .chmod_fn = vfswrap_chmod,
2525 .fchmod_fn = vfswrap_fchmod,
2526 .chown_fn = vfswrap_chown,
2527 .fchown_fn = vfswrap_fchown,
2528 .lchown_fn = vfswrap_lchown,
2529 .chdir_fn = vfswrap_chdir,
2530 .getwd_fn = vfswrap_getwd,
2531 .ntimes_fn = vfswrap_ntimes,
2532 .ftruncate_fn = vfswrap_ftruncate,
2533 .fallocate_fn = vfswrap_fallocate,
2534 .lock_fn = vfswrap_lock,
2535 .kernel_flock_fn = vfswrap_kernel_flock,
2536 .linux_setlease_fn = vfswrap_linux_setlease,
2537 .getlock_fn = vfswrap_getlock,
2538 .symlink_fn = vfswrap_symlink,
2539 .readlink_fn = vfswrap_readlink,
2540 .link_fn = vfswrap_link,
2541 .mknod_fn = vfswrap_mknod,
2542 .realpath_fn = vfswrap_realpath,
2543 .notify_watch_fn = vfswrap_notify_watch,
2544 .chflags_fn = vfswrap_chflags,
2545 .file_id_create_fn = vfswrap_file_id_create,
2546 .streaminfo_fn = vfswrap_streaminfo,
2547 .get_real_filename_fn = vfswrap_get_real_filename,
2548 .connectpath_fn = vfswrap_connectpath,
2549 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2550 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2551 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2552 .strict_lock_fn = vfswrap_strict_lock,
2553 .strict_unlock_fn = vfswrap_strict_unlock,
2554 .translate_name_fn = vfswrap_translate_name,
2555 .fsctl_fn = vfswrap_fsctl,
2556 .copy_chunk_send_fn = vfswrap_copy_chunk_send,
2557 .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
2558 .get_compression_fn = vfswrap_get_compression,
2559 .set_compression_fn = vfswrap_set_compression,
2561 /* NT ACL operations. */
2563 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2564 .get_nt_acl_fn = vfswrap_get_nt_acl,
2565 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2566 .audit_file_fn = vfswrap_audit_file,
2568 /* POSIX ACL operations. */
2570 .chmod_acl_fn = vfswrap_chmod_acl,
2571 .fchmod_acl_fn = vfswrap_fchmod_acl,
2573 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2574 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2575 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2576 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2577 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2578 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2579 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2581 /* EA operations. */
2582 .getxattr_fn = vfswrap_getxattr,
2583 .fgetxattr_fn = vfswrap_fgetxattr,
2584 .listxattr_fn = vfswrap_listxattr,
2585 .flistxattr_fn = vfswrap_flistxattr,
2586 .removexattr_fn = vfswrap_removexattr,
2587 .fremovexattr_fn = vfswrap_fremovexattr,
2588 .setxattr_fn = vfswrap_setxattr,
2589 .fsetxattr_fn = vfswrap_fsetxattr,
2591 /* aio operations */
2592 .aio_force_fn = vfswrap_aio_force,
2594 /* offline operations */
2595 .is_offline_fn = vfswrap_is_offline,
2596 .set_offline_fn = vfswrap_set_offline,
2598 /* durable handle operations */
2599 .durable_cookie_fn = vfswrap_durable_cookie,
2600 .durable_disconnect_fn = vfswrap_durable_disconnect,
2601 .durable_reconnect_fn = vfswrap_durable_reconnect,
2604 NTSTATUS vfs_default_init(void);
2605 NTSTATUS vfs_default_init(void)
2607 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
2608 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);