2 Unix SMB/CIFS implementation.
3 Wrap disk only vfs functions to sidestep dodgy compilers.
4 Copyright (C) Tim Potter 1998
5 Copyright (C) Jeremy Allison 2007
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "system/time.h"
23 #include "system/filesys.h"
24 #include "smbd/smbd.h"
25 #include "smbd/globals.h"
27 #include "smbprofile.h"
28 #include "../libcli/security/security.h"
29 #include "passdb/lookup_sid.h"
30 #include "source3/include/msdfs.h"
31 #include "librpc/gen_ndr/ndr_dfsblobs.h"
32 #include "lib/util/tevent_unix.h"
33 #include "lib/asys/asys.h"
34 #include "lib/util/tevent_ntstatus.h"
35 #include "lib/util/sys_rw.h"
38 #define DBGC_CLASS DBGC_VFS
40 /* Check for NULL pointer parameters in vfswrap_* functions */
42 /* We don't want to have NULL function pointers lying around. Someone
43 is sure to try and execute them. These stubs are used to prevent
46 static int vfswrap_connect(vfs_handle_struct *handle, const char *service, const char *user)
48 return 0; /* Return >= 0 for success */
51 static void vfswrap_disconnect(vfs_handle_struct *handle)
57 static uint64_t vfswrap_disk_free(vfs_handle_struct *handle, const char *path,
58 uint64_t *bsize, uint64_t *dfree,
61 if (sys_fsusage(path, dfree, dsize) != 0) {
69 static int vfswrap_get_quota(struct vfs_handle_struct *handle, const char *path,
70 enum SMB_QUOTA_TYPE qtype, unid_t id,
73 #ifdef HAVE_SYS_QUOTAS
76 START_PROFILE(syscall_get_quota);
77 result = sys_get_quota(path, qtype, id, qt);
78 END_PROFILE(syscall_get_quota);
86 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
88 #ifdef HAVE_SYS_QUOTAS
91 START_PROFILE(syscall_set_quota);
92 result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
93 END_PROFILE(syscall_set_quota);
101 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
102 struct files_struct *fsp,
103 struct shadow_copy_data *shadow_copy_data,
107 return -1; /* Not implemented. */
110 static int vfswrap_statvfs(struct vfs_handle_struct *handle, const char *path, vfs_statvfs_struct *statbuf)
112 return sys_statvfs(path, statbuf);
115 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
116 enum timestamp_set_resolution *p_ts_res)
118 connection_struct *conn = handle->conn;
119 uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
120 struct smb_filename *smb_fname_cpath = NULL;
121 struct vfs_statvfs_struct statbuf;
124 ZERO_STRUCT(statbuf);
125 ret = sys_statvfs(conn->connectpath, &statbuf);
127 caps = statbuf.FsCapabilities;
130 *p_ts_res = TIMESTAMP_SET_SECONDS;
132 /* Work out what timestamp resolution we can
133 * use when setting a timestamp. */
135 smb_fname_cpath = synthetic_smb_fname(talloc_tos(), conn->connectpath,
137 if (smb_fname_cpath == NULL) {
141 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
143 TALLOC_FREE(smb_fname_cpath);
147 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
148 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
149 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
150 /* If any of the normal UNIX directory timestamps
151 * have a non-zero tv_nsec component assume
152 * we might be able to set sub-second timestamps.
153 * See what filetime set primitives we have.
155 #if defined(HAVE_UTIMENSAT)
156 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
157 #elif defined(HAVE_UTIMES)
158 /* utimes allows msec timestamps to be set. */
159 *p_ts_res = TIMESTAMP_SET_MSEC;
160 #elif defined(HAVE_UTIME)
161 /* utime only allows sec timestamps to be set. */
162 *p_ts_res = TIMESTAMP_SET_SECONDS;
165 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
167 "available on share %s, directory %s\n",
168 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
169 lp_servicename(talloc_tos(), conn->params->service),
170 conn->connectpath ));
172 TALLOC_FREE(smb_fname_cpath);
176 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
177 struct dfs_GetDFSReferral *r)
179 struct junction_map *junction = NULL;
181 bool self_referral = false;
182 char *pathnamep = NULL;
183 char *local_dfs_path = NULL;
186 uint16_t max_referral_level = r->in.req.max_referral_level;
189 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
192 /* get the junction entry */
193 if (r->in.req.servername == NULL) {
194 return NT_STATUS_NOT_FOUND;
198 * Trim pathname sent by client so it begins with only one backslash.
199 * Two backslashes confuse some dfs clients
202 local_dfs_path = talloc_strdup(r, r->in.req.servername);
203 if (local_dfs_path == NULL) {
204 return NT_STATUS_NO_MEMORY;
206 pathnamep = local_dfs_path;
207 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
208 IS_DIRECTORY_SEP(pathnamep[1])) {
212 junction = talloc_zero(r, struct junction_map);
213 if (junction == NULL) {
214 return NT_STATUS_NO_MEMORY;
217 /* The following call can change cwd. */
218 status = get_referred_path(r, pathnamep,
219 !handle->conn->sconn->using_smb2,
220 junction, &consumedcnt, &self_referral);
221 if (!NT_STATUS_IS_OK(status)) {
222 vfs_ChDir(handle->conn, handle->conn->connectpath);
225 vfs_ChDir(handle->conn, handle->conn->connectpath);
227 if (!self_referral) {
228 pathnamep[consumedcnt] = '\0';
231 dbgtext("Path %s to alternate path(s):",
233 for (i=0; i < junction->referral_count; i++) {
235 junction->referral_list[i].alternate_path);
241 if (r->in.req.max_referral_level <= 2) {
242 max_referral_level = 2;
244 if (r->in.req.max_referral_level >= 3) {
245 max_referral_level = 3;
248 r->out.resp = talloc_zero(r, struct dfs_referral_resp);
249 if (r->out.resp == NULL) {
250 return NT_STATUS_NO_MEMORY;
253 r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
254 r->out.resp->nb_referrals = junction->referral_count;
256 r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
258 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
261 r->out.resp->referral_entries = talloc_zero_array(r,
262 struct dfs_referral_type,
263 r->out.resp->nb_referrals);
264 if (r->out.resp->referral_entries == NULL) {
265 return NT_STATUS_NO_MEMORY;
268 switch (max_referral_level) {
270 for(i=0; i < junction->referral_count; i++) {
271 struct referral *ref = &junction->referral_list[i];
272 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
273 struct dfs_referral_type *t =
274 &r->out.resp->referral_entries[i];
275 struct dfs_referral_v2 *v2 = &t->referral.v2;
278 v2->size = VERSION2_REFERRAL_SIZE;
280 v2->server_type = DFS_SERVER_ROOT;
282 v2->server_type = DFS_SERVER_NON_ROOT;
285 v2->proximity = ref->proximity;
287 v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
288 if (v2->DFS_path == NULL) {
289 return NT_STATUS_NO_MEMORY;
291 v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
292 if (v2->DFS_alt_path == NULL) {
293 return NT_STATUS_NO_MEMORY;
295 v2->netw_address = talloc_strdup(mem_ctx,
296 ref->alternate_path);
297 if (v2->netw_address == NULL) {
298 return NT_STATUS_NO_MEMORY;
304 for(i=0; i < junction->referral_count; i++) {
305 struct referral *ref = &junction->referral_list[i];
306 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
307 struct dfs_referral_type *t =
308 &r->out.resp->referral_entries[i];
309 struct dfs_referral_v3 *v3 = &t->referral.v3;
310 struct dfs_normal_referral *r1 = &v3->referrals.r1;
313 v3->size = VERSION3_REFERRAL_SIZE;
315 v3->server_type = DFS_SERVER_ROOT;
317 v3->server_type = DFS_SERVER_NON_ROOT;
321 r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
322 if (r1->DFS_path == NULL) {
323 return NT_STATUS_NO_MEMORY;
325 r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
326 if (r1->DFS_alt_path == NULL) {
327 return NT_STATUS_NO_MEMORY;
329 r1->netw_address = talloc_strdup(mem_ctx,
330 ref->alternate_path);
331 if (r1->netw_address == NULL) {
332 return NT_STATUS_NO_MEMORY;
337 DEBUG(0,("Invalid dfs referral version: %d\n",
338 max_referral_level));
339 return NT_STATUS_INVALID_LEVEL;
343 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
349 static NTSTATUS vfswrap_snap_check_path(struct vfs_handle_struct *handle,
351 const char *service_path,
354 return NT_STATUS_NOT_SUPPORTED;
357 static NTSTATUS vfswrap_snap_create(struct vfs_handle_struct *handle,
359 const char *base_volume,
365 return NT_STATUS_NOT_SUPPORTED;
368 static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle,
373 return NT_STATUS_NOT_SUPPORTED;
376 /* Directory operations */
378 static DIR *vfswrap_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32_t attr)
382 START_PROFILE(syscall_opendir);
383 result = opendir(fname);
384 END_PROFILE(syscall_opendir);
388 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
395 START_PROFILE(syscall_fdopendir);
396 result = sys_fdopendir(fsp->fh->fd);
397 END_PROFILE(syscall_fdopendir);
402 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
404 SMB_STRUCT_STAT *sbuf)
406 struct dirent *result;
408 START_PROFILE(syscall_readdir);
409 result = readdir(dirp);
410 END_PROFILE(syscall_readdir);
412 /* Default Posix readdir() does not give us stat info.
413 * Set to invalid to indicate we didn't return this info. */
414 SET_STAT_INVALID(*sbuf);
415 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
416 if (result != NULL) {
417 /* See if we can efficiently return this. */
419 int flags = (lp_posix_pathnames() ?
420 AT_SYMLINK_NOFOLLOW : 0);
421 int ret = fstatat(dirfd(dirp),
426 init_stat_ex_from_stat(sbuf,
428 lp_fake_directory_create_times(
429 SNUM(handle->conn)));
437 static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
438 const struct smb_filename *fname,
440 struct readdir_attr_data **attr_data)
442 return NT_STATUS_NOT_SUPPORTED;
445 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
447 START_PROFILE(syscall_seekdir);
448 seekdir(dirp, offset);
449 END_PROFILE(syscall_seekdir);
452 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
455 START_PROFILE(syscall_telldir);
456 result = telldir(dirp);
457 END_PROFILE(syscall_telldir);
461 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
463 START_PROFILE(syscall_rewinddir);
465 END_PROFILE(syscall_rewinddir);
468 static int vfswrap_mkdir(vfs_handle_struct *handle, const char *path, mode_t mode)
471 bool has_dacl = False;
474 START_PROFILE(syscall_mkdir);
476 if (lp_inherit_acls(SNUM(handle->conn))
477 && parent_dirname(talloc_tos(), path, &parent, NULL)
478 && (has_dacl = directory_has_default_acl(handle->conn, parent))) {
479 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
484 result = mkdir(path, mode);
486 if (result == 0 && !has_dacl) {
488 * We need to do this as the default behavior of POSIX ACLs
489 * is to set the mask to be the requested group permission
490 * bits, not the group permission bits to be the requested
491 * group permission bits. This is not what we want, as it will
492 * mess up any inherited ACL bits that were set. JRA.
494 int saved_errno = errno; /* We may get ENOSYS */
495 if ((SMB_VFS_CHMOD_ACL(handle->conn, path, mode) == -1) && (errno == ENOSYS))
499 END_PROFILE(syscall_mkdir);
503 static int vfswrap_rmdir(vfs_handle_struct *handle, const char *path)
507 START_PROFILE(syscall_rmdir);
508 result = rmdir(path);
509 END_PROFILE(syscall_rmdir);
513 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
517 START_PROFILE(syscall_closedir);
518 result = closedir(dirp);
519 END_PROFILE(syscall_closedir);
523 static void vfswrap_init_search_op(vfs_handle_struct *handle,
526 /* Default behavior is a NOOP */
529 /* File operations */
531 static int vfswrap_open(vfs_handle_struct *handle,
532 struct smb_filename *smb_fname,
533 files_struct *fsp, int flags, mode_t mode)
537 START_PROFILE(syscall_open);
539 if (smb_fname->stream_name) {
544 result = open(smb_fname->base_name, flags, mode);
546 END_PROFILE(syscall_open);
550 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
551 struct smb_request *req,
552 uint16_t root_dir_fid,
553 struct smb_filename *smb_fname,
554 uint32_t access_mask,
555 uint32_t share_access,
556 uint32_t create_disposition,
557 uint32_t create_options,
558 uint32_t file_attributes,
559 uint32_t oplock_request,
560 struct smb2_lease *lease,
561 uint64_t allocation_size,
562 uint32_t private_flags,
563 struct security_descriptor *sd,
564 struct ea_list *ea_list,
565 files_struct **result,
567 const struct smb2_create_blobs *in_context_blobs,
568 struct smb2_create_blobs *out_context_blobs)
570 struct smb2_create_blob *svhdx = NULL;
573 * It might be empty ... and smb2_create_blob_find does not handle that
575 if (in_context_blobs) {
576 svhdx = smb2_create_blob_find(in_context_blobs,
577 SVHDX_OPEN_DEVICE_CONTEXT);
581 /* SharedVHD is not yet supported */
582 DEBUG(10, ("Shared VHD not yet supported, INVALID_DEVICE_REQUEST\n"));
583 return NT_STATUS_INVALID_DEVICE_REQUEST;
586 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
587 access_mask, share_access,
588 create_disposition, create_options,
589 file_attributes, oplock_request, lease,
590 allocation_size, private_flags,
592 pinfo, in_context_blobs, out_context_blobs);
595 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
599 START_PROFILE(syscall_close);
600 result = fd_close_posix(fsp);
601 END_PROFILE(syscall_close);
605 static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
609 START_PROFILE_BYTES(syscall_read, n);
610 result = sys_read(fsp->fh->fd, data, n);
611 END_PROFILE_BYTES(syscall_read);
615 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
616 size_t n, off_t offset)
620 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
621 START_PROFILE_BYTES(syscall_pread, n);
622 result = sys_pread(fsp->fh->fd, data, n, offset);
623 END_PROFILE_BYTES(syscall_pread);
625 if (result == -1 && errno == ESPIPE) {
626 /* Maintain the fiction that pipes can be seeked (sought?) on. */
627 result = SMB_VFS_READ(fsp, data, n);
631 #else /* HAVE_PREAD */
635 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
636 if (curr == -1 && errno == ESPIPE) {
637 /* Maintain the fiction that pipes can be seeked (sought?) on. */
638 result = SMB_VFS_READ(fsp, data, n);
643 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
648 result = SMB_VFS_READ(fsp, data, n);
651 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
654 #endif /* HAVE_PREAD */
659 static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
663 START_PROFILE_BYTES(syscall_write, n);
664 result = sys_write(fsp->fh->fd, data, n);
665 END_PROFILE_BYTES(syscall_write);
669 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
670 size_t n, off_t offset)
674 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
675 START_PROFILE_BYTES(syscall_pwrite, n);
676 result = sys_pwrite(fsp->fh->fd, data, n, offset);
677 END_PROFILE_BYTES(syscall_pwrite);
679 if (result == -1 && errno == ESPIPE) {
680 /* Maintain the fiction that pipes can be sought on. */
681 result = SMB_VFS_WRITE(fsp, data, n);
684 #else /* HAVE_PWRITE */
688 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
693 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
697 result = SMB_VFS_WRITE(fsp, data, n);
700 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
703 #endif /* HAVE_PWRITE */
708 static void vfswrap_asys_finished(struct tevent_context *ev,
709 struct tevent_fd *fde,
710 uint16_t flags, void *p);
712 static bool vfswrap_init_asys_ctx(struct smbd_server_connection *conn)
714 struct asys_context *ctx;
715 struct tevent_fd *fde;
719 if (conn->asys_ctx != NULL) {
723 ret = asys_context_init(&ctx, lp_aio_max_threads());
725 DEBUG(1, ("asys_context_init failed: %s\n", strerror(ret)));
729 fd = asys_signalfd(ctx);
731 ret = set_blocking(fd, false);
733 DBG_WARNING("set_blocking failed: %s\n", strerror(errno));
737 fde = tevent_add_fd(conn->ev_ctx, conn, fd, TEVENT_FD_READ,
738 vfswrap_asys_finished, ctx);
740 DEBUG(1, ("tevent_add_fd failed\n"));
744 conn->asys_ctx = ctx;
745 conn->asys_fde = fde;
749 asys_context_destroy(ctx);
753 struct vfswrap_asys_state {
754 struct asys_context *asys_ctx;
755 struct tevent_req *req;
758 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
759 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
762 static int vfswrap_asys_state_destructor(struct vfswrap_asys_state *s)
764 asys_cancel(s->asys_ctx, s->req);
768 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
770 struct tevent_context *ev,
771 struct files_struct *fsp,
773 size_t n, off_t offset)
775 struct tevent_req *req;
776 struct vfswrap_asys_state *state;
779 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
783 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
785 return tevent_req_post(req, ev);
787 state->asys_ctx = handle->conn->sconn->asys_ctx;
790 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
791 state->profile_bytes, n);
792 ret = asys_pread(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
794 tevent_req_error(req, ret);
795 return tevent_req_post(req, ev);
797 talloc_set_destructor(state, vfswrap_asys_state_destructor);
802 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
804 struct tevent_context *ev,
805 struct files_struct *fsp,
807 size_t n, off_t offset)
809 struct tevent_req *req;
810 struct vfswrap_asys_state *state;
813 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
817 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
819 return tevent_req_post(req, ev);
821 state->asys_ctx = handle->conn->sconn->asys_ctx;
824 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
825 state->profile_bytes, n);
826 ret = asys_pwrite(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
828 tevent_req_error(req, ret);
829 return tevent_req_post(req, ev);
831 talloc_set_destructor(state, vfswrap_asys_state_destructor);
836 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
838 struct tevent_context *ev,
839 struct files_struct *fsp)
841 struct tevent_req *req;
842 struct vfswrap_asys_state *state;
845 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
849 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
851 return tevent_req_post(req, ev);
853 state->asys_ctx = handle->conn->sconn->asys_ctx;
856 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
857 state->profile_basic);
858 ret = asys_fsync(state->asys_ctx, fsp->fh->fd, req);
860 tevent_req_error(req, ret);
861 return tevent_req_post(req, ev);
863 talloc_set_destructor(state, vfswrap_asys_state_destructor);
868 static void vfswrap_asys_finished(struct tevent_context *ev,
869 struct tevent_fd *fde,
870 uint16_t flags, void *p)
872 struct asys_context *asys_ctx = (struct asys_context *)p;
873 struct asys_result results[get_outstanding_aio_calls()];
876 if ((flags & TEVENT_FD_READ) == 0) {
880 ret = asys_results(asys_ctx, results, get_outstanding_aio_calls());
882 DEBUG(1, ("asys_results returned %s\n", strerror(-ret)));
886 for (i=0; i<ret; i++) {
887 struct asys_result *result = &results[i];
888 struct tevent_req *req;
889 struct vfswrap_asys_state *state;
891 if ((result->ret == -1) && (result->err == ECANCELED)) {
895 req = talloc_get_type_abort(result->private_data,
897 state = tevent_req_data(req, struct vfswrap_asys_state);
899 talloc_set_destructor(state, NULL);
901 SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
902 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
903 state->ret = result->ret;
904 state->err = result->err;
905 tevent_req_defer_callback(req, ev);
906 tevent_req_done(req);
910 static ssize_t vfswrap_asys_ssize_t_recv(struct tevent_req *req, int *err)
912 struct vfswrap_asys_state *state = tevent_req_data(
913 req, struct vfswrap_asys_state);
915 if (tevent_req_is_unix_error(req, err)) {
922 static int vfswrap_asys_int_recv(struct tevent_req *req, int *err)
924 struct vfswrap_asys_state *state = tevent_req_data(
925 req, struct vfswrap_asys_state);
927 if (tevent_req_is_unix_error(req, err)) {
934 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
938 START_PROFILE(syscall_lseek);
940 /* Cope with 'stat' file opens. */
941 if (fsp->fh->fd != -1)
942 result = lseek(fsp->fh->fd, offset, whence);
945 * We want to maintain the fiction that we can seek
946 * on a fifo for file system purposes. This allows
947 * people to set up UNIX fifo's that feed data to Windows
951 if((result == -1) && (errno == ESPIPE)) {
956 END_PROFILE(syscall_lseek);
960 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
961 off_t offset, size_t n)
965 START_PROFILE_BYTES(syscall_sendfile, n);
966 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
967 END_PROFILE_BYTES(syscall_sendfile);
971 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
979 START_PROFILE_BYTES(syscall_recvfile, n);
980 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
981 END_PROFILE_BYTES(syscall_recvfile);
985 static int vfswrap_rename(vfs_handle_struct *handle,
986 const struct smb_filename *smb_fname_src,
987 const struct smb_filename *smb_fname_dst)
991 START_PROFILE(syscall_rename);
993 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
998 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
1001 END_PROFILE(syscall_rename);
1005 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
1010 START_PROFILE(syscall_fsync);
1011 result = fsync(fsp->fh->fd);
1012 END_PROFILE(syscall_fsync);
1019 static int vfswrap_stat(vfs_handle_struct *handle,
1020 struct smb_filename *smb_fname)
1024 START_PROFILE(syscall_stat);
1026 if (smb_fname->stream_name) {
1031 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1032 lp_fake_directory_create_times(SNUM(handle->conn)));
1034 END_PROFILE(syscall_stat);
1038 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1042 START_PROFILE(syscall_fstat);
1043 result = sys_fstat(fsp->fh->fd,
1044 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1045 END_PROFILE(syscall_fstat);
1049 static int vfswrap_lstat(vfs_handle_struct *handle,
1050 struct smb_filename *smb_fname)
1054 START_PROFILE(syscall_lstat);
1056 if (smb_fname->stream_name) {
1061 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1062 lp_fake_directory_create_times(SNUM(handle->conn)));
1064 END_PROFILE(syscall_lstat);
1068 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1070 enum vfs_translate_direction direction,
1071 TALLOC_CTX *mem_ctx,
1074 return NT_STATUS_NONE_MAPPED;
1078 * Implement the default fsctl operation.
1080 static bool vfswrap_logged_ioctl_message = false;
1082 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1083 struct files_struct *fsp,
1086 uint16_t req_flags, /* Needed for UNICODE ... */
1087 const uint8_t *_in_data,
1089 uint8_t **_out_data,
1090 uint32_t max_out_len,
1093 const char *in_data = (const char *)_in_data;
1094 char **out_data = (char **)_out_data;
1098 case FSCTL_SET_SPARSE:
1100 bool set_sparse = true;
1102 if (in_len >= 1 && in_data[0] == 0) {
1106 status = file_set_sparse(handle->conn, fsp, set_sparse);
1108 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1109 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1110 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1111 nt_errstr(status)));
1116 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1118 unsigned char objid[16];
1119 char *return_data = NULL;
1121 /* This should return the object-id on this file.
1122 * I think I'll make this be the inode+dev. JRA.
1125 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1126 fsp_fnum_dbg(fsp)));
1128 *out_len = MIN(max_out_len, 64);
1130 /* Hmmm, will this cause problems if less data asked for? */
1131 return_data = talloc_array(ctx, char, 64);
1132 if (return_data == NULL) {
1133 return NT_STATUS_NO_MEMORY;
1136 /* For backwards compatibility only store the dev/inode. */
1137 push_file_id_16(return_data, &fsp->file_id);
1138 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1139 push_file_id_16(return_data+32, &fsp->file_id);
1140 memset(return_data+48, 0, 16);
1141 *out_data = return_data;
1142 return NT_STATUS_OK;
1145 case FSCTL_GET_REPARSE_POINT:
1147 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1148 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1149 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1150 return NT_STATUS_NOT_A_REPARSE_POINT;
1153 case FSCTL_SET_REPARSE_POINT:
1155 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1156 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1157 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1158 return NT_STATUS_NOT_A_REPARSE_POINT;
1161 case FSCTL_GET_SHADOW_COPY_DATA:
1164 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1165 * and return their volume names. If max_data_count is 16, then it is just
1166 * asking for the number of volumes and length of the combined names.
1168 * pdata is the data allocated by our caller, but that uses
1169 * total_data_count (which is 0 in our case) rather than max_data_count.
1170 * Allocate the correct amount and return the pointer to let
1171 * it be deallocated when we return.
1173 struct shadow_copy_data *shadow_data = NULL;
1174 bool labels = False;
1175 uint32_t labels_data_count = 0;
1177 char *cur_pdata = NULL;
1179 if (max_out_len < 16) {
1180 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1182 return NT_STATUS_INVALID_PARAMETER;
1185 if (max_out_len > 16) {
1189 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1190 if (shadow_data == NULL) {
1191 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1192 return NT_STATUS_NO_MEMORY;
1196 * Call the VFS routine to actually do the work.
1198 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1201 /* broken module didn't set errno on error */
1202 status = NT_STATUS_UNSUCCESSFUL;
1204 status = map_nt_error_from_unix(errno);
1205 if (NT_STATUS_EQUAL(status,
1206 NT_STATUS_NOT_SUPPORTED)) {
1210 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1211 "connectpath %s, failed - %s.\n",
1212 fsp->conn->connectpath,
1213 nt_errstr(status)));
1214 TALLOC_FREE(shadow_data);
1218 labels_data_count = (shadow_data->num_volumes * 2 *
1219 sizeof(SHADOW_COPY_LABEL)) + 2;
1224 *out_len = 12 + labels_data_count;
1227 if (max_out_len < *out_len) {
1228 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1229 max_out_len, *out_len));
1230 TALLOC_FREE(shadow_data);
1231 return NT_STATUS_BUFFER_TOO_SMALL;
1234 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1235 if (cur_pdata == NULL) {
1236 TALLOC_FREE(shadow_data);
1237 return NT_STATUS_NO_MEMORY;
1240 *out_data = cur_pdata;
1242 /* num_volumes 4 bytes */
1243 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1246 /* num_labels 4 bytes */
1247 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1250 /* needed_data_count 4 bytes */
1251 SIVAL(cur_pdata, 8, labels_data_count);
1255 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1256 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1257 if (labels && shadow_data->labels) {
1258 for (i=0; i<shadow_data->num_volumes; i++) {
1260 status = srvstr_push(cur_pdata, req_flags,
1261 cur_pdata, shadow_data->labels[i],
1262 2 * sizeof(SHADOW_COPY_LABEL),
1263 STR_UNICODE|STR_TERMINATE, &len);
1264 if (!NT_STATUS_IS_OK(status)) {
1265 TALLOC_FREE(*out_data);
1266 TALLOC_FREE(shadow_data);
1269 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1270 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1274 TALLOC_FREE(shadow_data);
1276 return NT_STATUS_OK;
1279 case FSCTL_FIND_FILES_BY_SID:
1281 /* pretend this succeeded -
1283 * we have to send back a list with all files owned by this SID
1285 * but I have to check that --metze
1291 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1292 fsp_fnum_dbg(fsp)));
1295 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1296 return NT_STATUS_INVALID_PARAMETER;
1299 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1301 /* unknown 4 bytes: this is not the length of the sid :-( */
1302 /*unknown = IVAL(pdata,0);*/
1304 if (!sid_parse(_in_data + 4, sid_len, &sid)) {
1305 return NT_STATUS_INVALID_PARAMETER;
1307 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1309 if (!sid_to_uid(&sid, &uid)) {
1310 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1311 sid_string_dbg(&sid),
1312 (unsigned long)sid_len));
1316 /* we can take a look at the find source :-)
1318 * find ./ -uid $uid -name '*' is what we need here
1321 * and send 4bytes len and then NULL terminated unicode strings
1324 * but I don't know how to deal with the paged results
1325 * (maybe we can hang the result anywhere in the fsp struct)
1327 * but I don't know how to deal with the paged results
1328 * (maybe we can hang the result anywhere in the fsp struct)
1330 * we don't send all files at once
1331 * and at the next we should *not* start from the beginning,
1332 * so we have to cache the result
1337 /* this works for now... */
1338 return NT_STATUS_OK;
1341 case FSCTL_QUERY_ALLOCATED_RANGES:
1343 /* FIXME: This is just a dummy reply, telling that all of the
1344 * file is allocated. MKS cp needs that.
1345 * Adding the real allocated ranges via FIEMAP on Linux
1346 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1347 * this FSCTL correct for sparse files.
1349 uint64_t offset, length;
1350 char *out_data_tmp = NULL;
1353 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1355 return NT_STATUS_INVALID_PARAMETER;
1358 if (max_out_len < 16) {
1359 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1361 return NT_STATUS_INVALID_PARAMETER;
1364 offset = BVAL(in_data,0);
1365 length = BVAL(in_data,8);
1367 if (offset + length < offset) {
1368 /* No 64-bit integer wrap. */
1369 return NT_STATUS_INVALID_PARAMETER;
1372 /* Shouldn't this be SMB_VFS_STAT ... ? */
1373 status = vfs_stat_fsp(fsp);
1374 if (!NT_STATUS_IS_OK(status)) {
1379 out_data_tmp = talloc_array(ctx, char, *out_len);
1380 if (out_data_tmp == NULL) {
1381 DEBUG(10, ("unable to allocate memory for response\n"));
1382 return NT_STATUS_NO_MEMORY;
1385 if (offset > fsp->fsp_name->st.st_ex_size ||
1386 fsp->fsp_name->st.st_ex_size == 0 ||
1388 memset(out_data_tmp, 0, *out_len);
1390 uint64_t end = offset + length;
1391 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1392 SBVAL(out_data_tmp, 0, 0);
1393 SBVAL(out_data_tmp, 8, end);
1396 *out_data = out_data_tmp;
1398 return NT_STATUS_OK;
1401 case FSCTL_IS_VOLUME_DIRTY:
1403 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1404 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1406 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1407 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1409 return NT_STATUS_INVALID_PARAMETER;
1414 * Only print once ... unfortunately there could be lots of
1415 * different FSCTLs that are called.
1417 if (!vfswrap_logged_ioctl_message) {
1418 vfswrap_logged_ioctl_message = true;
1419 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1420 __func__, function));
1424 return NT_STATUS_NOT_SUPPORTED;
1427 struct vfs_cc_state {
1432 static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *handle,
1433 TALLOC_CTX *mem_ctx,
1434 struct tevent_context *ev,
1435 struct files_struct *src_fsp,
1437 struct files_struct *dest_fsp,
1441 struct tevent_req *req;
1442 struct vfs_cc_state *vfs_cc_state;
1445 DEBUG(10, ("performing server side copy chunk of length %lu\n",
1446 (unsigned long)num));
1448 req = tevent_req_create(mem_ctx, &vfs_cc_state, struct vfs_cc_state);
1453 vfs_cc_state->buf = talloc_array(vfs_cc_state, uint8_t,
1454 MIN(num, 8*1024*1024));
1455 if (tevent_req_nomem(vfs_cc_state->buf, req)) {
1456 return tevent_req_post(req, ev);
1459 status = vfs_stat_fsp(src_fsp);
1460 if (tevent_req_nterror(req, status)) {
1461 return tevent_req_post(req, ev);
1464 if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
1466 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1467 * If the SourceOffset or SourceOffset + Length extends beyond
1468 * the end of file, the server SHOULD<240> treat this as a
1469 * STATUS_END_OF_FILE error.
1471 * <240> Section 3.3.5.15.6: Windows servers will return
1472 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1474 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1475 return tevent_req_post(req, ev);
1478 /* could use 2.6.33+ sendfile here to do this in kernel */
1479 while (vfs_cc_state->copied < num) {
1481 struct lock_struct lck;
1484 off_t this_num = MIN(talloc_array_length(vfs_cc_state->buf),
1485 num - vfs_cc_state->copied);
1487 if (src_fsp->op == NULL) {
1488 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1489 return tevent_req_post(req, ev);
1491 init_strict_lock_struct(src_fsp,
1492 src_fsp->op->global->open_persistent_id,
1498 if (!SMB_VFS_STRICT_LOCK(src_fsp->conn, src_fsp, &lck)) {
1499 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1500 return tevent_req_post(req, ev);
1503 ret = SMB_VFS_PREAD(src_fsp, vfs_cc_state->buf,
1506 saved_errno = errno;
1509 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1512 errno = saved_errno;
1513 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1514 return tevent_req_post(req, ev);
1516 if (ret != this_num) {
1517 /* zero tolerance for short reads */
1518 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1519 return tevent_req_post(req, ev);
1524 if (dest_fsp->op == NULL) {
1525 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1526 return tevent_req_post(req, ev);
1529 init_strict_lock_struct(dest_fsp,
1530 dest_fsp->op->global->open_persistent_id,
1536 if (!SMB_VFS_STRICT_LOCK(dest_fsp->conn, dest_fsp, &lck)) {
1537 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1538 return tevent_req_post(req, ev);
1541 ret = SMB_VFS_PWRITE(dest_fsp, vfs_cc_state->buf,
1542 this_num, dest_off);
1544 saved_errno = errno;
1547 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1550 errno = saved_errno;
1551 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1552 return tevent_req_post(req, ev);
1554 if (ret != this_num) {
1555 /* zero tolerance for short writes */
1556 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1557 return tevent_req_post(req, ev);
1561 vfs_cc_state->copied += this_num;
1564 tevent_req_done(req);
1565 return tevent_req_post(req, ev);
1568 static NTSTATUS vfswrap_copy_chunk_recv(struct vfs_handle_struct *handle,
1569 struct tevent_req *req,
1572 struct vfs_cc_state *vfs_cc_state = tevent_req_data(req,
1573 struct vfs_cc_state);
1576 if (tevent_req_is_nterror(req, &status)) {
1577 DEBUG(2, ("server side copy chunk failed: %s\n",
1578 nt_errstr(status)));
1580 tevent_req_received(req);
1584 *copied = vfs_cc_state->copied;
1585 DEBUG(10, ("server side copy chunk copied %lu\n",
1586 (unsigned long)*copied));
1587 tevent_req_received(req);
1589 return NT_STATUS_OK;
1592 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1593 TALLOC_CTX *mem_ctx,
1594 struct files_struct *fsp,
1595 struct smb_filename *smb_fname,
1596 uint16_t *_compression_fmt)
1598 return NT_STATUS_INVALID_DEVICE_REQUEST;
1601 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1602 TALLOC_CTX *mem_ctx,
1603 struct files_struct *fsp,
1604 uint16_t compression_fmt)
1606 return NT_STATUS_INVALID_DEVICE_REQUEST;
1609 /********************************************************************
1610 Given a stat buffer return the allocated size on disk, taking into
1611 account sparse files.
1612 ********************************************************************/
1613 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1614 struct files_struct *fsp,
1615 const SMB_STRUCT_STAT *sbuf)
1619 START_PROFILE(syscall_get_alloc_size);
1621 if(S_ISDIR(sbuf->st_ex_mode)) {
1626 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1627 /* The type of st_blocksize is blkcnt_t which *MUST* be
1628 signed (according to POSIX) and can be less than 64-bits.
1629 Ensure when we're converting to 64 bits wide we don't
1631 #if defined(SIZEOF_BLKCNT_T_8)
1632 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1633 #elif defined(SIZEOF_BLKCNT_T_4)
1635 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1636 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1639 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1643 * Some file systems do not allocate a block for very
1644 * small files. But for non-empty file should report a
1648 uint64_t filesize = get_file_size_stat(sbuf);
1650 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
1654 result = get_file_size_stat(sbuf);
1657 if (fsp && fsp->initial_allocation_size)
1658 result = MAX(result,fsp->initial_allocation_size);
1660 result = smb_roundup(handle->conn, result);
1663 END_PROFILE(syscall_get_alloc_size);
1667 static int vfswrap_unlink(vfs_handle_struct *handle,
1668 const struct smb_filename *smb_fname)
1672 START_PROFILE(syscall_unlink);
1674 if (smb_fname->stream_name) {
1678 result = unlink(smb_fname->base_name);
1681 END_PROFILE(syscall_unlink);
1685 static int vfswrap_chmod(vfs_handle_struct *handle, const char *path, mode_t mode)
1689 START_PROFILE(syscall_chmod);
1692 * We need to do this due to the fact that the default POSIX ACL
1693 * chmod modifies the ACL *mask* for the group owner, not the
1694 * group owner bits directly. JRA.
1699 int saved_errno = errno; /* We might get ENOSYS */
1700 if ((result = SMB_VFS_CHMOD_ACL(handle->conn, path, mode)) == 0) {
1701 END_PROFILE(syscall_chmod);
1704 /* Error - return the old errno. */
1705 errno = saved_errno;
1708 result = chmod(path, mode);
1709 END_PROFILE(syscall_chmod);
1713 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
1717 START_PROFILE(syscall_fchmod);
1720 * We need to do this due to the fact that the default POSIX ACL
1721 * chmod modifies the ACL *mask* for the group owner, not the
1722 * group owner bits directly. JRA.
1726 int saved_errno = errno; /* We might get ENOSYS */
1727 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
1728 END_PROFILE(syscall_fchmod);
1731 /* Error - return the old errno. */
1732 errno = saved_errno;
1735 #if defined(HAVE_FCHMOD)
1736 result = fchmod(fsp->fh->fd, mode);
1742 END_PROFILE(syscall_fchmod);
1746 static int vfswrap_chown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1750 START_PROFILE(syscall_chown);
1751 result = chown(path, uid, gid);
1752 END_PROFILE(syscall_chown);
1756 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
1761 START_PROFILE(syscall_fchown);
1762 result = fchown(fsp->fh->fd, uid, gid);
1763 END_PROFILE(syscall_fchown);
1771 static int vfswrap_lchown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1775 START_PROFILE(syscall_lchown);
1776 result = lchown(path, uid, gid);
1777 END_PROFILE(syscall_lchown);
1781 static int vfswrap_chdir(vfs_handle_struct *handle, const char *path)
1785 START_PROFILE(syscall_chdir);
1786 result = chdir(path);
1787 END_PROFILE(syscall_chdir);
1791 static char *vfswrap_getwd(vfs_handle_struct *handle)
1795 START_PROFILE(syscall_getwd);
1796 result = sys_getwd();
1797 END_PROFILE(syscall_getwd);
1801 /*********************************************************************
1802 nsec timestamp resolution call. Convert down to whatever the underlying
1803 system will support.
1804 **********************************************************************/
1806 static int vfswrap_ntimes(vfs_handle_struct *handle,
1807 const struct smb_filename *smb_fname,
1808 struct smb_file_time *ft)
1812 START_PROFILE(syscall_ntimes);
1814 if (smb_fname->stream_name) {
1820 if (null_timespec(ft->atime)) {
1821 ft->atime= smb_fname->st.st_ex_atime;
1824 if (null_timespec(ft->mtime)) {
1825 ft->mtime = smb_fname->st.st_ex_mtime;
1828 if (!null_timespec(ft->create_time)) {
1829 set_create_timespec_ea(handle->conn,
1834 if ((timespec_compare(&ft->atime,
1835 &smb_fname->st.st_ex_atime) == 0) &&
1836 (timespec_compare(&ft->mtime,
1837 &smb_fname->st.st_ex_mtime) == 0)) {
1842 #if defined(HAVE_UTIMENSAT)
1844 struct timespec ts[2];
1847 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
1849 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
1851 if (!((result == -1) && (errno == ENOSYS))) {
1855 #if defined(HAVE_UTIMES)
1857 struct timeval tv[2];
1858 tv[0] = convert_timespec_to_timeval(ft->atime);
1859 tv[1] = convert_timespec_to_timeval(ft->mtime);
1860 result = utimes(smb_fname->base_name, tv);
1862 result = utimes(smb_fname->base_name, NULL);
1864 if (!((result == -1) && (errno == ENOSYS))) {
1868 #if defined(HAVE_UTIME)
1870 struct utimbuf times;
1871 times.actime = convert_timespec_to_time_t(ft->atime);
1872 times.modtime = convert_timespec_to_time_t(ft->mtime);
1873 result = utime(smb_fname->base_name, ×);
1875 result = utime(smb_fname->base_name, NULL);
1877 if (!((result == -1) && (errno == ENOSYS))) {
1885 END_PROFILE(syscall_ntimes);
1889 /*********************************************************************
1890 A version of ftruncate that will write the space on disk if strict
1892 **********************************************************************/
1894 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1896 off_t space_to_write;
1897 uint64_t space_avail;
1898 uint64_t bsize,dfree,dsize;
1901 SMB_STRUCT_STAT *pst;
1903 status = vfs_stat_fsp(fsp);
1904 if (!NT_STATUS_IS_OK(status)) {
1907 pst = &fsp->fsp_name->st;
1910 if (S_ISFIFO(pst->st_ex_mode))
1914 if (pst->st_ex_size == len)
1917 /* Shrink - just ftruncate. */
1918 if (pst->st_ex_size > len)
1919 return ftruncate(fsp->fh->fd, len);
1921 space_to_write = len - pst->st_ex_size;
1923 /* for allocation try fallocate first. This can fail on some
1924 platforms e.g. when the filesystem doesn't support it and no
1925 emulation is being done by the libc (like on AIX with JFS1). In that
1926 case we do our own emulation. fallocate implementations can
1927 return ENOTSUP or EINVAL in cases like that. */
1928 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
1929 if (ret == -1 && errno == ENOSPC) {
1935 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
1936 "error %d. Falling back to slow manual allocation\n", errno));
1938 /* available disk space is enough or not? */
1939 space_avail = get_dfree_info(fsp->conn,
1940 fsp->fsp_name->base_name,
1941 &bsize, &dfree, &dsize);
1942 /* space_avail is 1k blocks */
1943 if (space_avail == (uint64_t)-1 ||
1944 ((uint64_t)space_to_write/1024 > space_avail) ) {
1949 /* Write out the real space on disk. */
1950 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
1958 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1961 SMB_STRUCT_STAT *pst;
1965 START_PROFILE(syscall_ftruncate);
1967 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
1968 result = strict_allocate_ftruncate(handle, fsp, len);
1969 END_PROFILE(syscall_ftruncate);
1973 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
1974 ftruncate if the system supports it. Then I discovered that
1975 you can have some filesystems that support ftruncate
1976 expansion and some that don't! On Linux fat can't do
1977 ftruncate extend but ext2 can. */
1979 result = ftruncate(fsp->fh->fd, len);
1981 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
1982 extend a file with ftruncate. Provide alternate implementation
1985 /* Do an fstat to see if the file is longer than the requested
1986 size in which case the ftruncate above should have
1987 succeeded or shorter, in which case seek to len - 1 and
1988 write 1 byte of zero */
1989 status = vfs_stat_fsp(fsp);
1990 if (!NT_STATUS_IS_OK(status)) {
1994 /* We need to update the files_struct after successful ftruncate */
1999 pst = &fsp->fsp_name->st;
2002 if (S_ISFIFO(pst->st_ex_mode)) {
2008 if (pst->st_ex_size == len) {
2013 if (pst->st_ex_size > len) {
2014 /* the ftruncate should have worked */
2018 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2026 END_PROFILE(syscall_ftruncate);
2030 static int vfswrap_fallocate(vfs_handle_struct *handle,
2038 START_PROFILE(syscall_fallocate);
2040 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2042 * posix_fallocate returns 0 on success, errno on error
2043 * and doesn't set errno. Make it behave like fallocate()
2044 * which returns -1, and sets errno on failure.
2051 /* sys_fallocate handles filtering of unsupported mode flags */
2052 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2054 END_PROFILE(syscall_fallocate);
2058 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2062 START_PROFILE(syscall_fcntl_lock);
2063 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2064 END_PROFILE(syscall_fcntl_lock);
2068 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2069 uint32_t share_mode, uint32_t access_mask)
2071 START_PROFILE(syscall_kernel_flock);
2072 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2073 END_PROFILE(syscall_kernel_flock);
2077 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2081 START_PROFILE(syscall_fcntl_getlock);
2082 result = fcntl_getlock(fsp->fh->fd, poffset, pcount, ptype, ppid);
2083 END_PROFILE(syscall_fcntl_getlock);
2087 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2092 START_PROFILE(syscall_linux_setlease);
2094 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2095 result = linux_setlease(fsp->fh->fd, leasetype);
2099 END_PROFILE(syscall_linux_setlease);
2103 static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2107 START_PROFILE(syscall_symlink);
2108 result = symlink(oldpath, newpath);
2109 END_PROFILE(syscall_symlink);
2113 static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
2117 START_PROFILE(syscall_readlink);
2118 result = readlink(path, buf, bufsiz);
2119 END_PROFILE(syscall_readlink);
2123 static int vfswrap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2127 START_PROFILE(syscall_link);
2128 result = link(oldpath, newpath);
2129 END_PROFILE(syscall_link);
2133 static int vfswrap_mknod(vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev)
2137 START_PROFILE(syscall_mknod);
2138 result = sys_mknod(pathname, mode, dev);
2139 END_PROFILE(syscall_mknod);
2143 static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
2147 START_PROFILE(syscall_realpath);
2148 result = sys_realpath(path);
2149 END_PROFILE(syscall_realpath);
2153 static int vfswrap_chflags(vfs_handle_struct *handle, const char *path,
2157 return chflags(path, flags);
2164 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2165 const SMB_STRUCT_STAT *sbuf)
2169 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2173 key.devid = sbuf->st_ex_dev;
2174 key.inode = sbuf->st_ex_ino;
2175 /* key.extid is unused by default. */
2180 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2181 struct files_struct *fsp,
2183 TALLOC_CTX *mem_ctx,
2184 unsigned int *pnum_streams,
2185 struct stream_struct **pstreams)
2187 SMB_STRUCT_STAT sbuf;
2188 struct stream_struct *tmp_streams = NULL;
2191 if ((fsp != NULL) && (fsp->is_directory)) {
2193 * No default streams on directories
2198 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2199 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2202 struct smb_filename smb_fname;
2204 ZERO_STRUCT(smb_fname);
2205 smb_fname.base_name = discard_const_p(char, fname);
2207 if (lp_posix_pathnames()) {
2208 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname);
2210 ret = SMB_VFS_STAT(handle->conn, &smb_fname);
2212 sbuf = smb_fname.st;
2216 return map_nt_error_from_unix(errno);
2219 if (S_ISDIR(sbuf.st_ex_mode)) {
2223 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2224 (*pnum_streams) + 1);
2225 if (tmp_streams == NULL) {
2226 return NT_STATUS_NO_MEMORY;
2228 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2229 if (tmp_streams[*pnum_streams].name == NULL) {
2230 return NT_STATUS_NO_MEMORY;
2232 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2233 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2236 *pstreams = tmp_streams;
2238 return NT_STATUS_OK;
2241 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2244 TALLOC_CTX *mem_ctx,
2248 * Don't fall back to get_real_filename so callers can differentiate
2249 * between a full directory scan and an actual case-insensitive stat.
2255 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2258 return handle->conn->connectpath;
2261 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2262 struct byte_range_lock *br_lck,
2263 struct lock_struct *plock,
2266 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2268 /* Note: blr is not used in the default implementation. */
2269 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2272 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2273 struct messaging_context *msg_ctx,
2274 struct byte_range_lock *br_lck,
2275 const struct lock_struct *plock)
2277 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2279 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2282 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2283 struct byte_range_lock *br_lck,
2284 struct lock_struct *plock)
2286 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2288 /* Note: blr is not used in the default implementation. */
2289 return brl_lock_cancel_default(br_lck, plock);
2292 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2294 struct lock_struct *plock)
2296 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2297 plock->lock_type == WRITE_LOCK);
2299 return strict_lock_default(fsp, plock);
2302 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2304 struct lock_struct *plock)
2306 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2307 plock->lock_type == WRITE_LOCK);
2309 strict_unlock_default(fsp, plock);
2312 /* NT ACL operations. */
2314 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2316 uint32_t security_info,
2317 TALLOC_CTX *mem_ctx,
2318 struct security_descriptor **ppdesc)
2322 START_PROFILE(fget_nt_acl);
2323 result = posix_fget_nt_acl(fsp, security_info,
2325 END_PROFILE(fget_nt_acl);
2329 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2331 uint32_t security_info,
2332 TALLOC_CTX *mem_ctx,
2333 struct security_descriptor **ppdesc)
2337 START_PROFILE(get_nt_acl);
2338 result = posix_get_nt_acl(handle->conn, name, security_info,
2340 END_PROFILE(get_nt_acl);
2344 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2348 START_PROFILE(fset_nt_acl);
2349 result = set_nt_acl(fsp, security_info_sent, psd);
2350 END_PROFILE(fset_nt_acl);
2354 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2355 struct smb_filename *file,
2356 struct security_acl *sacl,
2357 uint32_t access_requested,
2358 uint32_t access_denied)
2360 return NT_STATUS_OK; /* Nothing to do here ... */
2363 static int vfswrap_chmod_acl(vfs_handle_struct *handle, const char *name, mode_t mode)
2371 START_PROFILE(chmod_acl);
2372 result = chmod_acl(handle->conn, name, mode);
2373 END_PROFILE(chmod_acl);
2378 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2386 START_PROFILE(fchmod_acl);
2387 result = fchmod_acl(fsp, mode);
2388 END_PROFILE(fchmod_acl);
2393 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2395 SMB_ACL_TYPE_T type,
2396 TALLOC_CTX *mem_ctx)
2398 return sys_acl_get_file(handle, path_p, type, mem_ctx);
2401 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2403 TALLOC_CTX *mem_ctx)
2405 return sys_acl_get_fd(handle, fsp, mem_ctx);
2408 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2410 return sys_acl_set_file(handle, name, acltype, theacl);
2413 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2415 return sys_acl_set_fd(handle, fsp, theacl);
2418 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
2420 return sys_acl_delete_def_file(handle, path);
2423 /****************************************************************
2424 Extended attribute operations.
2425 *****************************************************************/
2427 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
2429 return getxattr(path, name, value, size);
2432 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2434 return fgetxattr(fsp->fh->fd, name, value, size);
2437 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
2439 return listxattr(path, list, size);
2442 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2444 return flistxattr(fsp->fh->fd, list, size);
2447 static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
2449 return removexattr(path, name);
2452 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2454 return fremovexattr(fsp->fh->fd, name);
2457 static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
2459 return setxattr(path, name, value, size, flags);
2462 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2464 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2467 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2472 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2473 const struct smb_filename *fname,
2474 SMB_STRUCT_STAT *sbuf)
2478 bool offline = false;
2480 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2484 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2485 #if defined(ENOTSUP)
2491 status = get_full_smb_filename(talloc_tos(), fname, &path);
2492 if (!NT_STATUS_IS_OK(status)) {
2493 errno = map_errno_from_nt_status(status);
2497 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2504 static int vfswrap_set_offline(struct vfs_handle_struct *handle,
2505 const struct smb_filename *fname)
2507 /* We don't know how to set offline bit by default, needs to be overriden in the vfs modules */
2508 #if defined(ENOTSUP)
2514 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2515 struct files_struct *fsp,
2516 TALLOC_CTX *mem_ctx,
2519 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2522 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2523 struct files_struct *fsp,
2524 const DATA_BLOB old_cookie,
2525 TALLOC_CTX *mem_ctx,
2526 DATA_BLOB *new_cookie)
2528 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2532 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2533 struct smb_request *smb1req,
2534 struct smbXsrv_open *op,
2535 const DATA_BLOB old_cookie,
2536 TALLOC_CTX *mem_ctx,
2537 struct files_struct **fsp,
2538 DATA_BLOB *new_cookie)
2540 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2541 old_cookie, mem_ctx,
2545 static struct vfs_fn_pointers vfs_default_fns = {
2546 /* Disk operations */
2548 .connect_fn = vfswrap_connect,
2549 .disconnect_fn = vfswrap_disconnect,
2550 .disk_free_fn = vfswrap_disk_free,
2551 .get_quota_fn = vfswrap_get_quota,
2552 .set_quota_fn = vfswrap_set_quota,
2553 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2554 .statvfs_fn = vfswrap_statvfs,
2555 .fs_capabilities_fn = vfswrap_fs_capabilities,
2556 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2557 .snap_check_path_fn = vfswrap_snap_check_path,
2558 .snap_create_fn = vfswrap_snap_create,
2559 .snap_delete_fn = vfswrap_snap_delete,
2561 /* Directory operations */
2563 .opendir_fn = vfswrap_opendir,
2564 .fdopendir_fn = vfswrap_fdopendir,
2565 .readdir_fn = vfswrap_readdir,
2566 .readdir_attr_fn = vfswrap_readdir_attr,
2567 .seekdir_fn = vfswrap_seekdir,
2568 .telldir_fn = vfswrap_telldir,
2569 .rewind_dir_fn = vfswrap_rewinddir,
2570 .mkdir_fn = vfswrap_mkdir,
2571 .rmdir_fn = vfswrap_rmdir,
2572 .closedir_fn = vfswrap_closedir,
2573 .init_search_op_fn = vfswrap_init_search_op,
2575 /* File operations */
2577 .open_fn = vfswrap_open,
2578 .create_file_fn = vfswrap_create_file,
2579 .close_fn = vfswrap_close,
2580 .read_fn = vfswrap_read,
2581 .pread_fn = vfswrap_pread,
2582 .pread_send_fn = vfswrap_pread_send,
2583 .pread_recv_fn = vfswrap_asys_ssize_t_recv,
2584 .write_fn = vfswrap_write,
2585 .pwrite_fn = vfswrap_pwrite,
2586 .pwrite_send_fn = vfswrap_pwrite_send,
2587 .pwrite_recv_fn = vfswrap_asys_ssize_t_recv,
2588 .lseek_fn = vfswrap_lseek,
2589 .sendfile_fn = vfswrap_sendfile,
2590 .recvfile_fn = vfswrap_recvfile,
2591 .rename_fn = vfswrap_rename,
2592 .fsync_fn = vfswrap_fsync,
2593 .fsync_send_fn = vfswrap_fsync_send,
2594 .fsync_recv_fn = vfswrap_asys_int_recv,
2595 .stat_fn = vfswrap_stat,
2596 .fstat_fn = vfswrap_fstat,
2597 .lstat_fn = vfswrap_lstat,
2598 .get_alloc_size_fn = vfswrap_get_alloc_size,
2599 .unlink_fn = vfswrap_unlink,
2600 .chmod_fn = vfswrap_chmod,
2601 .fchmod_fn = vfswrap_fchmod,
2602 .chown_fn = vfswrap_chown,
2603 .fchown_fn = vfswrap_fchown,
2604 .lchown_fn = vfswrap_lchown,
2605 .chdir_fn = vfswrap_chdir,
2606 .getwd_fn = vfswrap_getwd,
2607 .ntimes_fn = vfswrap_ntimes,
2608 .ftruncate_fn = vfswrap_ftruncate,
2609 .fallocate_fn = vfswrap_fallocate,
2610 .lock_fn = vfswrap_lock,
2611 .kernel_flock_fn = vfswrap_kernel_flock,
2612 .linux_setlease_fn = vfswrap_linux_setlease,
2613 .getlock_fn = vfswrap_getlock,
2614 .symlink_fn = vfswrap_symlink,
2615 .readlink_fn = vfswrap_readlink,
2616 .link_fn = vfswrap_link,
2617 .mknod_fn = vfswrap_mknod,
2618 .realpath_fn = vfswrap_realpath,
2619 .chflags_fn = vfswrap_chflags,
2620 .file_id_create_fn = vfswrap_file_id_create,
2621 .streaminfo_fn = vfswrap_streaminfo,
2622 .get_real_filename_fn = vfswrap_get_real_filename,
2623 .connectpath_fn = vfswrap_connectpath,
2624 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2625 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2626 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2627 .strict_lock_fn = vfswrap_strict_lock,
2628 .strict_unlock_fn = vfswrap_strict_unlock,
2629 .translate_name_fn = vfswrap_translate_name,
2630 .fsctl_fn = vfswrap_fsctl,
2631 .copy_chunk_send_fn = vfswrap_copy_chunk_send,
2632 .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
2633 .get_compression_fn = vfswrap_get_compression,
2634 .set_compression_fn = vfswrap_set_compression,
2636 /* NT ACL operations. */
2638 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2639 .get_nt_acl_fn = vfswrap_get_nt_acl,
2640 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2641 .audit_file_fn = vfswrap_audit_file,
2643 /* POSIX ACL operations. */
2645 .chmod_acl_fn = vfswrap_chmod_acl,
2646 .fchmod_acl_fn = vfswrap_fchmod_acl,
2648 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2649 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2650 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2651 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2652 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2653 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2654 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2656 /* EA operations. */
2657 .getxattr_fn = vfswrap_getxattr,
2658 .fgetxattr_fn = vfswrap_fgetxattr,
2659 .listxattr_fn = vfswrap_listxattr,
2660 .flistxattr_fn = vfswrap_flistxattr,
2661 .removexattr_fn = vfswrap_removexattr,
2662 .fremovexattr_fn = vfswrap_fremovexattr,
2663 .setxattr_fn = vfswrap_setxattr,
2664 .fsetxattr_fn = vfswrap_fsetxattr,
2666 /* aio operations */
2667 .aio_force_fn = vfswrap_aio_force,
2669 /* offline operations */
2670 .is_offline_fn = vfswrap_is_offline,
2671 .set_offline_fn = vfswrap_set_offline,
2673 /* durable handle operations */
2674 .durable_cookie_fn = vfswrap_durable_cookie,
2675 .durable_disconnect_fn = vfswrap_durable_disconnect,
2676 .durable_reconnect_fn = vfswrap_durable_reconnect,
2679 NTSTATUS vfs_default_init(void);
2680 NTSTATUS vfs_default_init(void)
2682 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
2683 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);