2 Unix SMB/CIFS implementation.
3 Wrap disk only vfs functions to sidestep dodgy compilers.
4 Copyright (C) Tim Potter 1998
5 Copyright (C) Jeremy Allison 2007
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "system/time.h"
23 #include "system/filesys.h"
24 #include "smbd/smbd.h"
25 #include "smbd/globals.h"
27 #include "smbprofile.h"
28 #include "../libcli/security/security.h"
29 #include "passdb/lookup_sid.h"
30 #include "source3/include/msdfs.h"
31 #include "librpc/gen_ndr/ndr_dfsblobs.h"
32 #include "lib/util/tevent_unix.h"
33 #include "lib/asys/asys.h"
34 #include "lib/util/tevent_ntstatus.h"
35 #include "lib/util/sys_rw.h"
38 #define DBGC_CLASS DBGC_VFS
40 /* Check for NULL pointer parameters in vfswrap_* functions */
42 /* We don't want to have NULL function pointers lying around. Someone
43 is sure to try and execute them. These stubs are used to prevent
46 static int vfswrap_connect(vfs_handle_struct *handle, const char *service, const char *user)
48 return 0; /* Return >= 0 for success */
51 static void vfswrap_disconnect(vfs_handle_struct *handle)
57 static uint64_t vfswrap_disk_free(vfs_handle_struct *handle, const char *path,
58 uint64_t *bsize, uint64_t *dfree,
61 if (sys_fsusage(path, dfree, dsize) != 0) {
69 static int vfswrap_get_quota(struct vfs_handle_struct *handle, const char *path,
70 enum SMB_QUOTA_TYPE qtype, unid_t id,
73 #ifdef HAVE_SYS_QUOTAS
76 START_PROFILE(syscall_get_quota);
77 result = sys_get_quota(path, qtype, id, qt);
78 END_PROFILE(syscall_get_quota);
86 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
88 #ifdef HAVE_SYS_QUOTAS
91 START_PROFILE(syscall_set_quota);
92 result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
93 END_PROFILE(syscall_set_quota);
101 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
102 struct files_struct *fsp,
103 struct shadow_copy_data *shadow_copy_data,
107 return -1; /* Not implemented. */
110 static int vfswrap_statvfs(struct vfs_handle_struct *handle, const char *path, vfs_statvfs_struct *statbuf)
112 return sys_statvfs(path, statbuf);
115 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
116 enum timestamp_set_resolution *p_ts_res)
118 connection_struct *conn = handle->conn;
119 uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
120 struct smb_filename *smb_fname_cpath = NULL;
121 struct vfs_statvfs_struct statbuf;
124 ZERO_STRUCT(statbuf);
125 ret = sys_statvfs(conn->connectpath, &statbuf);
127 caps = statbuf.FsCapabilities;
130 *p_ts_res = TIMESTAMP_SET_SECONDS;
132 /* Work out what timestamp resolution we can
133 * use when setting a timestamp. */
135 smb_fname_cpath = synthetic_smb_fname(talloc_tos(), conn->connectpath,
137 if (smb_fname_cpath == NULL) {
141 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
143 TALLOC_FREE(smb_fname_cpath);
147 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
148 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
149 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
150 /* If any of the normal UNIX directory timestamps
151 * have a non-zero tv_nsec component assume
152 * we might be able to set sub-second timestamps.
153 * See what filetime set primitives we have.
155 #if defined(HAVE_UTIMENSAT)
156 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
157 #elif defined(HAVE_UTIMES)
158 /* utimes allows msec timestamps to be set. */
159 *p_ts_res = TIMESTAMP_SET_MSEC;
160 #elif defined(HAVE_UTIME)
161 /* utime only allows sec timestamps to be set. */
162 *p_ts_res = TIMESTAMP_SET_SECONDS;
165 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
167 "available on share %s, directory %s\n",
168 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
169 lp_servicename(talloc_tos(), conn->params->service),
170 conn->connectpath ));
172 TALLOC_FREE(smb_fname_cpath);
176 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
177 struct dfs_GetDFSReferral *r)
179 struct junction_map *junction = NULL;
181 bool self_referral = false;
182 char *pathnamep = NULL;
183 char *local_dfs_path = NULL;
186 uint16_t max_referral_level = r->in.req.max_referral_level;
189 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
192 /* get the junction entry */
193 if (r->in.req.servername == NULL) {
194 return NT_STATUS_NOT_FOUND;
198 * Trim pathname sent by client so it begins with only one backslash.
199 * Two backslashes confuse some dfs clients
202 local_dfs_path = talloc_strdup(r, r->in.req.servername);
203 if (local_dfs_path == NULL) {
204 return NT_STATUS_NO_MEMORY;
206 pathnamep = local_dfs_path;
207 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
208 IS_DIRECTORY_SEP(pathnamep[1])) {
212 junction = talloc_zero(r, struct junction_map);
213 if (junction == NULL) {
214 return NT_STATUS_NO_MEMORY;
217 /* The following call can change cwd. */
218 status = get_referred_path(r, pathnamep,
219 !handle->conn->sconn->using_smb2,
220 junction, &consumedcnt, &self_referral);
221 if (!NT_STATUS_IS_OK(status)) {
222 vfs_ChDir(handle->conn, handle->conn->connectpath);
225 vfs_ChDir(handle->conn, handle->conn->connectpath);
227 if (!self_referral) {
228 pathnamep[consumedcnt] = '\0';
231 dbgtext("Path %s to alternate path(s):",
233 for (i=0; i < junction->referral_count; i++) {
235 junction->referral_list[i].alternate_path);
241 if (r->in.req.max_referral_level <= 2) {
242 max_referral_level = 2;
244 if (r->in.req.max_referral_level >= 3) {
245 max_referral_level = 3;
248 r->out.resp = talloc_zero(r, struct dfs_referral_resp);
249 if (r->out.resp == NULL) {
250 return NT_STATUS_NO_MEMORY;
253 r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
254 r->out.resp->nb_referrals = junction->referral_count;
256 r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
258 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
261 r->out.resp->referral_entries = talloc_zero_array(r,
262 struct dfs_referral_type,
263 r->out.resp->nb_referrals);
264 if (r->out.resp->referral_entries == NULL) {
265 return NT_STATUS_NO_MEMORY;
268 switch (max_referral_level) {
270 for(i=0; i < junction->referral_count; i++) {
271 struct referral *ref = &junction->referral_list[i];
272 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
273 struct dfs_referral_type *t =
274 &r->out.resp->referral_entries[i];
275 struct dfs_referral_v2 *v2 = &t->referral.v2;
278 v2->size = VERSION2_REFERRAL_SIZE;
280 v2->server_type = DFS_SERVER_ROOT;
282 v2->server_type = DFS_SERVER_NON_ROOT;
285 v2->proximity = ref->proximity;
287 v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
288 if (v2->DFS_path == NULL) {
289 return NT_STATUS_NO_MEMORY;
291 v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
292 if (v2->DFS_alt_path == NULL) {
293 return NT_STATUS_NO_MEMORY;
295 v2->netw_address = talloc_strdup(mem_ctx,
296 ref->alternate_path);
297 if (v2->netw_address == NULL) {
298 return NT_STATUS_NO_MEMORY;
304 for(i=0; i < junction->referral_count; i++) {
305 struct referral *ref = &junction->referral_list[i];
306 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
307 struct dfs_referral_type *t =
308 &r->out.resp->referral_entries[i];
309 struct dfs_referral_v3 *v3 = &t->referral.v3;
310 struct dfs_normal_referral *r1 = &v3->referrals.r1;
313 v3->size = VERSION3_REFERRAL_SIZE;
315 v3->server_type = DFS_SERVER_ROOT;
317 v3->server_type = DFS_SERVER_NON_ROOT;
321 r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
322 if (r1->DFS_path == NULL) {
323 return NT_STATUS_NO_MEMORY;
325 r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
326 if (r1->DFS_alt_path == NULL) {
327 return NT_STATUS_NO_MEMORY;
329 r1->netw_address = talloc_strdup(mem_ctx,
330 ref->alternate_path);
331 if (r1->netw_address == NULL) {
332 return NT_STATUS_NO_MEMORY;
337 DEBUG(0,("Invalid dfs referral version: %d\n",
338 max_referral_level));
339 return NT_STATUS_INVALID_LEVEL;
343 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
349 static NTSTATUS vfswrap_snap_check_path(struct vfs_handle_struct *handle,
351 const char *service_path,
354 return NT_STATUS_NOT_SUPPORTED;
357 static NTSTATUS vfswrap_snap_create(struct vfs_handle_struct *handle,
359 const char *base_volume,
365 return NT_STATUS_NOT_SUPPORTED;
368 static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle,
373 return NT_STATUS_NOT_SUPPORTED;
376 /* Directory operations */
378 static DIR *vfswrap_opendir(vfs_handle_struct *handle,
379 const struct smb_filename *smb_fname,
385 START_PROFILE(syscall_opendir);
386 result = opendir(smb_fname->base_name);
387 END_PROFILE(syscall_opendir);
391 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
398 START_PROFILE(syscall_fdopendir);
399 result = sys_fdopendir(fsp->fh->fd);
400 END_PROFILE(syscall_fdopendir);
405 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
407 SMB_STRUCT_STAT *sbuf)
409 struct dirent *result;
411 START_PROFILE(syscall_readdir);
412 result = readdir(dirp);
413 END_PROFILE(syscall_readdir);
415 /* Default Posix readdir() does not give us stat info.
416 * Set to invalid to indicate we didn't return this info. */
417 SET_STAT_INVALID(*sbuf);
418 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
419 if (result != NULL) {
420 /* See if we can efficiently return this. */
422 int flags = AT_SYMLINK_NOFOLLOW;
423 int ret = fstatat(dirfd(dirp),
428 * As this is an optimization,
429 * ignore it if we stat'ed a
430 * symlink. Make the caller
431 * do it again as we don't
432 * know if they wanted the link
433 * info, or its target info.
435 if ((ret == 0) && (!S_ISLNK(st.st_mode))) {
436 init_stat_ex_from_stat(sbuf,
438 lp_fake_directory_create_times(
439 SNUM(handle->conn)));
447 static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
448 const struct smb_filename *fname,
450 struct readdir_attr_data **attr_data)
452 return NT_STATUS_NOT_SUPPORTED;
455 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
457 START_PROFILE(syscall_seekdir);
458 seekdir(dirp, offset);
459 END_PROFILE(syscall_seekdir);
462 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
465 START_PROFILE(syscall_telldir);
466 result = telldir(dirp);
467 END_PROFILE(syscall_telldir);
471 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
473 START_PROFILE(syscall_rewinddir);
475 END_PROFILE(syscall_rewinddir);
478 static int vfswrap_mkdir(vfs_handle_struct *handle,
479 const struct smb_filename *smb_fname,
483 bool has_dacl = False;
484 const char *path = smb_fname->base_name;
487 START_PROFILE(syscall_mkdir);
489 if (lp_inherit_acls(SNUM(handle->conn))
490 && parent_dirname(talloc_tos(), path, &parent, NULL)
491 && (has_dacl = directory_has_default_acl(handle->conn, parent))) {
492 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
497 result = mkdir(path, mode);
499 if (result == 0 && !has_dacl) {
501 * We need to do this as the default behavior of POSIX ACLs
502 * is to set the mask to be the requested group permission
503 * bits, not the group permission bits to be the requested
504 * group permission bits. This is not what we want, as it will
505 * mess up any inherited ACL bits that were set. JRA.
507 int saved_errno = errno; /* We may get ENOSYS */
508 if ((SMB_VFS_CHMOD_ACL(handle->conn, smb_fname, mode) == -1) &&
514 END_PROFILE(syscall_mkdir);
518 static int vfswrap_rmdir(vfs_handle_struct *handle,
519 const struct smb_filename *smb_fname)
523 START_PROFILE(syscall_rmdir);
524 result = rmdir(smb_fname->base_name);
525 END_PROFILE(syscall_rmdir);
529 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
533 START_PROFILE(syscall_closedir);
534 result = closedir(dirp);
535 END_PROFILE(syscall_closedir);
539 static void vfswrap_init_search_op(vfs_handle_struct *handle,
542 /* Default behavior is a NOOP */
545 /* File operations */
547 static int vfswrap_open(vfs_handle_struct *handle,
548 struct smb_filename *smb_fname,
549 files_struct *fsp, int flags, mode_t mode)
553 START_PROFILE(syscall_open);
555 if (smb_fname->stream_name) {
560 result = open(smb_fname->base_name, flags, mode);
562 END_PROFILE(syscall_open);
566 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
567 struct smb_request *req,
568 uint16_t root_dir_fid,
569 struct smb_filename *smb_fname,
570 uint32_t access_mask,
571 uint32_t share_access,
572 uint32_t create_disposition,
573 uint32_t create_options,
574 uint32_t file_attributes,
575 uint32_t oplock_request,
576 struct smb2_lease *lease,
577 uint64_t allocation_size,
578 uint32_t private_flags,
579 struct security_descriptor *sd,
580 struct ea_list *ea_list,
581 files_struct **result,
583 const struct smb2_create_blobs *in_context_blobs,
584 struct smb2_create_blobs *out_context_blobs)
586 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
587 access_mask, share_access,
588 create_disposition, create_options,
589 file_attributes, oplock_request, lease,
590 allocation_size, private_flags,
592 pinfo, in_context_blobs, out_context_blobs);
595 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
599 START_PROFILE(syscall_close);
600 result = fd_close_posix(fsp);
601 END_PROFILE(syscall_close);
605 static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
609 START_PROFILE_BYTES(syscall_read, n);
610 result = sys_read(fsp->fh->fd, data, n);
611 END_PROFILE_BYTES(syscall_read);
615 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
616 size_t n, off_t offset)
620 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
621 START_PROFILE_BYTES(syscall_pread, n);
622 result = sys_pread(fsp->fh->fd, data, n, offset);
623 END_PROFILE_BYTES(syscall_pread);
625 if (result == -1 && errno == ESPIPE) {
626 /* Maintain the fiction that pipes can be seeked (sought?) on. */
627 result = SMB_VFS_READ(fsp, data, n);
631 #else /* HAVE_PREAD */
635 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
636 if (curr == -1 && errno == ESPIPE) {
637 /* Maintain the fiction that pipes can be seeked (sought?) on. */
638 result = SMB_VFS_READ(fsp, data, n);
643 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
648 result = SMB_VFS_READ(fsp, data, n);
651 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
654 #endif /* HAVE_PREAD */
659 static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
663 START_PROFILE_BYTES(syscall_write, n);
664 result = sys_write(fsp->fh->fd, data, n);
665 END_PROFILE_BYTES(syscall_write);
669 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
670 size_t n, off_t offset)
674 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
675 START_PROFILE_BYTES(syscall_pwrite, n);
676 result = sys_pwrite(fsp->fh->fd, data, n, offset);
677 END_PROFILE_BYTES(syscall_pwrite);
679 if (result == -1 && errno == ESPIPE) {
680 /* Maintain the fiction that pipes can be sought on. */
681 result = SMB_VFS_WRITE(fsp, data, n);
684 #else /* HAVE_PWRITE */
688 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
693 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
697 result = SMB_VFS_WRITE(fsp, data, n);
700 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
703 #endif /* HAVE_PWRITE */
708 static void vfswrap_asys_finished(struct tevent_context *ev,
709 struct tevent_fd *fde,
710 uint16_t flags, void *p);
712 static bool vfswrap_init_asys_ctx(struct smbd_server_connection *conn)
714 struct asys_context *ctx;
715 struct tevent_fd *fde;
719 if (conn->asys_ctx != NULL) {
723 ret = asys_context_init(&ctx, lp_aio_max_threads());
725 DEBUG(1, ("asys_context_init failed: %s\n", strerror(ret)));
729 fd = asys_signalfd(ctx);
731 ret = set_blocking(fd, false);
733 DBG_WARNING("set_blocking failed: %s\n", strerror(errno));
737 fde = tevent_add_fd(conn->ev_ctx, conn, fd, TEVENT_FD_READ,
738 vfswrap_asys_finished, ctx);
740 DEBUG(1, ("tevent_add_fd failed\n"));
744 conn->asys_ctx = ctx;
745 conn->asys_fde = fde;
749 asys_context_destroy(ctx);
753 struct vfswrap_asys_state {
754 struct asys_context *asys_ctx;
755 struct tevent_req *req;
757 struct vfs_aio_state vfs_aio_state;
758 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
759 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
762 static int vfswrap_asys_state_destructor(struct vfswrap_asys_state *s)
764 asys_cancel(s->asys_ctx, s->req);
768 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
770 struct tevent_context *ev,
771 struct files_struct *fsp,
773 size_t n, off_t offset)
775 struct tevent_req *req;
776 struct vfswrap_asys_state *state;
779 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
783 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
785 return tevent_req_post(req, ev);
787 state->asys_ctx = handle->conn->sconn->asys_ctx;
790 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
791 state->profile_bytes, n);
792 ret = asys_pread(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
794 tevent_req_error(req, ret);
795 return tevent_req_post(req, ev);
797 talloc_set_destructor(state, vfswrap_asys_state_destructor);
802 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
804 struct tevent_context *ev,
805 struct files_struct *fsp,
807 size_t n, off_t offset)
809 struct tevent_req *req;
810 struct vfswrap_asys_state *state;
813 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
817 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
819 return tevent_req_post(req, ev);
821 state->asys_ctx = handle->conn->sconn->asys_ctx;
824 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
825 state->profile_bytes, n);
826 ret = asys_pwrite(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
828 tevent_req_error(req, ret);
829 return tevent_req_post(req, ev);
831 talloc_set_destructor(state, vfswrap_asys_state_destructor);
836 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
838 struct tevent_context *ev,
839 struct files_struct *fsp)
841 struct tevent_req *req;
842 struct vfswrap_asys_state *state;
845 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
849 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
851 return tevent_req_post(req, ev);
853 state->asys_ctx = handle->conn->sconn->asys_ctx;
856 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
857 state->profile_basic);
858 ret = asys_fsync(state->asys_ctx, fsp->fh->fd, req);
860 tevent_req_error(req, ret);
861 return tevent_req_post(req, ev);
863 talloc_set_destructor(state, vfswrap_asys_state_destructor);
868 static void vfswrap_asys_finished(struct tevent_context *ev,
869 struct tevent_fd *fde,
870 uint16_t flags, void *p)
872 struct asys_context *asys_ctx = (struct asys_context *)p;
873 struct asys_result results[get_outstanding_aio_calls()];
876 if ((flags & TEVENT_FD_READ) == 0) {
880 ret = asys_results(asys_ctx, results, get_outstanding_aio_calls());
882 DEBUG(1, ("asys_results returned %s\n", strerror(-ret)));
886 for (i=0; i<ret; i++) {
887 struct asys_result *result = &results[i];
888 struct tevent_req *req;
889 struct vfswrap_asys_state *state;
891 if ((result->ret == -1) && (result->err == ECANCELED)) {
895 req = talloc_get_type_abort(result->private_data,
897 state = tevent_req_data(req, struct vfswrap_asys_state);
899 talloc_set_destructor(state, NULL);
901 SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
902 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
903 state->ret = result->ret;
904 state->vfs_aio_state.error = result->err;
905 state->vfs_aio_state.duration = result->duration;
906 tevent_req_defer_callback(req, ev);
907 tevent_req_done(req);
911 static ssize_t vfswrap_asys_ssize_t_recv(struct tevent_req *req,
912 struct vfs_aio_state *vfs_aio_state)
914 struct vfswrap_asys_state *state = tevent_req_data(
915 req, struct vfswrap_asys_state);
917 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
920 *vfs_aio_state = state->vfs_aio_state;
924 static int vfswrap_asys_int_recv(struct tevent_req *req,
925 struct vfs_aio_state *vfs_aio_state)
927 struct vfswrap_asys_state *state = tevent_req_data(
928 req, struct vfswrap_asys_state);
930 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
933 *vfs_aio_state = state->vfs_aio_state;
937 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
941 START_PROFILE(syscall_lseek);
943 /* Cope with 'stat' file opens. */
944 if (fsp->fh->fd != -1)
945 result = lseek(fsp->fh->fd, offset, whence);
948 * We want to maintain the fiction that we can seek
949 * on a fifo for file system purposes. This allows
950 * people to set up UNIX fifo's that feed data to Windows
954 if((result == -1) && (errno == ESPIPE)) {
959 END_PROFILE(syscall_lseek);
963 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
964 off_t offset, size_t n)
968 START_PROFILE_BYTES(syscall_sendfile, n);
969 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
970 END_PROFILE_BYTES(syscall_sendfile);
974 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
982 START_PROFILE_BYTES(syscall_recvfile, n);
983 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
984 END_PROFILE_BYTES(syscall_recvfile);
988 static int vfswrap_rename(vfs_handle_struct *handle,
989 const struct smb_filename *smb_fname_src,
990 const struct smb_filename *smb_fname_dst)
994 START_PROFILE(syscall_rename);
996 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
1001 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
1004 END_PROFILE(syscall_rename);
1008 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
1013 START_PROFILE(syscall_fsync);
1014 result = fsync(fsp->fh->fd);
1015 END_PROFILE(syscall_fsync);
1022 static int vfswrap_stat(vfs_handle_struct *handle,
1023 struct smb_filename *smb_fname)
1027 START_PROFILE(syscall_stat);
1029 if (smb_fname->stream_name) {
1034 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1035 lp_fake_directory_create_times(SNUM(handle->conn)));
1037 END_PROFILE(syscall_stat);
1041 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1045 START_PROFILE(syscall_fstat);
1046 result = sys_fstat(fsp->fh->fd,
1047 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1048 END_PROFILE(syscall_fstat);
1052 static int vfswrap_lstat(vfs_handle_struct *handle,
1053 struct smb_filename *smb_fname)
1057 START_PROFILE(syscall_lstat);
1059 if (smb_fname->stream_name) {
1064 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1065 lp_fake_directory_create_times(SNUM(handle->conn)));
1067 END_PROFILE(syscall_lstat);
1071 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1073 enum vfs_translate_direction direction,
1074 TALLOC_CTX *mem_ctx,
1077 return NT_STATUS_NONE_MAPPED;
1081 * Implement the default fsctl operation.
1083 static bool vfswrap_logged_ioctl_message = false;
1085 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1086 struct files_struct *fsp,
1089 uint16_t req_flags, /* Needed for UNICODE ... */
1090 const uint8_t *_in_data,
1092 uint8_t **_out_data,
1093 uint32_t max_out_len,
1096 const char *in_data = (const char *)_in_data;
1097 char **out_data = (char **)_out_data;
1101 case FSCTL_SET_SPARSE:
1103 bool set_sparse = true;
1105 if (in_len >= 1 && in_data[0] == 0) {
1109 status = file_set_sparse(handle->conn, fsp, set_sparse);
1111 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1112 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1113 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1114 nt_errstr(status)));
1119 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1121 unsigned char objid[16];
1122 char *return_data = NULL;
1124 /* This should return the object-id on this file.
1125 * I think I'll make this be the inode+dev. JRA.
1128 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1129 fsp_fnum_dbg(fsp)));
1131 *out_len = MIN(max_out_len, 64);
1133 /* Hmmm, will this cause problems if less data asked for? */
1134 return_data = talloc_array(ctx, char, 64);
1135 if (return_data == NULL) {
1136 return NT_STATUS_NO_MEMORY;
1139 /* For backwards compatibility only store the dev/inode. */
1140 push_file_id_16(return_data, &fsp->file_id);
1141 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1142 push_file_id_16(return_data+32, &fsp->file_id);
1143 memset(return_data+48, 0, 16);
1144 *out_data = return_data;
1145 return NT_STATUS_OK;
1148 case FSCTL_GET_REPARSE_POINT:
1150 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1151 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1152 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1153 return NT_STATUS_NOT_A_REPARSE_POINT;
1156 case FSCTL_SET_REPARSE_POINT:
1158 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1159 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1160 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1161 return NT_STATUS_NOT_A_REPARSE_POINT;
1164 case FSCTL_GET_SHADOW_COPY_DATA:
1167 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1168 * and return their volume names. If max_data_count is 16, then it is just
1169 * asking for the number of volumes and length of the combined names.
1171 * pdata is the data allocated by our caller, but that uses
1172 * total_data_count (which is 0 in our case) rather than max_data_count.
1173 * Allocate the correct amount and return the pointer to let
1174 * it be deallocated when we return.
1176 struct shadow_copy_data *shadow_data = NULL;
1177 bool labels = False;
1178 uint32_t labels_data_count = 0;
1180 char *cur_pdata = NULL;
1182 if (max_out_len < 16) {
1183 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1185 return NT_STATUS_INVALID_PARAMETER;
1188 if (max_out_len > 16) {
1192 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1193 if (shadow_data == NULL) {
1194 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1195 return NT_STATUS_NO_MEMORY;
1199 * Call the VFS routine to actually do the work.
1201 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1204 /* broken module didn't set errno on error */
1205 status = NT_STATUS_UNSUCCESSFUL;
1207 status = map_nt_error_from_unix(errno);
1208 if (NT_STATUS_EQUAL(status,
1209 NT_STATUS_NOT_SUPPORTED)) {
1213 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1214 "connectpath %s, failed - %s.\n",
1215 fsp->conn->connectpath,
1216 nt_errstr(status)));
1217 TALLOC_FREE(shadow_data);
1221 labels_data_count = (shadow_data->num_volumes * 2 *
1222 sizeof(SHADOW_COPY_LABEL)) + 2;
1227 *out_len = 12 + labels_data_count;
1230 if (max_out_len < *out_len) {
1231 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1232 max_out_len, *out_len));
1233 TALLOC_FREE(shadow_data);
1234 return NT_STATUS_BUFFER_TOO_SMALL;
1237 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1238 if (cur_pdata == NULL) {
1239 TALLOC_FREE(shadow_data);
1240 return NT_STATUS_NO_MEMORY;
1243 *out_data = cur_pdata;
1245 /* num_volumes 4 bytes */
1246 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1249 /* num_labels 4 bytes */
1250 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1253 /* needed_data_count 4 bytes */
1254 SIVAL(cur_pdata, 8, labels_data_count);
1258 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1259 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1260 if (labels && shadow_data->labels) {
1261 for (i=0; i<shadow_data->num_volumes; i++) {
1263 status = srvstr_push(cur_pdata, req_flags,
1264 cur_pdata, shadow_data->labels[i],
1265 2 * sizeof(SHADOW_COPY_LABEL),
1266 STR_UNICODE|STR_TERMINATE, &len);
1267 if (!NT_STATUS_IS_OK(status)) {
1268 TALLOC_FREE(*out_data);
1269 TALLOC_FREE(shadow_data);
1272 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1273 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1277 TALLOC_FREE(shadow_data);
1279 return NT_STATUS_OK;
1282 case FSCTL_FIND_FILES_BY_SID:
1284 /* pretend this succeeded -
1286 * we have to send back a list with all files owned by this SID
1288 * but I have to check that --metze
1294 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1295 fsp_fnum_dbg(fsp)));
1298 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1299 return NT_STATUS_INVALID_PARAMETER;
1302 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1304 /* unknown 4 bytes: this is not the length of the sid :-( */
1305 /*unknown = IVAL(pdata,0);*/
1307 if (!sid_parse(_in_data + 4, sid_len, &sid)) {
1308 return NT_STATUS_INVALID_PARAMETER;
1310 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1312 if (!sid_to_uid(&sid, &uid)) {
1313 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1314 sid_string_dbg(&sid),
1315 (unsigned long)sid_len));
1319 /* we can take a look at the find source :-)
1321 * find ./ -uid $uid -name '*' is what we need here
1324 * and send 4bytes len and then NULL terminated unicode strings
1327 * but I don't know how to deal with the paged results
1328 * (maybe we can hang the result anywhere in the fsp struct)
1330 * but I don't know how to deal with the paged results
1331 * (maybe we can hang the result anywhere in the fsp struct)
1333 * we don't send all files at once
1334 * and at the next we should *not* start from the beginning,
1335 * so we have to cache the result
1340 /* this works for now... */
1341 return NT_STATUS_OK;
1344 case FSCTL_QUERY_ALLOCATED_RANGES:
1346 /* FIXME: This is just a dummy reply, telling that all of the
1347 * file is allocated. MKS cp needs that.
1348 * Adding the real allocated ranges via FIEMAP on Linux
1349 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1350 * this FSCTL correct for sparse files.
1352 uint64_t offset, length;
1353 char *out_data_tmp = NULL;
1356 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1358 return NT_STATUS_INVALID_PARAMETER;
1361 if (max_out_len < 16) {
1362 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1364 return NT_STATUS_INVALID_PARAMETER;
1367 offset = BVAL(in_data,0);
1368 length = BVAL(in_data,8);
1370 if (offset + length < offset) {
1371 /* No 64-bit integer wrap. */
1372 return NT_STATUS_INVALID_PARAMETER;
1375 /* Shouldn't this be SMB_VFS_STAT ... ? */
1376 status = vfs_stat_fsp(fsp);
1377 if (!NT_STATUS_IS_OK(status)) {
1382 out_data_tmp = talloc_array(ctx, char, *out_len);
1383 if (out_data_tmp == NULL) {
1384 DEBUG(10, ("unable to allocate memory for response\n"));
1385 return NT_STATUS_NO_MEMORY;
1388 if (offset > fsp->fsp_name->st.st_ex_size ||
1389 fsp->fsp_name->st.st_ex_size == 0 ||
1391 memset(out_data_tmp, 0, *out_len);
1393 uint64_t end = offset + length;
1394 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1395 SBVAL(out_data_tmp, 0, 0);
1396 SBVAL(out_data_tmp, 8, end);
1399 *out_data = out_data_tmp;
1401 return NT_STATUS_OK;
1404 case FSCTL_IS_VOLUME_DIRTY:
1406 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1407 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1409 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1410 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1412 return NT_STATUS_INVALID_PARAMETER;
1417 * Only print once ... unfortunately there could be lots of
1418 * different FSCTLs that are called.
1420 if (!vfswrap_logged_ioctl_message) {
1421 vfswrap_logged_ioctl_message = true;
1422 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1423 __func__, function));
1427 return NT_STATUS_NOT_SUPPORTED;
1430 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1431 struct smb_filename *smb_fname,
1434 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1437 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1438 struct files_struct *fsp,
1441 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1444 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1445 const struct smb_filename *smb_fname,
1448 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1451 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1452 struct files_struct *fsp,
1455 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1458 struct vfs_cc_state {
1463 static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *handle,
1464 TALLOC_CTX *mem_ctx,
1465 struct tevent_context *ev,
1466 struct files_struct *src_fsp,
1468 struct files_struct *dest_fsp,
1472 struct tevent_req *req;
1473 struct vfs_cc_state *vfs_cc_state;
1476 DEBUG(10, ("performing server side copy chunk of length %lu\n",
1477 (unsigned long)num));
1479 req = tevent_req_create(mem_ctx, &vfs_cc_state, struct vfs_cc_state);
1484 vfs_cc_state->buf = talloc_array(vfs_cc_state, uint8_t,
1485 MIN(num, 8*1024*1024));
1486 if (tevent_req_nomem(vfs_cc_state->buf, req)) {
1487 return tevent_req_post(req, ev);
1490 status = vfs_stat_fsp(src_fsp);
1491 if (tevent_req_nterror(req, status)) {
1492 return tevent_req_post(req, ev);
1495 if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
1497 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1498 * If the SourceOffset or SourceOffset + Length extends beyond
1499 * the end of file, the server SHOULD<240> treat this as a
1500 * STATUS_END_OF_FILE error.
1502 * <240> Section 3.3.5.15.6: Windows servers will return
1503 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1505 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1506 return tevent_req_post(req, ev);
1509 /* could use 2.6.33+ sendfile here to do this in kernel */
1510 while (vfs_cc_state->copied < num) {
1512 struct lock_struct lck;
1515 off_t this_num = MIN(talloc_array_length(vfs_cc_state->buf),
1516 num - vfs_cc_state->copied);
1518 if (src_fsp->op == NULL) {
1519 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1520 return tevent_req_post(req, ev);
1522 init_strict_lock_struct(src_fsp,
1523 src_fsp->op->global->open_persistent_id,
1529 if (!SMB_VFS_STRICT_LOCK(src_fsp->conn, src_fsp, &lck)) {
1530 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1531 return tevent_req_post(req, ev);
1534 ret = SMB_VFS_PREAD(src_fsp, vfs_cc_state->buf,
1537 saved_errno = errno;
1540 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1543 errno = saved_errno;
1544 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1545 return tevent_req_post(req, ev);
1547 if (ret != this_num) {
1548 /* zero tolerance for short reads */
1549 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1550 return tevent_req_post(req, ev);
1555 if (dest_fsp->op == NULL) {
1556 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1557 return tevent_req_post(req, ev);
1560 init_strict_lock_struct(dest_fsp,
1561 dest_fsp->op->global->open_persistent_id,
1567 if (!SMB_VFS_STRICT_LOCK(dest_fsp->conn, dest_fsp, &lck)) {
1568 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1569 return tevent_req_post(req, ev);
1572 ret = SMB_VFS_PWRITE(dest_fsp, vfs_cc_state->buf,
1573 this_num, dest_off);
1575 saved_errno = errno;
1578 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1581 errno = saved_errno;
1582 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1583 return tevent_req_post(req, ev);
1585 if (ret != this_num) {
1586 /* zero tolerance for short writes */
1587 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1588 return tevent_req_post(req, ev);
1592 vfs_cc_state->copied += this_num;
1595 tevent_req_done(req);
1596 return tevent_req_post(req, ev);
1599 static NTSTATUS vfswrap_copy_chunk_recv(struct vfs_handle_struct *handle,
1600 struct tevent_req *req,
1603 struct vfs_cc_state *vfs_cc_state = tevent_req_data(req,
1604 struct vfs_cc_state);
1607 if (tevent_req_is_nterror(req, &status)) {
1608 DEBUG(2, ("server side copy chunk failed: %s\n",
1609 nt_errstr(status)));
1611 tevent_req_received(req);
1615 *copied = vfs_cc_state->copied;
1616 DEBUG(10, ("server side copy chunk copied %lu\n",
1617 (unsigned long)*copied));
1618 tevent_req_received(req);
1620 return NT_STATUS_OK;
1623 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1624 TALLOC_CTX *mem_ctx,
1625 struct files_struct *fsp,
1626 struct smb_filename *smb_fname,
1627 uint16_t *_compression_fmt)
1629 return NT_STATUS_INVALID_DEVICE_REQUEST;
1632 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1633 TALLOC_CTX *mem_ctx,
1634 struct files_struct *fsp,
1635 uint16_t compression_fmt)
1637 return NT_STATUS_INVALID_DEVICE_REQUEST;
1640 /********************************************************************
1641 Given a stat buffer return the allocated size on disk, taking into
1642 account sparse files.
1643 ********************************************************************/
1644 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1645 struct files_struct *fsp,
1646 const SMB_STRUCT_STAT *sbuf)
1650 START_PROFILE(syscall_get_alloc_size);
1652 if(S_ISDIR(sbuf->st_ex_mode)) {
1657 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1658 /* The type of st_blocksize is blkcnt_t which *MUST* be
1659 signed (according to POSIX) and can be less than 64-bits.
1660 Ensure when we're converting to 64 bits wide we don't
1662 #if defined(SIZEOF_BLKCNT_T_8)
1663 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1664 #elif defined(SIZEOF_BLKCNT_T_4)
1666 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1667 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1670 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1674 * Some file systems do not allocate a block for very
1675 * small files. But for non-empty file should report a
1679 uint64_t filesize = get_file_size_stat(sbuf);
1681 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
1685 result = get_file_size_stat(sbuf);
1688 if (fsp && fsp->initial_allocation_size)
1689 result = MAX(result,fsp->initial_allocation_size);
1691 result = smb_roundup(handle->conn, result);
1694 END_PROFILE(syscall_get_alloc_size);
1698 static int vfswrap_unlink(vfs_handle_struct *handle,
1699 const struct smb_filename *smb_fname)
1703 START_PROFILE(syscall_unlink);
1705 if (smb_fname->stream_name) {
1709 result = unlink(smb_fname->base_name);
1712 END_PROFILE(syscall_unlink);
1716 static int vfswrap_chmod(vfs_handle_struct *handle,
1717 const struct smb_filename *smb_fname,
1722 START_PROFILE(syscall_chmod);
1725 * We need to do this due to the fact that the default POSIX ACL
1726 * chmod modifies the ACL *mask* for the group owner, not the
1727 * group owner bits directly. JRA.
1732 int saved_errno = errno; /* We might get ENOSYS */
1733 result = SMB_VFS_CHMOD_ACL(handle->conn,
1737 END_PROFILE(syscall_chmod);
1740 /* Error - return the old errno. */
1741 errno = saved_errno;
1744 result = chmod(smb_fname->base_name, mode);
1745 END_PROFILE(syscall_chmod);
1749 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
1753 START_PROFILE(syscall_fchmod);
1756 * We need to do this due to the fact that the default POSIX ACL
1757 * chmod modifies the ACL *mask* for the group owner, not the
1758 * group owner bits directly. JRA.
1762 int saved_errno = errno; /* We might get ENOSYS */
1763 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
1764 END_PROFILE(syscall_fchmod);
1767 /* Error - return the old errno. */
1768 errno = saved_errno;
1771 #if defined(HAVE_FCHMOD)
1772 result = fchmod(fsp->fh->fd, mode);
1778 END_PROFILE(syscall_fchmod);
1782 static int vfswrap_chown(vfs_handle_struct *handle,
1783 const struct smb_filename *smb_fname,
1789 START_PROFILE(syscall_chown);
1790 result = chown(smb_fname->base_name, uid, gid);
1791 END_PROFILE(syscall_chown);
1795 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
1800 START_PROFILE(syscall_fchown);
1801 result = fchown(fsp->fh->fd, uid, gid);
1802 END_PROFILE(syscall_fchown);
1810 static int vfswrap_lchown(vfs_handle_struct *handle,
1811 const struct smb_filename *smb_fname,
1817 START_PROFILE(syscall_lchown);
1818 result = lchown(smb_fname->base_name, uid, gid);
1819 END_PROFILE(syscall_lchown);
1823 static int vfswrap_chdir(vfs_handle_struct *handle, const char *path)
1827 START_PROFILE(syscall_chdir);
1828 result = chdir(path);
1829 END_PROFILE(syscall_chdir);
1833 static char *vfswrap_getwd(vfs_handle_struct *handle)
1837 START_PROFILE(syscall_getwd);
1838 result = sys_getwd();
1839 END_PROFILE(syscall_getwd);
1843 /*********************************************************************
1844 nsec timestamp resolution call. Convert down to whatever the underlying
1845 system will support.
1846 **********************************************************************/
1848 static int vfswrap_ntimes(vfs_handle_struct *handle,
1849 const struct smb_filename *smb_fname,
1850 struct smb_file_time *ft)
1854 START_PROFILE(syscall_ntimes);
1856 if (smb_fname->stream_name) {
1862 if (null_timespec(ft->atime)) {
1863 ft->atime= smb_fname->st.st_ex_atime;
1866 if (null_timespec(ft->mtime)) {
1867 ft->mtime = smb_fname->st.st_ex_mtime;
1870 if (!null_timespec(ft->create_time)) {
1871 set_create_timespec_ea(handle->conn,
1876 if ((timespec_compare(&ft->atime,
1877 &smb_fname->st.st_ex_atime) == 0) &&
1878 (timespec_compare(&ft->mtime,
1879 &smb_fname->st.st_ex_mtime) == 0)) {
1884 #if defined(HAVE_UTIMENSAT)
1886 struct timespec ts[2];
1889 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
1891 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
1893 if (!((result == -1) && (errno == ENOSYS))) {
1897 #if defined(HAVE_UTIMES)
1899 struct timeval tv[2];
1900 tv[0] = convert_timespec_to_timeval(ft->atime);
1901 tv[1] = convert_timespec_to_timeval(ft->mtime);
1902 result = utimes(smb_fname->base_name, tv);
1904 result = utimes(smb_fname->base_name, NULL);
1906 if (!((result == -1) && (errno == ENOSYS))) {
1910 #if defined(HAVE_UTIME)
1912 struct utimbuf times;
1913 times.actime = convert_timespec_to_time_t(ft->atime);
1914 times.modtime = convert_timespec_to_time_t(ft->mtime);
1915 result = utime(smb_fname->base_name, ×);
1917 result = utime(smb_fname->base_name, NULL);
1919 if (!((result == -1) && (errno == ENOSYS))) {
1927 END_PROFILE(syscall_ntimes);
1931 /*********************************************************************
1932 A version of ftruncate that will write the space on disk if strict
1934 **********************************************************************/
1936 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1938 off_t space_to_write;
1939 uint64_t space_avail;
1940 uint64_t bsize,dfree,dsize;
1943 SMB_STRUCT_STAT *pst;
1945 status = vfs_stat_fsp(fsp);
1946 if (!NT_STATUS_IS_OK(status)) {
1949 pst = &fsp->fsp_name->st;
1952 if (S_ISFIFO(pst->st_ex_mode))
1956 if (pst->st_ex_size == len)
1959 /* Shrink - just ftruncate. */
1960 if (pst->st_ex_size > len)
1961 return ftruncate(fsp->fh->fd, len);
1963 space_to_write = len - pst->st_ex_size;
1965 /* for allocation try fallocate first. This can fail on some
1966 platforms e.g. when the filesystem doesn't support it and no
1967 emulation is being done by the libc (like on AIX with JFS1). In that
1968 case we do our own emulation. fallocate implementations can
1969 return ENOTSUP or EINVAL in cases like that. */
1970 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
1971 if (ret == -1 && errno == ENOSPC) {
1977 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
1978 "error %d. Falling back to slow manual allocation\n", errno));
1980 /* available disk space is enough or not? */
1982 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
1983 /* space_avail is 1k blocks */
1984 if (space_avail == (uint64_t)-1 ||
1985 ((uint64_t)space_to_write/1024 > space_avail) ) {
1990 /* Write out the real space on disk. */
1991 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
1999 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2002 SMB_STRUCT_STAT *pst;
2006 START_PROFILE(syscall_ftruncate);
2008 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2009 result = strict_allocate_ftruncate(handle, fsp, len);
2010 END_PROFILE(syscall_ftruncate);
2014 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2015 ftruncate if the system supports it. Then I discovered that
2016 you can have some filesystems that support ftruncate
2017 expansion and some that don't! On Linux fat can't do
2018 ftruncate extend but ext2 can. */
2020 result = ftruncate(fsp->fh->fd, len);
2022 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2023 extend a file with ftruncate. Provide alternate implementation
2026 /* Do an fstat to see if the file is longer than the requested
2027 size in which case the ftruncate above should have
2028 succeeded or shorter, in which case seek to len - 1 and
2029 write 1 byte of zero */
2030 status = vfs_stat_fsp(fsp);
2031 if (!NT_STATUS_IS_OK(status)) {
2035 /* We need to update the files_struct after successful ftruncate */
2040 pst = &fsp->fsp_name->st;
2043 if (S_ISFIFO(pst->st_ex_mode)) {
2049 if (pst->st_ex_size == len) {
2054 if (pst->st_ex_size > len) {
2055 /* the ftruncate should have worked */
2059 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2067 END_PROFILE(syscall_ftruncate);
2071 static int vfswrap_fallocate(vfs_handle_struct *handle,
2079 START_PROFILE(syscall_fallocate);
2081 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2083 * posix_fallocate returns 0 on success, errno on error
2084 * and doesn't set errno. Make it behave like fallocate()
2085 * which returns -1, and sets errno on failure.
2092 /* sys_fallocate handles filtering of unsupported mode flags */
2093 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2095 END_PROFILE(syscall_fallocate);
2099 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2103 START_PROFILE(syscall_fcntl_lock);
2105 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2107 "force process locks",
2109 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2112 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2113 END_PROFILE(syscall_fcntl_lock);
2117 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2118 uint32_t share_mode, uint32_t access_mask)
2120 START_PROFILE(syscall_kernel_flock);
2121 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2122 END_PROFILE(syscall_kernel_flock);
2126 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2131 START_PROFILE(syscall_fcntl_getlock);
2133 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2135 "force process locks",
2137 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2140 result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2141 END_PROFILE(syscall_fcntl_getlock);
2145 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2150 START_PROFILE(syscall_linux_setlease);
2152 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2153 result = linux_setlease(fsp->fh->fd, leasetype);
2157 END_PROFILE(syscall_linux_setlease);
2161 static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2165 START_PROFILE(syscall_symlink);
2166 result = symlink(oldpath, newpath);
2167 END_PROFILE(syscall_symlink);
2171 static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
2175 START_PROFILE(syscall_readlink);
2176 result = readlink(path, buf, bufsiz);
2177 END_PROFILE(syscall_readlink);
2181 static int vfswrap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2185 START_PROFILE(syscall_link);
2186 result = link(oldpath, newpath);
2187 END_PROFILE(syscall_link);
2191 static int vfswrap_mknod(vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev)
2195 START_PROFILE(syscall_mknod);
2196 result = sys_mknod(pathname, mode, dev);
2197 END_PROFILE(syscall_mknod);
2201 static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
2205 START_PROFILE(syscall_realpath);
2206 result = sys_realpath(path);
2207 END_PROFILE(syscall_realpath);
2211 static int vfswrap_chflags(vfs_handle_struct *handle, const char *path,
2215 return chflags(path, flags);
2222 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2223 const SMB_STRUCT_STAT *sbuf)
2227 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2231 key.devid = sbuf->st_ex_dev;
2232 key.inode = sbuf->st_ex_ino;
2233 /* key.extid is unused by default. */
2238 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2239 struct files_struct *fsp,
2240 const struct smb_filename *smb_fname,
2241 TALLOC_CTX *mem_ctx,
2242 unsigned int *pnum_streams,
2243 struct stream_struct **pstreams)
2245 SMB_STRUCT_STAT sbuf;
2246 struct stream_struct *tmp_streams = NULL;
2249 if ((fsp != NULL) && (fsp->is_directory)) {
2251 * No default streams on directories
2256 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2257 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2260 struct smb_filename smb_fname_cp;
2262 ZERO_STRUCT(smb_fname_cp);
2263 smb_fname_cp.base_name = discard_const_p(char,
2264 smb_fname->base_name);
2265 smb_fname_cp.flags = smb_fname->flags;
2267 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
2268 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2270 ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2272 sbuf = smb_fname_cp.st;
2276 return map_nt_error_from_unix(errno);
2279 if (S_ISDIR(sbuf.st_ex_mode)) {
2283 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2284 (*pnum_streams) + 1);
2285 if (tmp_streams == NULL) {
2286 return NT_STATUS_NO_MEMORY;
2288 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2289 if (tmp_streams[*pnum_streams].name == NULL) {
2290 return NT_STATUS_NO_MEMORY;
2292 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2293 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2296 *pstreams = tmp_streams;
2298 return NT_STATUS_OK;
2301 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2304 TALLOC_CTX *mem_ctx,
2308 * Don't fall back to get_real_filename so callers can differentiate
2309 * between a full directory scan and an actual case-insensitive stat.
2315 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2318 return handle->conn->connectpath;
2321 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2322 struct byte_range_lock *br_lck,
2323 struct lock_struct *plock,
2326 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2328 /* Note: blr is not used in the default implementation. */
2329 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2332 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2333 struct messaging_context *msg_ctx,
2334 struct byte_range_lock *br_lck,
2335 const struct lock_struct *plock)
2337 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2339 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2342 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2343 struct byte_range_lock *br_lck,
2344 struct lock_struct *plock)
2346 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2348 /* Note: blr is not used in the default implementation. */
2349 return brl_lock_cancel_default(br_lck, plock);
2352 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2354 struct lock_struct *plock)
2356 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2357 plock->lock_type == WRITE_LOCK);
2359 return strict_lock_default(fsp, plock);
2362 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2364 struct lock_struct *plock)
2366 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2367 plock->lock_type == WRITE_LOCK);
2369 strict_unlock_default(fsp, plock);
2372 /* NT ACL operations. */
2374 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2376 uint32_t security_info,
2377 TALLOC_CTX *mem_ctx,
2378 struct security_descriptor **ppdesc)
2382 START_PROFILE(fget_nt_acl);
2383 result = posix_fget_nt_acl(fsp, security_info,
2385 END_PROFILE(fget_nt_acl);
2389 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2390 const struct smb_filename *smb_fname,
2391 uint32_t security_info,
2392 TALLOC_CTX *mem_ctx,
2393 struct security_descriptor **ppdesc)
2397 START_PROFILE(get_nt_acl);
2398 result = posix_get_nt_acl(handle->conn,
2403 END_PROFILE(get_nt_acl);
2407 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2411 START_PROFILE(fset_nt_acl);
2412 result = set_nt_acl(fsp, security_info_sent, psd);
2413 END_PROFILE(fset_nt_acl);
2417 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2418 struct smb_filename *file,
2419 struct security_acl *sacl,
2420 uint32_t access_requested,
2421 uint32_t access_denied)
2423 return NT_STATUS_OK; /* Nothing to do here ... */
2426 static int vfswrap_chmod_acl(vfs_handle_struct *handle,
2427 const struct smb_filename *smb_fname,
2436 START_PROFILE(chmod_acl);
2437 result = chmod_acl(handle->conn, smb_fname->base_name, mode);
2438 END_PROFILE(chmod_acl);
2443 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2451 START_PROFILE(fchmod_acl);
2452 result = fchmod_acl(fsp, mode);
2453 END_PROFILE(fchmod_acl);
2458 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2460 SMB_ACL_TYPE_T type,
2461 TALLOC_CTX *mem_ctx)
2463 return sys_acl_get_file(handle, path_p, type, mem_ctx);
2466 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2468 TALLOC_CTX *mem_ctx)
2470 return sys_acl_get_fd(handle, fsp, mem_ctx);
2473 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2475 return sys_acl_set_file(handle, name, acltype, theacl);
2478 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2480 return sys_acl_set_fd(handle, fsp, theacl);
2483 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
2485 return sys_acl_delete_def_file(handle, path);
2488 /****************************************************************
2489 Extended attribute operations.
2490 *****************************************************************/
2492 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
2494 return getxattr(path, name, value, size);
2497 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2499 return fgetxattr(fsp->fh->fd, name, value, size);
2502 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
2504 return listxattr(path, list, size);
2507 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2509 return flistxattr(fsp->fh->fd, list, size);
2512 static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
2514 return removexattr(path, name);
2517 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2519 return fremovexattr(fsp->fh->fd, name);
2522 static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
2524 return setxattr(path, name, value, size, flags);
2527 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2529 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2532 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2537 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2538 const struct smb_filename *fname,
2539 SMB_STRUCT_STAT *sbuf)
2543 bool offline = false;
2545 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2549 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2550 #if defined(ENOTSUP)
2556 status = get_full_smb_filename(talloc_tos(), fname, &path);
2557 if (!NT_STATUS_IS_OK(status)) {
2558 errno = map_errno_from_nt_status(status);
2562 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2569 static int vfswrap_set_offline(struct vfs_handle_struct *handle,
2570 const struct smb_filename *fname)
2572 /* We don't know how to set offline bit by default, needs to be overriden in the vfs modules */
2573 #if defined(ENOTSUP)
2579 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2580 struct files_struct *fsp,
2581 TALLOC_CTX *mem_ctx,
2584 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2587 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2588 struct files_struct *fsp,
2589 const DATA_BLOB old_cookie,
2590 TALLOC_CTX *mem_ctx,
2591 DATA_BLOB *new_cookie)
2593 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2597 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2598 struct smb_request *smb1req,
2599 struct smbXsrv_open *op,
2600 const DATA_BLOB old_cookie,
2601 TALLOC_CTX *mem_ctx,
2602 struct files_struct **fsp,
2603 DATA_BLOB *new_cookie)
2605 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2606 old_cookie, mem_ctx,
2610 static struct vfs_fn_pointers vfs_default_fns = {
2611 /* Disk operations */
2613 .connect_fn = vfswrap_connect,
2614 .disconnect_fn = vfswrap_disconnect,
2615 .disk_free_fn = vfswrap_disk_free,
2616 .get_quota_fn = vfswrap_get_quota,
2617 .set_quota_fn = vfswrap_set_quota,
2618 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2619 .statvfs_fn = vfswrap_statvfs,
2620 .fs_capabilities_fn = vfswrap_fs_capabilities,
2621 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2622 .snap_check_path_fn = vfswrap_snap_check_path,
2623 .snap_create_fn = vfswrap_snap_create,
2624 .snap_delete_fn = vfswrap_snap_delete,
2626 /* Directory operations */
2628 .opendir_fn = vfswrap_opendir,
2629 .fdopendir_fn = vfswrap_fdopendir,
2630 .readdir_fn = vfswrap_readdir,
2631 .readdir_attr_fn = vfswrap_readdir_attr,
2632 .seekdir_fn = vfswrap_seekdir,
2633 .telldir_fn = vfswrap_telldir,
2634 .rewind_dir_fn = vfswrap_rewinddir,
2635 .mkdir_fn = vfswrap_mkdir,
2636 .rmdir_fn = vfswrap_rmdir,
2637 .closedir_fn = vfswrap_closedir,
2638 .init_search_op_fn = vfswrap_init_search_op,
2640 /* File operations */
2642 .open_fn = vfswrap_open,
2643 .create_file_fn = vfswrap_create_file,
2644 .close_fn = vfswrap_close,
2645 .read_fn = vfswrap_read,
2646 .pread_fn = vfswrap_pread,
2647 .pread_send_fn = vfswrap_pread_send,
2648 .pread_recv_fn = vfswrap_asys_ssize_t_recv,
2649 .write_fn = vfswrap_write,
2650 .pwrite_fn = vfswrap_pwrite,
2651 .pwrite_send_fn = vfswrap_pwrite_send,
2652 .pwrite_recv_fn = vfswrap_asys_ssize_t_recv,
2653 .lseek_fn = vfswrap_lseek,
2654 .sendfile_fn = vfswrap_sendfile,
2655 .recvfile_fn = vfswrap_recvfile,
2656 .rename_fn = vfswrap_rename,
2657 .fsync_fn = vfswrap_fsync,
2658 .fsync_send_fn = vfswrap_fsync_send,
2659 .fsync_recv_fn = vfswrap_asys_int_recv,
2660 .stat_fn = vfswrap_stat,
2661 .fstat_fn = vfswrap_fstat,
2662 .lstat_fn = vfswrap_lstat,
2663 .get_alloc_size_fn = vfswrap_get_alloc_size,
2664 .unlink_fn = vfswrap_unlink,
2665 .chmod_fn = vfswrap_chmod,
2666 .fchmod_fn = vfswrap_fchmod,
2667 .chown_fn = vfswrap_chown,
2668 .fchown_fn = vfswrap_fchown,
2669 .lchown_fn = vfswrap_lchown,
2670 .chdir_fn = vfswrap_chdir,
2671 .getwd_fn = vfswrap_getwd,
2672 .ntimes_fn = vfswrap_ntimes,
2673 .ftruncate_fn = vfswrap_ftruncate,
2674 .fallocate_fn = vfswrap_fallocate,
2675 .lock_fn = vfswrap_lock,
2676 .kernel_flock_fn = vfswrap_kernel_flock,
2677 .linux_setlease_fn = vfswrap_linux_setlease,
2678 .getlock_fn = vfswrap_getlock,
2679 .symlink_fn = vfswrap_symlink,
2680 .readlink_fn = vfswrap_readlink,
2681 .link_fn = vfswrap_link,
2682 .mknod_fn = vfswrap_mknod,
2683 .realpath_fn = vfswrap_realpath,
2684 .chflags_fn = vfswrap_chflags,
2685 .file_id_create_fn = vfswrap_file_id_create,
2686 .streaminfo_fn = vfswrap_streaminfo,
2687 .get_real_filename_fn = vfswrap_get_real_filename,
2688 .connectpath_fn = vfswrap_connectpath,
2689 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2690 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2691 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2692 .strict_lock_fn = vfswrap_strict_lock,
2693 .strict_unlock_fn = vfswrap_strict_unlock,
2694 .translate_name_fn = vfswrap_translate_name,
2695 .fsctl_fn = vfswrap_fsctl,
2696 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
2697 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
2698 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
2699 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
2700 .copy_chunk_send_fn = vfswrap_copy_chunk_send,
2701 .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
2702 .get_compression_fn = vfswrap_get_compression,
2703 .set_compression_fn = vfswrap_set_compression,
2705 /* NT ACL operations. */
2707 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2708 .get_nt_acl_fn = vfswrap_get_nt_acl,
2709 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2710 .audit_file_fn = vfswrap_audit_file,
2712 /* POSIX ACL operations. */
2714 .chmod_acl_fn = vfswrap_chmod_acl,
2715 .fchmod_acl_fn = vfswrap_fchmod_acl,
2717 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2718 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2719 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2720 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2721 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2722 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2723 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2725 /* EA operations. */
2726 .getxattr_fn = vfswrap_getxattr,
2727 .fgetxattr_fn = vfswrap_fgetxattr,
2728 .listxattr_fn = vfswrap_listxattr,
2729 .flistxattr_fn = vfswrap_flistxattr,
2730 .removexattr_fn = vfswrap_removexattr,
2731 .fremovexattr_fn = vfswrap_fremovexattr,
2732 .setxattr_fn = vfswrap_setxattr,
2733 .fsetxattr_fn = vfswrap_fsetxattr,
2735 /* aio operations */
2736 .aio_force_fn = vfswrap_aio_force,
2738 /* offline operations */
2739 .is_offline_fn = vfswrap_is_offline,
2740 .set_offline_fn = vfswrap_set_offline,
2742 /* durable handle operations */
2743 .durable_cookie_fn = vfswrap_durable_cookie,
2744 .durable_disconnect_fn = vfswrap_durable_disconnect,
2745 .durable_reconnect_fn = vfswrap_durable_reconnect,
2748 NTSTATUS vfs_default_init(void);
2749 NTSTATUS vfs_default_init(void)
2751 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
2752 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);