2 Unix SMB/CIFS implementation.
3 Wrap disk only vfs functions to sidestep dodgy compilers.
4 Copyright (C) Tim Potter 1998
5 Copyright (C) Jeremy Allison 2007
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "system/time.h"
23 #include "system/filesys.h"
24 #include "smbd/smbd.h"
25 #include "smbd/globals.h"
27 #include "smbprofile.h"
28 #include "../libcli/security/security.h"
29 #include "passdb/lookup_sid.h"
30 #include "source3/include/msdfs.h"
31 #include "librpc/gen_ndr/ndr_dfsblobs.h"
32 #include "lib/util/tevent_unix.h"
33 #include "lib/asys/asys.h"
34 #include "lib/util/tevent_ntstatus.h"
35 #include "lib/sys_rw.h"
38 #define DBGC_CLASS DBGC_VFS
40 /* Check for NULL pointer parameters in vfswrap_* functions */
42 /* We don't want to have NULL function pointers lying around. Someone
43 is sure to try and execute them. These stubs are used to prevent
46 static int vfswrap_connect(vfs_handle_struct *handle, const char *service, const char *user)
48 return 0; /* Return >= 0 for success */
51 static void vfswrap_disconnect(vfs_handle_struct *handle)
57 static uint64_t vfswrap_disk_free(vfs_handle_struct *handle, const char *path,
58 uint64_t *bsize, uint64_t *dfree,
63 result = sys_disk_free(handle->conn, path, bsize, dfree, dsize);
67 static int vfswrap_get_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
69 #ifdef HAVE_SYS_QUOTAS
72 START_PROFILE(syscall_get_quota);
73 result = sys_get_quota(handle->conn->connectpath, qtype, id, qt);
74 END_PROFILE(syscall_get_quota);
82 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
84 #ifdef HAVE_SYS_QUOTAS
87 START_PROFILE(syscall_set_quota);
88 result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
89 END_PROFILE(syscall_set_quota);
97 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
98 struct files_struct *fsp,
99 struct shadow_copy_data *shadow_copy_data,
103 return -1; /* Not implemented. */
106 static int vfswrap_statvfs(struct vfs_handle_struct *handle, const char *path, vfs_statvfs_struct *statbuf)
108 return sys_statvfs(path, statbuf);
111 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
112 enum timestamp_set_resolution *p_ts_res)
114 connection_struct *conn = handle->conn;
115 uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
116 struct smb_filename *smb_fname_cpath = NULL;
117 struct vfs_statvfs_struct statbuf;
120 ZERO_STRUCT(statbuf);
121 ret = sys_statvfs(conn->connectpath, &statbuf);
123 caps = statbuf.FsCapabilities;
126 *p_ts_res = TIMESTAMP_SET_SECONDS;
128 /* Work out what timestamp resolution we can
129 * use when setting a timestamp. */
131 smb_fname_cpath = synthetic_smb_fname(talloc_tos(), conn->connectpath,
133 if (smb_fname_cpath == NULL) {
137 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
139 TALLOC_FREE(smb_fname_cpath);
143 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
144 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
145 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
146 /* If any of the normal UNIX directory timestamps
147 * have a non-zero tv_nsec component assume
148 * we might be able to set sub-second timestamps.
149 * See what filetime set primitives we have.
151 #if defined(HAVE_UTIMENSAT)
152 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
153 #elif defined(HAVE_UTIMES)
154 /* utimes allows msec timestamps to be set. */
155 *p_ts_res = TIMESTAMP_SET_MSEC;
156 #elif defined(HAVE_UTIME)
157 /* utime only allows sec timestamps to be set. */
158 *p_ts_res = TIMESTAMP_SET_SECONDS;
161 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
163 "available on share %s, directory %s\n",
164 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
165 lp_servicename(talloc_tos(), conn->params->service),
166 conn->connectpath ));
168 TALLOC_FREE(smb_fname_cpath);
172 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
173 struct dfs_GetDFSReferral *r)
175 struct junction_map *junction = NULL;
177 bool self_referral = false;
178 char *pathnamep = NULL;
179 char *local_dfs_path = NULL;
182 uint16_t max_referral_level = r->in.req.max_referral_level;
185 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
188 /* get the junction entry */
189 if (r->in.req.servername == NULL) {
190 return NT_STATUS_NOT_FOUND;
194 * Trim pathname sent by client so it begins with only one backslash.
195 * Two backslashes confuse some dfs clients
198 local_dfs_path = talloc_strdup(r, r->in.req.servername);
199 if (local_dfs_path == NULL) {
200 return NT_STATUS_NO_MEMORY;
202 pathnamep = local_dfs_path;
203 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
204 IS_DIRECTORY_SEP(pathnamep[1])) {
208 junction = talloc_zero(r, struct junction_map);
209 if (junction == NULL) {
210 return NT_STATUS_NO_MEMORY;
213 /* The following call can change cwd. */
214 status = get_referred_path(r, pathnamep,
215 !handle->conn->sconn->using_smb2,
216 junction, &consumedcnt, &self_referral);
217 if (!NT_STATUS_IS_OK(status)) {
218 vfs_ChDir(handle->conn, handle->conn->connectpath);
221 vfs_ChDir(handle->conn, handle->conn->connectpath);
223 if (!self_referral) {
224 pathnamep[consumedcnt] = '\0';
227 dbgtext("Path %s to alternate path(s):",
229 for (i=0; i < junction->referral_count; i++) {
231 junction->referral_list[i].alternate_path);
237 if (r->in.req.max_referral_level <= 2) {
238 max_referral_level = 2;
240 if (r->in.req.max_referral_level >= 3) {
241 max_referral_level = 3;
244 r->out.resp = talloc_zero(r, struct dfs_referral_resp);
245 if (r->out.resp == NULL) {
246 return NT_STATUS_NO_MEMORY;
249 r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
250 r->out.resp->nb_referrals = junction->referral_count;
252 r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
254 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
257 r->out.resp->referral_entries = talloc_zero_array(r,
258 struct dfs_referral_type,
259 r->out.resp->nb_referrals);
260 if (r->out.resp->referral_entries == NULL) {
261 return NT_STATUS_NO_MEMORY;
264 switch (max_referral_level) {
266 for(i=0; i < junction->referral_count; i++) {
267 struct referral *ref = &junction->referral_list[i];
268 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
269 struct dfs_referral_type *t =
270 &r->out.resp->referral_entries[i];
271 struct dfs_referral_v2 *v2 = &t->referral.v2;
274 v2->size = VERSION2_REFERRAL_SIZE;
276 v2->server_type = DFS_SERVER_ROOT;
278 v2->server_type = DFS_SERVER_NON_ROOT;
281 v2->proximity = ref->proximity;
283 v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
284 if (v2->DFS_path == NULL) {
285 return NT_STATUS_NO_MEMORY;
287 v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
288 if (v2->DFS_alt_path == NULL) {
289 return NT_STATUS_NO_MEMORY;
291 v2->netw_address = talloc_strdup(mem_ctx,
292 ref->alternate_path);
293 if (v2->netw_address == NULL) {
294 return NT_STATUS_NO_MEMORY;
300 for(i=0; i < junction->referral_count; i++) {
301 struct referral *ref = &junction->referral_list[i];
302 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
303 struct dfs_referral_type *t =
304 &r->out.resp->referral_entries[i];
305 struct dfs_referral_v3 *v3 = &t->referral.v3;
306 struct dfs_normal_referral *r1 = &v3->referrals.r1;
309 v3->size = VERSION3_REFERRAL_SIZE;
311 v3->server_type = DFS_SERVER_ROOT;
313 v3->server_type = DFS_SERVER_NON_ROOT;
317 r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
318 if (r1->DFS_path == NULL) {
319 return NT_STATUS_NO_MEMORY;
321 r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
322 if (r1->DFS_alt_path == NULL) {
323 return NT_STATUS_NO_MEMORY;
325 r1->netw_address = talloc_strdup(mem_ctx,
326 ref->alternate_path);
327 if (r1->netw_address == NULL) {
328 return NT_STATUS_NO_MEMORY;
333 DEBUG(0,("Invalid dfs referral version: %d\n",
334 max_referral_level));
335 return NT_STATUS_INVALID_LEVEL;
339 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
345 static NTSTATUS vfswrap_snap_check_path(struct vfs_handle_struct *handle,
347 const char *service_path,
350 return NT_STATUS_NOT_SUPPORTED;
353 static NTSTATUS vfswrap_snap_create(struct vfs_handle_struct *handle,
355 const char *base_volume,
361 return NT_STATUS_NOT_SUPPORTED;
364 static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle,
369 return NT_STATUS_NOT_SUPPORTED;
372 /* Directory operations */
374 static DIR *vfswrap_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32_t attr)
378 START_PROFILE(syscall_opendir);
379 result = opendir(fname);
380 END_PROFILE(syscall_opendir);
384 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
391 START_PROFILE(syscall_fdopendir);
392 result = sys_fdopendir(fsp->fh->fd);
393 END_PROFILE(syscall_fdopendir);
398 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
400 SMB_STRUCT_STAT *sbuf)
402 struct dirent *result;
404 START_PROFILE(syscall_readdir);
405 result = readdir(dirp);
406 END_PROFILE(syscall_readdir);
408 /* Default Posix readdir() does not give us stat info.
409 * Set to invalid to indicate we didn't return this info. */
410 SET_STAT_INVALID(*sbuf);
411 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
412 if (result != NULL) {
413 /* See if we can efficiently return this. */
415 int flags = (lp_posix_pathnames() ?
416 AT_SYMLINK_NOFOLLOW : 0);
417 int ret = fstatat(dirfd(dirp),
422 init_stat_ex_from_stat(sbuf,
424 lp_fake_directory_create_times(
425 SNUM(handle->conn)));
433 static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
434 const struct smb_filename *fname,
436 struct readdir_attr_data **attr_data)
438 return NT_STATUS_NOT_SUPPORTED;
441 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
443 START_PROFILE(syscall_seekdir);
444 seekdir(dirp, offset);
445 END_PROFILE(syscall_seekdir);
448 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
451 START_PROFILE(syscall_telldir);
452 result = telldir(dirp);
453 END_PROFILE(syscall_telldir);
457 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
459 START_PROFILE(syscall_rewinddir);
461 END_PROFILE(syscall_rewinddir);
464 static int vfswrap_mkdir(vfs_handle_struct *handle, const char *path, mode_t mode)
467 bool has_dacl = False;
470 START_PROFILE(syscall_mkdir);
472 if (lp_inherit_acls(SNUM(handle->conn))
473 && parent_dirname(talloc_tos(), path, &parent, NULL)
474 && (has_dacl = directory_has_default_acl(handle->conn, parent)))
475 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
479 result = mkdir(path, mode);
481 if (result == 0 && !has_dacl) {
483 * We need to do this as the default behavior of POSIX ACLs
484 * is to set the mask to be the requested group permission
485 * bits, not the group permission bits to be the requested
486 * group permission bits. This is not what we want, as it will
487 * mess up any inherited ACL bits that were set. JRA.
489 int saved_errno = errno; /* We may get ENOSYS */
490 if ((SMB_VFS_CHMOD_ACL(handle->conn, path, mode) == -1) && (errno == ENOSYS))
494 END_PROFILE(syscall_mkdir);
498 static int vfswrap_rmdir(vfs_handle_struct *handle, const char *path)
502 START_PROFILE(syscall_rmdir);
503 result = rmdir(path);
504 END_PROFILE(syscall_rmdir);
508 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
512 START_PROFILE(syscall_closedir);
513 result = closedir(dirp);
514 END_PROFILE(syscall_closedir);
518 static void vfswrap_init_search_op(vfs_handle_struct *handle,
521 /* Default behavior is a NOOP */
524 /* File operations */
526 static int vfswrap_open(vfs_handle_struct *handle,
527 struct smb_filename *smb_fname,
528 files_struct *fsp, int flags, mode_t mode)
532 START_PROFILE(syscall_open);
534 if (smb_fname->stream_name) {
539 result = open(smb_fname->base_name, flags, mode);
541 END_PROFILE(syscall_open);
545 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
546 struct smb_request *req,
547 uint16_t root_dir_fid,
548 struct smb_filename *smb_fname,
549 uint32_t access_mask,
550 uint32_t share_access,
551 uint32_t create_disposition,
552 uint32_t create_options,
553 uint32_t file_attributes,
554 uint32_t oplock_request,
555 struct smb2_lease *lease,
556 uint64_t allocation_size,
557 uint32_t private_flags,
558 struct security_descriptor *sd,
559 struct ea_list *ea_list,
560 files_struct **result,
562 const struct smb2_create_blobs *in_context_blobs,
563 struct smb2_create_blobs *out_context_blobs)
565 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
566 access_mask, share_access,
567 create_disposition, create_options,
568 file_attributes, oplock_request, lease,
569 allocation_size, private_flags,
571 pinfo, in_context_blobs, out_context_blobs);
574 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
578 START_PROFILE(syscall_close);
579 result = fd_close_posix(fsp);
580 END_PROFILE(syscall_close);
584 static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
588 START_PROFILE_BYTES(syscall_read, n);
589 result = sys_read(fsp->fh->fd, data, n);
590 END_PROFILE_BYTES(syscall_read);
594 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
595 size_t n, off_t offset)
599 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
600 START_PROFILE_BYTES(syscall_pread, n);
601 result = sys_pread(fsp->fh->fd, data, n, offset);
602 END_PROFILE_BYTES(syscall_pread);
604 if (result == -1 && errno == ESPIPE) {
605 /* Maintain the fiction that pipes can be seeked (sought?) on. */
606 result = SMB_VFS_READ(fsp, data, n);
610 #else /* HAVE_PREAD */
614 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
615 if (curr == -1 && errno == ESPIPE) {
616 /* Maintain the fiction that pipes can be seeked (sought?) on. */
617 result = SMB_VFS_READ(fsp, data, n);
622 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
627 result = SMB_VFS_READ(fsp, data, n);
630 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
633 #endif /* HAVE_PREAD */
638 static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
642 START_PROFILE_BYTES(syscall_write, n);
643 result = sys_write(fsp->fh->fd, data, n);
644 END_PROFILE_BYTES(syscall_write);
648 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
649 size_t n, off_t offset)
653 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
654 START_PROFILE_BYTES(syscall_pwrite, n);
655 result = sys_pwrite(fsp->fh->fd, data, n, offset);
656 END_PROFILE_BYTES(syscall_pwrite);
658 if (result == -1 && errno == ESPIPE) {
659 /* Maintain the fiction that pipes can be sought on. */
660 result = SMB_VFS_WRITE(fsp, data, n);
663 #else /* HAVE_PWRITE */
667 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
672 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
676 result = SMB_VFS_WRITE(fsp, data, n);
679 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
682 #endif /* HAVE_PWRITE */
687 static void vfswrap_asys_finished(struct tevent_context *ev,
688 struct tevent_fd *fde,
689 uint16_t flags, void *p);
691 static bool vfswrap_init_asys_ctx(struct smbd_server_connection *conn)
696 if (conn->asys_ctx != NULL) {
699 ret = asys_context_init(&conn->asys_ctx, aio_pending_size);
701 DEBUG(1, ("asys_context_init failed: %s\n", strerror(ret)));
705 fd = asys_signalfd(conn->asys_ctx);
707 ret = set_blocking(fd, false);
709 DBG_WARNING("set_blocking failed: %s\n", strerror(errno));
713 conn->asys_fde = tevent_add_fd(conn->ev_ctx, conn, fd,
715 vfswrap_asys_finished,
717 if (conn->asys_fde == NULL) {
718 DEBUG(1, ("tevent_add_fd failed\n"));
724 asys_context_destroy(conn->asys_ctx);
725 conn->asys_ctx = NULL;
729 struct vfswrap_asys_state {
730 struct asys_context *asys_ctx;
731 struct tevent_req *req;
734 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
735 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
738 static int vfswrap_asys_state_destructor(struct vfswrap_asys_state *s)
740 asys_cancel(s->asys_ctx, s->req);
744 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
746 struct tevent_context *ev,
747 struct files_struct *fsp,
749 size_t n, off_t offset)
751 struct tevent_req *req;
752 struct vfswrap_asys_state *state;
755 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
759 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
761 return tevent_req_post(req, ev);
763 state->asys_ctx = handle->conn->sconn->asys_ctx;
766 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
767 state->profile_bytes, n);
768 ret = asys_pread(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
770 tevent_req_error(req, ret);
771 return tevent_req_post(req, ev);
773 talloc_set_destructor(state, vfswrap_asys_state_destructor);
778 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
780 struct tevent_context *ev,
781 struct files_struct *fsp,
783 size_t n, off_t offset)
785 struct tevent_req *req;
786 struct vfswrap_asys_state *state;
789 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
793 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
795 return tevent_req_post(req, ev);
797 state->asys_ctx = handle->conn->sconn->asys_ctx;
800 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
801 state->profile_bytes, n);
802 ret = asys_pwrite(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
804 tevent_req_error(req, ret);
805 return tevent_req_post(req, ev);
807 talloc_set_destructor(state, vfswrap_asys_state_destructor);
812 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
814 struct tevent_context *ev,
815 struct files_struct *fsp)
817 struct tevent_req *req;
818 struct vfswrap_asys_state *state;
821 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
825 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
827 return tevent_req_post(req, ev);
829 state->asys_ctx = handle->conn->sconn->asys_ctx;
832 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
833 state->profile_basic);
834 ret = asys_fsync(state->asys_ctx, fsp->fh->fd, req);
836 tevent_req_error(req, ret);
837 return tevent_req_post(req, ev);
839 talloc_set_destructor(state, vfswrap_asys_state_destructor);
844 static void vfswrap_asys_finished(struct tevent_context *ev,
845 struct tevent_fd *fde,
846 uint16_t flags, void *p)
848 struct asys_context *asys_ctx = (struct asys_context *)p;
849 struct asys_result results[outstanding_aio_calls];
852 if ((flags & TEVENT_FD_READ) == 0) {
856 ret = asys_results(asys_ctx, results, outstanding_aio_calls);
858 DEBUG(1, ("asys_results returned %s\n", strerror(-ret)));
862 for (i=0; i<ret; i++) {
863 struct asys_result *result = &results[i];
864 struct tevent_req *req;
865 struct vfswrap_asys_state *state;
867 if ((result->ret == -1) && (result->err == ECANCELED)) {
871 req = talloc_get_type_abort(result->private_data,
873 state = tevent_req_data(req, struct vfswrap_asys_state);
875 talloc_set_destructor(state, NULL);
877 SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
878 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
879 state->ret = result->ret;
880 state->err = result->err;
881 tevent_req_defer_callback(req, ev);
882 tevent_req_done(req);
886 static ssize_t vfswrap_asys_ssize_t_recv(struct tevent_req *req, int *err)
888 struct vfswrap_asys_state *state = tevent_req_data(
889 req, struct vfswrap_asys_state);
891 if (tevent_req_is_unix_error(req, err)) {
898 static int vfswrap_asys_int_recv(struct tevent_req *req, int *err)
900 struct vfswrap_asys_state *state = tevent_req_data(
901 req, struct vfswrap_asys_state);
903 if (tevent_req_is_unix_error(req, err)) {
910 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
914 START_PROFILE(syscall_lseek);
916 /* Cope with 'stat' file opens. */
917 if (fsp->fh->fd != -1)
918 result = lseek(fsp->fh->fd, offset, whence);
921 * We want to maintain the fiction that we can seek
922 * on a fifo for file system purposes. This allows
923 * people to set up UNIX fifo's that feed data to Windows
927 if((result == -1) && (errno == ESPIPE)) {
932 END_PROFILE(syscall_lseek);
936 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
937 off_t offset, size_t n)
941 START_PROFILE_BYTES(syscall_sendfile, n);
942 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
943 END_PROFILE_BYTES(syscall_sendfile);
947 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
955 START_PROFILE_BYTES(syscall_recvfile, n);
956 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
957 END_PROFILE_BYTES(syscall_recvfile);
961 static int vfswrap_rename(vfs_handle_struct *handle,
962 const struct smb_filename *smb_fname_src,
963 const struct smb_filename *smb_fname_dst)
967 START_PROFILE(syscall_rename);
969 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
974 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
977 END_PROFILE(syscall_rename);
981 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
986 START_PROFILE(syscall_fsync);
987 result = fsync(fsp->fh->fd);
988 END_PROFILE(syscall_fsync);
995 static int vfswrap_stat(vfs_handle_struct *handle,
996 struct smb_filename *smb_fname)
1000 START_PROFILE(syscall_stat);
1002 if (smb_fname->stream_name) {
1007 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1008 lp_fake_directory_create_times(SNUM(handle->conn)));
1010 END_PROFILE(syscall_stat);
1014 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1018 START_PROFILE(syscall_fstat);
1019 result = sys_fstat(fsp->fh->fd,
1020 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1021 END_PROFILE(syscall_fstat);
1025 static int vfswrap_lstat(vfs_handle_struct *handle,
1026 struct smb_filename *smb_fname)
1030 START_PROFILE(syscall_lstat);
1032 if (smb_fname->stream_name) {
1037 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1038 lp_fake_directory_create_times(SNUM(handle->conn)));
1040 END_PROFILE(syscall_lstat);
1044 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1046 enum vfs_translate_direction direction,
1047 TALLOC_CTX *mem_ctx,
1050 return NT_STATUS_NONE_MAPPED;
1054 * Implement the default fsctl operation.
1056 static bool vfswrap_logged_ioctl_message = false;
1058 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1059 struct files_struct *fsp,
1062 uint16_t req_flags, /* Needed for UNICODE ... */
1063 const uint8_t *_in_data,
1065 uint8_t **_out_data,
1066 uint32_t max_out_len,
1069 const char *in_data = (const char *)_in_data;
1070 char **out_data = (char **)_out_data;
1074 case FSCTL_SET_SPARSE:
1076 bool set_sparse = true;
1078 if (in_len >= 1 && in_data[0] == 0) {
1082 status = file_set_sparse(handle->conn, fsp, set_sparse);
1084 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1085 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1086 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1087 nt_errstr(status)));
1092 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1094 unsigned char objid[16];
1095 char *return_data = NULL;
1097 /* This should return the object-id on this file.
1098 * I think I'll make this be the inode+dev. JRA.
1101 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1102 fsp_fnum_dbg(fsp)));
1104 *out_len = MIN(max_out_len, 64);
1106 /* Hmmm, will this cause problems if less data asked for? */
1107 return_data = talloc_array(ctx, char, 64);
1108 if (return_data == NULL) {
1109 return NT_STATUS_NO_MEMORY;
1112 /* For backwards compatibility only store the dev/inode. */
1113 push_file_id_16(return_data, &fsp->file_id);
1114 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1115 push_file_id_16(return_data+32, &fsp->file_id);
1116 memset(return_data+48, 0, 16);
1117 *out_data = return_data;
1118 return NT_STATUS_OK;
1121 case FSCTL_GET_REPARSE_POINT:
1123 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1124 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1125 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1126 return NT_STATUS_NOT_A_REPARSE_POINT;
1129 case FSCTL_SET_REPARSE_POINT:
1131 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1132 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1133 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1134 return NT_STATUS_NOT_A_REPARSE_POINT;
1137 case FSCTL_GET_SHADOW_COPY_DATA:
1140 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1141 * and return their volume names. If max_data_count is 16, then it is just
1142 * asking for the number of volumes and length of the combined names.
1144 * pdata is the data allocated by our caller, but that uses
1145 * total_data_count (which is 0 in our case) rather than max_data_count.
1146 * Allocate the correct amount and return the pointer to let
1147 * it be deallocated when we return.
1149 struct shadow_copy_data *shadow_data = NULL;
1150 bool labels = False;
1151 uint32_t labels_data_count = 0;
1153 char *cur_pdata = NULL;
1155 if (max_out_len < 16) {
1156 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1158 return NT_STATUS_INVALID_PARAMETER;
1161 if (max_out_len > 16) {
1165 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1166 if (shadow_data == NULL) {
1167 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1168 return NT_STATUS_NO_MEMORY;
1172 * Call the VFS routine to actually do the work.
1174 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1177 /* broken module didn't set errno on error */
1178 status = NT_STATUS_UNSUCCESSFUL;
1180 status = map_nt_error_from_unix(errno);
1181 if (NT_STATUS_EQUAL(status,
1182 NT_STATUS_NOT_SUPPORTED)) {
1186 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1187 "connectpath %s, failed - %s.\n",
1188 fsp->conn->connectpath,
1189 nt_errstr(status)));
1190 TALLOC_FREE(shadow_data);
1194 labels_data_count = (shadow_data->num_volumes * 2 *
1195 sizeof(SHADOW_COPY_LABEL)) + 2;
1200 *out_len = 12 + labels_data_count;
1203 if (max_out_len < *out_len) {
1204 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1205 max_out_len, *out_len));
1206 TALLOC_FREE(shadow_data);
1207 return NT_STATUS_BUFFER_TOO_SMALL;
1210 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1211 if (cur_pdata == NULL) {
1212 TALLOC_FREE(shadow_data);
1213 return NT_STATUS_NO_MEMORY;
1216 *out_data = cur_pdata;
1218 /* num_volumes 4 bytes */
1219 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1222 /* num_labels 4 bytes */
1223 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1226 /* needed_data_count 4 bytes */
1227 SIVAL(cur_pdata, 8, labels_data_count);
1231 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1232 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1233 if (labels && shadow_data->labels) {
1234 for (i=0; i<shadow_data->num_volumes; i++) {
1236 status = srvstr_push(cur_pdata, req_flags,
1237 cur_pdata, shadow_data->labels[i],
1238 2 * sizeof(SHADOW_COPY_LABEL),
1239 STR_UNICODE|STR_TERMINATE, &len);
1240 if (!NT_STATUS_IS_OK(status)) {
1241 TALLOC_FREE(*out_data);
1242 TALLOC_FREE(shadow_data);
1245 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1246 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1250 TALLOC_FREE(shadow_data);
1252 return NT_STATUS_OK;
1255 case FSCTL_FIND_FILES_BY_SID:
1257 /* pretend this succeeded -
1259 * we have to send back a list with all files owned by this SID
1261 * but I have to check that --metze
1267 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1268 fsp_fnum_dbg(fsp)));
1271 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1272 return NT_STATUS_INVALID_PARAMETER;
1275 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1277 /* unknown 4 bytes: this is not the length of the sid :-( */
1278 /*unknown = IVAL(pdata,0);*/
1280 if (!sid_parse(in_data + 4, sid_len, &sid)) {
1281 return NT_STATUS_INVALID_PARAMETER;
1283 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1285 if (!sid_to_uid(&sid, &uid)) {
1286 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1287 sid_string_dbg(&sid),
1288 (unsigned long)sid_len));
1292 /* we can take a look at the find source :-)
1294 * find ./ -uid $uid -name '*' is what we need here
1297 * and send 4bytes len and then NULL terminated unicode strings
1300 * but I don't know how to deal with the paged results
1301 * (maybe we can hang the result anywhere in the fsp struct)
1303 * but I don't know how to deal with the paged results
1304 * (maybe we can hang the result anywhere in the fsp struct)
1306 * we don't send all files at once
1307 * and at the next we should *not* start from the beginning,
1308 * so we have to cache the result
1313 /* this works for now... */
1314 return NT_STATUS_OK;
1317 case FSCTL_QUERY_ALLOCATED_RANGES:
1319 /* FIXME: This is just a dummy reply, telling that all of the
1320 * file is allocated. MKS cp needs that.
1321 * Adding the real allocated ranges via FIEMAP on Linux
1322 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1323 * this FSCTL correct for sparse files.
1325 uint64_t offset, length;
1326 char *out_data_tmp = NULL;
1329 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1331 return NT_STATUS_INVALID_PARAMETER;
1334 if (max_out_len < 16) {
1335 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1337 return NT_STATUS_INVALID_PARAMETER;
1340 offset = BVAL(in_data,0);
1341 length = BVAL(in_data,8);
1343 if (offset + length < offset) {
1344 /* No 64-bit integer wrap. */
1345 return NT_STATUS_INVALID_PARAMETER;
1348 /* Shouldn't this be SMB_VFS_STAT ... ? */
1349 status = vfs_stat_fsp(fsp);
1350 if (!NT_STATUS_IS_OK(status)) {
1355 out_data_tmp = talloc_array(ctx, char, *out_len);
1356 if (out_data_tmp == NULL) {
1357 DEBUG(10, ("unable to allocate memory for response\n"));
1358 return NT_STATUS_NO_MEMORY;
1361 if (offset > fsp->fsp_name->st.st_ex_size ||
1362 fsp->fsp_name->st.st_ex_size == 0 ||
1364 memset(out_data_tmp, 0, *out_len);
1366 uint64_t end = offset + length;
1367 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1368 SBVAL(out_data_tmp, 0, 0);
1369 SBVAL(out_data_tmp, 8, end);
1372 *out_data = out_data_tmp;
1374 return NT_STATUS_OK;
1377 case FSCTL_IS_VOLUME_DIRTY:
1379 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1380 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1382 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1383 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1385 return NT_STATUS_INVALID_PARAMETER;
1390 * Only print once ... unfortunately there could be lots of
1391 * different FSCTLs that are called.
1393 if (!vfswrap_logged_ioctl_message) {
1394 vfswrap_logged_ioctl_message = true;
1395 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1396 __func__, function));
1400 return NT_STATUS_NOT_SUPPORTED;
1403 struct vfs_cc_state {
1408 static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *handle,
1409 TALLOC_CTX *mem_ctx,
1410 struct tevent_context *ev,
1411 struct files_struct *src_fsp,
1413 struct files_struct *dest_fsp,
1417 struct tevent_req *req;
1418 struct vfs_cc_state *vfs_cc_state;
1421 DEBUG(10, ("performing server side copy chunk of length %lu\n",
1422 (unsigned long)num));
1424 req = tevent_req_create(mem_ctx, &vfs_cc_state, struct vfs_cc_state);
1429 vfs_cc_state->buf = talloc_array(vfs_cc_state, uint8_t,
1430 MIN(num, 8*1024*1024));
1431 if (tevent_req_nomem(vfs_cc_state->buf, req)) {
1432 return tevent_req_post(req, ev);
1435 status = vfs_stat_fsp(src_fsp);
1436 if (tevent_req_nterror(req, status)) {
1437 return tevent_req_post(req, ev);
1440 if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
1442 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1443 * If the SourceOffset or SourceOffset + Length extends beyond
1444 * the end of file, the server SHOULD<240> treat this as a
1445 * STATUS_END_OF_FILE error.
1447 * <240> Section 3.3.5.15.6: Windows servers will return
1448 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1450 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1451 return tevent_req_post(req, ev);
1454 /* could use 2.6.33+ sendfile here to do this in kernel */
1455 while (vfs_cc_state->copied < num) {
1457 struct lock_struct lck;
1460 off_t this_num = MIN(talloc_array_length(vfs_cc_state->buf),
1461 num - vfs_cc_state->copied);
1463 if (src_fsp->op == NULL) {
1464 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1465 return tevent_req_post(req, ev);
1467 init_strict_lock_struct(src_fsp,
1468 src_fsp->op->global->open_persistent_id,
1474 if (!SMB_VFS_STRICT_LOCK(src_fsp->conn, src_fsp, &lck)) {
1475 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1476 return tevent_req_post(req, ev);
1479 ret = SMB_VFS_PREAD(src_fsp, vfs_cc_state->buf,
1482 saved_errno = errno;
1485 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1488 errno = saved_errno;
1489 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1490 return tevent_req_post(req, ev);
1492 if (ret != this_num) {
1493 /* zero tolerance for short reads */
1494 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1495 return tevent_req_post(req, ev);
1500 if (dest_fsp->op == NULL) {
1501 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1502 return tevent_req_post(req, ev);
1505 init_strict_lock_struct(dest_fsp,
1506 dest_fsp->op->global->open_persistent_id,
1512 if (!SMB_VFS_STRICT_LOCK(dest_fsp->conn, dest_fsp, &lck)) {
1513 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1514 return tevent_req_post(req, ev);
1517 ret = SMB_VFS_PWRITE(dest_fsp, vfs_cc_state->buf,
1518 this_num, dest_off);
1520 saved_errno = errno;
1523 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1526 errno = saved_errno;
1527 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1528 return tevent_req_post(req, ev);
1530 if (ret != this_num) {
1531 /* zero tolerance for short writes */
1532 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1533 return tevent_req_post(req, ev);
1537 vfs_cc_state->copied += this_num;
1540 tevent_req_done(req);
1541 return tevent_req_post(req, ev);
1544 static NTSTATUS vfswrap_copy_chunk_recv(struct vfs_handle_struct *handle,
1545 struct tevent_req *req,
1548 struct vfs_cc_state *vfs_cc_state = tevent_req_data(req,
1549 struct vfs_cc_state);
1552 if (tevent_req_is_nterror(req, &status)) {
1553 DEBUG(2, ("server side copy chunk failed: %s\n",
1554 nt_errstr(status)));
1556 tevent_req_received(req);
1560 *copied = vfs_cc_state->copied;
1561 DEBUG(10, ("server side copy chunk copied %lu\n",
1562 (unsigned long)*copied));
1563 tevent_req_received(req);
1565 return NT_STATUS_OK;
1568 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1569 TALLOC_CTX *mem_ctx,
1570 struct files_struct *fsp,
1571 struct smb_filename *smb_fname,
1572 uint16_t *_compression_fmt)
1574 return NT_STATUS_INVALID_DEVICE_REQUEST;
1577 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1578 TALLOC_CTX *mem_ctx,
1579 struct files_struct *fsp,
1580 uint16_t compression_fmt)
1582 return NT_STATUS_INVALID_DEVICE_REQUEST;
1585 /********************************************************************
1586 Given a stat buffer return the allocated size on disk, taking into
1587 account sparse files.
1588 ********************************************************************/
1589 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1590 struct files_struct *fsp,
1591 const SMB_STRUCT_STAT *sbuf)
1595 START_PROFILE(syscall_get_alloc_size);
1597 if(S_ISDIR(sbuf->st_ex_mode)) {
1602 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1603 /* The type of st_blocksize is blkcnt_t which *MUST* be
1604 signed (according to POSIX) and can be less than 64-bits.
1605 Ensure when we're converting to 64 bits wide we don't
1607 #if defined(SIZEOF_BLKCNT_T_8)
1608 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1609 #elif defined(SIZEOF_BLKCNT_T_4)
1611 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1612 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1615 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1619 * Some file systems do not allocate a block for very
1620 * small files. But for non-empty file should report a
1624 uint64_t filesize = get_file_size_stat(sbuf);
1626 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
1630 result = get_file_size_stat(sbuf);
1633 if (fsp && fsp->initial_allocation_size)
1634 result = MAX(result,fsp->initial_allocation_size);
1636 result = smb_roundup(handle->conn, result);
1639 END_PROFILE(syscall_get_alloc_size);
1643 static int vfswrap_unlink(vfs_handle_struct *handle,
1644 const struct smb_filename *smb_fname)
1648 START_PROFILE(syscall_unlink);
1650 if (smb_fname->stream_name) {
1654 result = unlink(smb_fname->base_name);
1657 END_PROFILE(syscall_unlink);
1661 static int vfswrap_chmod(vfs_handle_struct *handle, const char *path, mode_t mode)
1665 START_PROFILE(syscall_chmod);
1668 * We need to do this due to the fact that the default POSIX ACL
1669 * chmod modifies the ACL *mask* for the group owner, not the
1670 * group owner bits directly. JRA.
1675 int saved_errno = errno; /* We might get ENOSYS */
1676 if ((result = SMB_VFS_CHMOD_ACL(handle->conn, path, mode)) == 0) {
1677 END_PROFILE(syscall_chmod);
1680 /* Error - return the old errno. */
1681 errno = saved_errno;
1684 result = chmod(path, mode);
1685 END_PROFILE(syscall_chmod);
1689 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
1693 START_PROFILE(syscall_fchmod);
1696 * We need to do this due to the fact that the default POSIX ACL
1697 * chmod modifies the ACL *mask* for the group owner, not the
1698 * group owner bits directly. JRA.
1702 int saved_errno = errno; /* We might get ENOSYS */
1703 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
1704 END_PROFILE(syscall_fchmod);
1707 /* Error - return the old errno. */
1708 errno = saved_errno;
1711 #if defined(HAVE_FCHMOD)
1712 result = fchmod(fsp->fh->fd, mode);
1718 END_PROFILE(syscall_fchmod);
1722 static int vfswrap_chown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1726 START_PROFILE(syscall_chown);
1727 result = chown(path, uid, gid);
1728 END_PROFILE(syscall_chown);
1732 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
1737 START_PROFILE(syscall_fchown);
1738 result = fchown(fsp->fh->fd, uid, gid);
1739 END_PROFILE(syscall_fchown);
1747 static int vfswrap_lchown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1751 START_PROFILE(syscall_lchown);
1752 result = lchown(path, uid, gid);
1753 END_PROFILE(syscall_lchown);
1757 static int vfswrap_chdir(vfs_handle_struct *handle, const char *path)
1761 START_PROFILE(syscall_chdir);
1762 result = chdir(path);
1763 END_PROFILE(syscall_chdir);
1767 static char *vfswrap_getwd(vfs_handle_struct *handle)
1771 START_PROFILE(syscall_getwd);
1772 result = sys_getwd();
1773 END_PROFILE(syscall_getwd);
1777 /*********************************************************************
1778 nsec timestamp resolution call. Convert down to whatever the underlying
1779 system will support.
1780 **********************************************************************/
1782 static int vfswrap_ntimes(vfs_handle_struct *handle,
1783 const struct smb_filename *smb_fname,
1784 struct smb_file_time *ft)
1788 START_PROFILE(syscall_ntimes);
1790 if (smb_fname->stream_name) {
1796 if (null_timespec(ft->atime)) {
1797 ft->atime= smb_fname->st.st_ex_atime;
1800 if (null_timespec(ft->mtime)) {
1801 ft->mtime = smb_fname->st.st_ex_mtime;
1804 if (!null_timespec(ft->create_time)) {
1805 set_create_timespec_ea(handle->conn,
1810 if ((timespec_compare(&ft->atime,
1811 &smb_fname->st.st_ex_atime) == 0) &&
1812 (timespec_compare(&ft->mtime,
1813 &smb_fname->st.st_ex_mtime) == 0)) {
1818 #if defined(HAVE_UTIMENSAT)
1820 struct timespec ts[2];
1823 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
1825 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
1827 if (!((result == -1) && (errno == ENOSYS))) {
1831 #if defined(HAVE_UTIMES)
1833 struct timeval tv[2];
1834 tv[0] = convert_timespec_to_timeval(ft->atime);
1835 tv[1] = convert_timespec_to_timeval(ft->mtime);
1836 result = utimes(smb_fname->base_name, tv);
1838 result = utimes(smb_fname->base_name, NULL);
1840 if (!((result == -1) && (errno == ENOSYS))) {
1844 #if defined(HAVE_UTIME)
1846 struct utimbuf times;
1847 times.actime = convert_timespec_to_time_t(ft->atime);
1848 times.modtime = convert_timespec_to_time_t(ft->mtime);
1849 result = utime(smb_fname->base_name, ×);
1851 result = utime(smb_fname->base_name, NULL);
1853 if (!((result == -1) && (errno == ENOSYS))) {
1861 END_PROFILE(syscall_ntimes);
1865 /*********************************************************************
1866 A version of ftruncate that will write the space on disk if strict
1868 **********************************************************************/
1870 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1872 off_t space_to_write;
1873 uint64_t space_avail;
1874 uint64_t bsize,dfree,dsize;
1877 SMB_STRUCT_STAT *pst;
1879 status = vfs_stat_fsp(fsp);
1880 if (!NT_STATUS_IS_OK(status)) {
1883 pst = &fsp->fsp_name->st;
1886 if (S_ISFIFO(pst->st_ex_mode))
1890 if (pst->st_ex_size == len)
1893 /* Shrink - just ftruncate. */
1894 if (pst->st_ex_size > len)
1895 return ftruncate(fsp->fh->fd, len);
1897 space_to_write = len - pst->st_ex_size;
1899 /* for allocation try fallocate first. This can fail on some
1900 platforms e.g. when the filesystem doesn't support it and no
1901 emulation is being done by the libc (like on AIX with JFS1). In that
1902 case we do our own emulation. fallocate implementations can
1903 return ENOTSUP or EINVAL in cases like that. */
1904 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
1905 if (ret == -1 && errno == ENOSPC) {
1911 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
1912 "error %d. Falling back to slow manual allocation\n", errno));
1914 /* available disk space is enough or not? */
1915 space_avail = get_dfree_info(fsp->conn,
1916 fsp->fsp_name->base_name,
1917 &bsize, &dfree, &dsize);
1918 /* space_avail is 1k blocks */
1919 if (space_avail == (uint64_t)-1 ||
1920 ((uint64_t)space_to_write/1024 > space_avail) ) {
1925 /* Write out the real space on disk. */
1926 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
1934 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1937 SMB_STRUCT_STAT *pst;
1941 START_PROFILE(syscall_ftruncate);
1943 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
1944 result = strict_allocate_ftruncate(handle, fsp, len);
1945 END_PROFILE(syscall_ftruncate);
1949 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
1950 ftruncate if the system supports it. Then I discovered that
1951 you can have some filesystems that support ftruncate
1952 expansion and some that don't! On Linux fat can't do
1953 ftruncate extend but ext2 can. */
1955 result = ftruncate(fsp->fh->fd, len);
1957 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
1958 extend a file with ftruncate. Provide alternate implementation
1961 /* Do an fstat to see if the file is longer than the requested
1962 size in which case the ftruncate above should have
1963 succeeded or shorter, in which case seek to len - 1 and
1964 write 1 byte of zero */
1965 status = vfs_stat_fsp(fsp);
1966 if (!NT_STATUS_IS_OK(status)) {
1970 /* We need to update the files_struct after successful ftruncate */
1975 pst = &fsp->fsp_name->st;
1978 if (S_ISFIFO(pst->st_ex_mode)) {
1984 if (pst->st_ex_size == len) {
1989 if (pst->st_ex_size > len) {
1990 /* the ftruncate should have worked */
1994 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2002 END_PROFILE(syscall_ftruncate);
2006 static int vfswrap_fallocate(vfs_handle_struct *handle,
2014 START_PROFILE(syscall_fallocate);
2016 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2018 * posix_fallocate returns 0 on success, errno on error
2019 * and doesn't set errno. Make it behave like fallocate()
2020 * which returns -1, and sets errno on failure.
2027 /* sys_fallocate handles filtering of unsupported mode flags */
2028 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2030 END_PROFILE(syscall_fallocate);
2034 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2038 START_PROFILE(syscall_fcntl_lock);
2039 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2040 END_PROFILE(syscall_fcntl_lock);
2044 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2045 uint32_t share_mode, uint32_t access_mask)
2047 START_PROFILE(syscall_kernel_flock);
2048 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2049 END_PROFILE(syscall_kernel_flock);
2053 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2057 START_PROFILE(syscall_fcntl_getlock);
2058 result = fcntl_getlock(fsp->fh->fd, poffset, pcount, ptype, ppid);
2059 END_PROFILE(syscall_fcntl_getlock);
2063 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2068 START_PROFILE(syscall_linux_setlease);
2070 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2071 result = linux_setlease(fsp->fh->fd, leasetype);
2075 END_PROFILE(syscall_linux_setlease);
2079 static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2083 START_PROFILE(syscall_symlink);
2084 result = symlink(oldpath, newpath);
2085 END_PROFILE(syscall_symlink);
2089 static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
2093 START_PROFILE(syscall_readlink);
2094 result = readlink(path, buf, bufsiz);
2095 END_PROFILE(syscall_readlink);
2099 static int vfswrap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2103 START_PROFILE(syscall_link);
2104 result = link(oldpath, newpath);
2105 END_PROFILE(syscall_link);
2109 static int vfswrap_mknod(vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev)
2113 START_PROFILE(syscall_mknod);
2114 result = sys_mknod(pathname, mode, dev);
2115 END_PROFILE(syscall_mknod);
2119 static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
2123 START_PROFILE(syscall_realpath);
2124 #ifdef REALPATH_TAKES_NULL
2125 result = realpath(path, NULL);
2127 result = SMB_MALLOC_ARRAY(char, PATH_MAX+1);
2129 char *resolved_path = realpath(path, result);
2130 if (!resolved_path) {
2133 /* SMB_ASSERT(result == resolved_path) ? */
2134 result = resolved_path;
2138 END_PROFILE(syscall_realpath);
2142 static int vfswrap_chflags(vfs_handle_struct *handle, const char *path,
2146 return chflags(path, flags);
2153 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2154 const SMB_STRUCT_STAT *sbuf)
2158 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2162 key.devid = sbuf->st_ex_dev;
2163 key.inode = sbuf->st_ex_ino;
2164 /* key.extid is unused by default. */
2169 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2170 struct files_struct *fsp,
2172 TALLOC_CTX *mem_ctx,
2173 unsigned int *pnum_streams,
2174 struct stream_struct **pstreams)
2176 SMB_STRUCT_STAT sbuf;
2177 struct stream_struct *tmp_streams = NULL;
2180 if ((fsp != NULL) && (fsp->is_directory)) {
2182 * No default streams on directories
2187 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2188 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2191 struct smb_filename smb_fname;
2193 ZERO_STRUCT(smb_fname);
2194 smb_fname.base_name = discard_const_p(char, fname);
2196 if (lp_posix_pathnames()) {
2197 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname);
2199 ret = SMB_VFS_STAT(handle->conn, &smb_fname);
2201 sbuf = smb_fname.st;
2205 return map_nt_error_from_unix(errno);
2208 if (S_ISDIR(sbuf.st_ex_mode)) {
2212 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2213 (*pnum_streams) + 1);
2214 if (tmp_streams == NULL) {
2215 return NT_STATUS_NO_MEMORY;
2217 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2218 if (tmp_streams[*pnum_streams].name == NULL) {
2219 return NT_STATUS_NO_MEMORY;
2221 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2222 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2225 *pstreams = tmp_streams;
2227 return NT_STATUS_OK;
2230 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2233 TALLOC_CTX *mem_ctx,
2237 * Don't fall back to get_real_filename so callers can differentiate
2238 * between a full directory scan and an actual case-insensitive stat.
2244 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2247 return handle->conn->connectpath;
2250 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2251 struct byte_range_lock *br_lck,
2252 struct lock_struct *plock,
2255 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2257 /* Note: blr is not used in the default implementation. */
2258 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2261 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2262 struct messaging_context *msg_ctx,
2263 struct byte_range_lock *br_lck,
2264 const struct lock_struct *plock)
2266 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2268 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2271 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2272 struct byte_range_lock *br_lck,
2273 struct lock_struct *plock)
2275 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2277 /* Note: blr is not used in the default implementation. */
2278 return brl_lock_cancel_default(br_lck, plock);
2281 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2283 struct lock_struct *plock)
2285 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2286 plock->lock_type == WRITE_LOCK);
2288 return strict_lock_default(fsp, plock);
2291 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2293 struct lock_struct *plock)
2295 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2296 plock->lock_type == WRITE_LOCK);
2298 strict_unlock_default(fsp, plock);
2301 /* NT ACL operations. */
2303 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2305 uint32_t security_info,
2306 TALLOC_CTX *mem_ctx,
2307 struct security_descriptor **ppdesc)
2311 START_PROFILE(fget_nt_acl);
2312 result = posix_fget_nt_acl(fsp, security_info,
2314 END_PROFILE(fget_nt_acl);
2318 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2320 uint32_t security_info,
2321 TALLOC_CTX *mem_ctx,
2322 struct security_descriptor **ppdesc)
2326 START_PROFILE(get_nt_acl);
2327 result = posix_get_nt_acl(handle->conn, name, security_info,
2329 END_PROFILE(get_nt_acl);
2333 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2337 START_PROFILE(fset_nt_acl);
2338 result = set_nt_acl(fsp, security_info_sent, psd);
2339 END_PROFILE(fset_nt_acl);
2343 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2344 struct smb_filename *file,
2345 struct security_acl *sacl,
2346 uint32_t access_requested,
2347 uint32_t access_denied)
2349 return NT_STATUS_OK; /* Nothing to do here ... */
2352 static int vfswrap_chmod_acl(vfs_handle_struct *handle, const char *name, mode_t mode)
2360 START_PROFILE(chmod_acl);
2361 result = chmod_acl(handle->conn, name, mode);
2362 END_PROFILE(chmod_acl);
2367 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2375 START_PROFILE(fchmod_acl);
2376 result = fchmod_acl(fsp, mode);
2377 END_PROFILE(fchmod_acl);
2382 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2384 SMB_ACL_TYPE_T type,
2385 TALLOC_CTX *mem_ctx)
2387 return sys_acl_get_file(handle, path_p, type, mem_ctx);
2390 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2392 TALLOC_CTX *mem_ctx)
2394 return sys_acl_get_fd(handle, fsp, mem_ctx);
2397 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2399 return sys_acl_set_file(handle, name, acltype, theacl);
2402 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2404 return sys_acl_set_fd(handle, fsp, theacl);
2407 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
2409 return sys_acl_delete_def_file(handle, path);
2412 /****************************************************************
2413 Extended attribute operations.
2414 *****************************************************************/
2416 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
2418 return getxattr(path, name, value, size);
2421 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2423 return fgetxattr(fsp->fh->fd, name, value, size);
2426 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
2428 return listxattr(path, list, size);
2431 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2433 return flistxattr(fsp->fh->fd, list, size);
2436 static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
2438 return removexattr(path, name);
2441 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2443 return fremovexattr(fsp->fh->fd, name);
2446 static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
2448 return setxattr(path, name, value, size, flags);
2451 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2453 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2456 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2461 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2462 const struct smb_filename *fname,
2463 SMB_STRUCT_STAT *sbuf)
2467 bool offline = false;
2469 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2473 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2474 #if defined(ENOTSUP)
2480 status = get_full_smb_filename(talloc_tos(), fname, &path);
2481 if (!NT_STATUS_IS_OK(status)) {
2482 errno = map_errno_from_nt_status(status);
2486 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2493 static int vfswrap_set_offline(struct vfs_handle_struct *handle,
2494 const struct smb_filename *fname)
2496 /* We don't know how to set offline bit by default, needs to be overriden in the vfs modules */
2497 #if defined(ENOTSUP)
2503 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2504 struct files_struct *fsp,
2505 TALLOC_CTX *mem_ctx,
2508 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2511 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2512 struct files_struct *fsp,
2513 const DATA_BLOB old_cookie,
2514 TALLOC_CTX *mem_ctx,
2515 DATA_BLOB *new_cookie)
2517 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2521 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2522 struct smb_request *smb1req,
2523 struct smbXsrv_open *op,
2524 const DATA_BLOB old_cookie,
2525 TALLOC_CTX *mem_ctx,
2526 struct files_struct **fsp,
2527 DATA_BLOB *new_cookie)
2529 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2530 old_cookie, mem_ctx,
2534 static struct vfs_fn_pointers vfs_default_fns = {
2535 /* Disk operations */
2537 .connect_fn = vfswrap_connect,
2538 .disconnect_fn = vfswrap_disconnect,
2539 .disk_free_fn = vfswrap_disk_free,
2540 .get_quota_fn = vfswrap_get_quota,
2541 .set_quota_fn = vfswrap_set_quota,
2542 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2543 .statvfs_fn = vfswrap_statvfs,
2544 .fs_capabilities_fn = vfswrap_fs_capabilities,
2545 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2546 .snap_check_path_fn = vfswrap_snap_check_path,
2547 .snap_create_fn = vfswrap_snap_create,
2548 .snap_delete_fn = vfswrap_snap_delete,
2550 /* Directory operations */
2552 .opendir_fn = vfswrap_opendir,
2553 .fdopendir_fn = vfswrap_fdopendir,
2554 .readdir_fn = vfswrap_readdir,
2555 .readdir_attr_fn = vfswrap_readdir_attr,
2556 .seekdir_fn = vfswrap_seekdir,
2557 .telldir_fn = vfswrap_telldir,
2558 .rewind_dir_fn = vfswrap_rewinddir,
2559 .mkdir_fn = vfswrap_mkdir,
2560 .rmdir_fn = vfswrap_rmdir,
2561 .closedir_fn = vfswrap_closedir,
2562 .init_search_op_fn = vfswrap_init_search_op,
2564 /* File operations */
2566 .open_fn = vfswrap_open,
2567 .create_file_fn = vfswrap_create_file,
2568 .close_fn = vfswrap_close,
2569 .read_fn = vfswrap_read,
2570 .pread_fn = vfswrap_pread,
2571 .pread_send_fn = vfswrap_pread_send,
2572 .pread_recv_fn = vfswrap_asys_ssize_t_recv,
2573 .write_fn = vfswrap_write,
2574 .pwrite_fn = vfswrap_pwrite,
2575 .pwrite_send_fn = vfswrap_pwrite_send,
2576 .pwrite_recv_fn = vfswrap_asys_ssize_t_recv,
2577 .lseek_fn = vfswrap_lseek,
2578 .sendfile_fn = vfswrap_sendfile,
2579 .recvfile_fn = vfswrap_recvfile,
2580 .rename_fn = vfswrap_rename,
2581 .fsync_fn = vfswrap_fsync,
2582 .fsync_send_fn = vfswrap_fsync_send,
2583 .fsync_recv_fn = vfswrap_asys_int_recv,
2584 .stat_fn = vfswrap_stat,
2585 .fstat_fn = vfswrap_fstat,
2586 .lstat_fn = vfswrap_lstat,
2587 .get_alloc_size_fn = vfswrap_get_alloc_size,
2588 .unlink_fn = vfswrap_unlink,
2589 .chmod_fn = vfswrap_chmod,
2590 .fchmod_fn = vfswrap_fchmod,
2591 .chown_fn = vfswrap_chown,
2592 .fchown_fn = vfswrap_fchown,
2593 .lchown_fn = vfswrap_lchown,
2594 .chdir_fn = vfswrap_chdir,
2595 .getwd_fn = vfswrap_getwd,
2596 .ntimes_fn = vfswrap_ntimes,
2597 .ftruncate_fn = vfswrap_ftruncate,
2598 .fallocate_fn = vfswrap_fallocate,
2599 .lock_fn = vfswrap_lock,
2600 .kernel_flock_fn = vfswrap_kernel_flock,
2601 .linux_setlease_fn = vfswrap_linux_setlease,
2602 .getlock_fn = vfswrap_getlock,
2603 .symlink_fn = vfswrap_symlink,
2604 .readlink_fn = vfswrap_readlink,
2605 .link_fn = vfswrap_link,
2606 .mknod_fn = vfswrap_mknod,
2607 .realpath_fn = vfswrap_realpath,
2608 .chflags_fn = vfswrap_chflags,
2609 .file_id_create_fn = vfswrap_file_id_create,
2610 .streaminfo_fn = vfswrap_streaminfo,
2611 .get_real_filename_fn = vfswrap_get_real_filename,
2612 .connectpath_fn = vfswrap_connectpath,
2613 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2614 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2615 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2616 .strict_lock_fn = vfswrap_strict_lock,
2617 .strict_unlock_fn = vfswrap_strict_unlock,
2618 .translate_name_fn = vfswrap_translate_name,
2619 .fsctl_fn = vfswrap_fsctl,
2620 .copy_chunk_send_fn = vfswrap_copy_chunk_send,
2621 .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
2622 .get_compression_fn = vfswrap_get_compression,
2623 .set_compression_fn = vfswrap_set_compression,
2625 /* NT ACL operations. */
2627 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2628 .get_nt_acl_fn = vfswrap_get_nt_acl,
2629 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2630 .audit_file_fn = vfswrap_audit_file,
2632 /* POSIX ACL operations. */
2634 .chmod_acl_fn = vfswrap_chmod_acl,
2635 .fchmod_acl_fn = vfswrap_fchmod_acl,
2637 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2638 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2639 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2640 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2641 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2642 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2643 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2645 /* EA operations. */
2646 .getxattr_fn = vfswrap_getxattr,
2647 .fgetxattr_fn = vfswrap_fgetxattr,
2648 .listxattr_fn = vfswrap_listxattr,
2649 .flistxattr_fn = vfswrap_flistxattr,
2650 .removexattr_fn = vfswrap_removexattr,
2651 .fremovexattr_fn = vfswrap_fremovexattr,
2652 .setxattr_fn = vfswrap_setxattr,
2653 .fsetxattr_fn = vfswrap_fsetxattr,
2655 /* aio operations */
2656 .aio_force_fn = vfswrap_aio_force,
2658 /* offline operations */
2659 .is_offline_fn = vfswrap_is_offline,
2660 .set_offline_fn = vfswrap_set_offline,
2662 /* durable handle operations */
2663 .durable_cookie_fn = vfswrap_durable_cookie,
2664 .durable_disconnect_fn = vfswrap_durable_disconnect,
2665 .durable_reconnect_fn = vfswrap_durable_reconnect,
2668 NTSTATUS vfs_default_init(void);
2669 NTSTATUS vfs_default_init(void)
2671 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
2672 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);