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 = (lp_posix_pathnames() ?
423 AT_SYMLINK_NOFOLLOW : 0);
424 int ret = fstatat(dirfd(dirp),
429 init_stat_ex_from_stat(sbuf,
431 lp_fake_directory_create_times(
432 SNUM(handle->conn)));
440 static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
441 const struct smb_filename *fname,
443 struct readdir_attr_data **attr_data)
445 return NT_STATUS_NOT_SUPPORTED;
448 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
450 START_PROFILE(syscall_seekdir);
451 seekdir(dirp, offset);
452 END_PROFILE(syscall_seekdir);
455 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
458 START_PROFILE(syscall_telldir);
459 result = telldir(dirp);
460 END_PROFILE(syscall_telldir);
464 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
466 START_PROFILE(syscall_rewinddir);
468 END_PROFILE(syscall_rewinddir);
471 static int vfswrap_mkdir(vfs_handle_struct *handle,
472 const struct smb_filename *smb_fname,
476 bool has_dacl = False;
477 const char *path = smb_fname->base_name;
480 START_PROFILE(syscall_mkdir);
482 if (lp_inherit_acls(SNUM(handle->conn))
483 && parent_dirname(talloc_tos(), path, &parent, NULL)
484 && (has_dacl = directory_has_default_acl(handle->conn, parent))) {
485 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
490 result = mkdir(path, mode);
492 if (result == 0 && !has_dacl) {
494 * We need to do this as the default behavior of POSIX ACLs
495 * is to set the mask to be the requested group permission
496 * bits, not the group permission bits to be the requested
497 * group permission bits. This is not what we want, as it will
498 * mess up any inherited ACL bits that were set. JRA.
500 int saved_errno = errno; /* We may get ENOSYS */
501 if ((SMB_VFS_CHMOD_ACL(handle->conn, path, mode) == -1) && (errno == ENOSYS))
505 END_PROFILE(syscall_mkdir);
509 static int vfswrap_rmdir(vfs_handle_struct *handle,
510 const struct smb_filename *smb_fname)
514 START_PROFILE(syscall_rmdir);
515 result = rmdir(smb_fname->base_name);
516 END_PROFILE(syscall_rmdir);
520 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
524 START_PROFILE(syscall_closedir);
525 result = closedir(dirp);
526 END_PROFILE(syscall_closedir);
530 static void vfswrap_init_search_op(vfs_handle_struct *handle,
533 /* Default behavior is a NOOP */
536 /* File operations */
538 static int vfswrap_open(vfs_handle_struct *handle,
539 struct smb_filename *smb_fname,
540 files_struct *fsp, int flags, mode_t mode)
544 START_PROFILE(syscall_open);
546 if (smb_fname->stream_name) {
551 result = open(smb_fname->base_name, flags, mode);
553 END_PROFILE(syscall_open);
557 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
558 struct smb_request *req,
559 uint16_t root_dir_fid,
560 struct smb_filename *smb_fname,
561 uint32_t access_mask,
562 uint32_t share_access,
563 uint32_t create_disposition,
564 uint32_t create_options,
565 uint32_t file_attributes,
566 uint32_t oplock_request,
567 struct smb2_lease *lease,
568 uint64_t allocation_size,
569 uint32_t private_flags,
570 struct security_descriptor *sd,
571 struct ea_list *ea_list,
572 files_struct **result,
574 const struct smb2_create_blobs *in_context_blobs,
575 struct smb2_create_blobs *out_context_blobs)
577 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
578 access_mask, share_access,
579 create_disposition, create_options,
580 file_attributes, oplock_request, lease,
581 allocation_size, private_flags,
583 pinfo, in_context_blobs, out_context_blobs);
586 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
590 START_PROFILE(syscall_close);
591 result = fd_close_posix(fsp);
592 END_PROFILE(syscall_close);
596 static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
600 START_PROFILE_BYTES(syscall_read, n);
601 result = sys_read(fsp->fh->fd, data, n);
602 END_PROFILE_BYTES(syscall_read);
606 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
607 size_t n, off_t offset)
611 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
612 START_PROFILE_BYTES(syscall_pread, n);
613 result = sys_pread(fsp->fh->fd, data, n, offset);
614 END_PROFILE_BYTES(syscall_pread);
616 if (result == -1 && errno == ESPIPE) {
617 /* Maintain the fiction that pipes can be seeked (sought?) on. */
618 result = SMB_VFS_READ(fsp, data, n);
622 #else /* HAVE_PREAD */
626 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
627 if (curr == -1 && errno == ESPIPE) {
628 /* Maintain the fiction that pipes can be seeked (sought?) on. */
629 result = SMB_VFS_READ(fsp, data, n);
634 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
639 result = SMB_VFS_READ(fsp, data, n);
642 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
645 #endif /* HAVE_PREAD */
650 static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
654 START_PROFILE_BYTES(syscall_write, n);
655 result = sys_write(fsp->fh->fd, data, n);
656 END_PROFILE_BYTES(syscall_write);
660 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
661 size_t n, off_t offset)
665 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
666 START_PROFILE_BYTES(syscall_pwrite, n);
667 result = sys_pwrite(fsp->fh->fd, data, n, offset);
668 END_PROFILE_BYTES(syscall_pwrite);
670 if (result == -1 && errno == ESPIPE) {
671 /* Maintain the fiction that pipes can be sought on. */
672 result = SMB_VFS_WRITE(fsp, data, n);
675 #else /* HAVE_PWRITE */
679 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
684 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
688 result = SMB_VFS_WRITE(fsp, data, n);
691 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
694 #endif /* HAVE_PWRITE */
699 static void vfswrap_asys_finished(struct tevent_context *ev,
700 struct tevent_fd *fde,
701 uint16_t flags, void *p);
703 static bool vfswrap_init_asys_ctx(struct smbd_server_connection *conn)
705 struct asys_context *ctx;
706 struct tevent_fd *fde;
710 if (conn->asys_ctx != NULL) {
714 ret = asys_context_init(&ctx, lp_aio_max_threads());
716 DEBUG(1, ("asys_context_init failed: %s\n", strerror(ret)));
720 fd = asys_signalfd(ctx);
722 ret = set_blocking(fd, false);
724 DBG_WARNING("set_blocking failed: %s\n", strerror(errno));
728 fde = tevent_add_fd(conn->ev_ctx, conn, fd, TEVENT_FD_READ,
729 vfswrap_asys_finished, ctx);
731 DEBUG(1, ("tevent_add_fd failed\n"));
735 conn->asys_ctx = ctx;
736 conn->asys_fde = fde;
740 asys_context_destroy(ctx);
744 struct vfswrap_asys_state {
745 struct asys_context *asys_ctx;
746 struct tevent_req *req;
748 struct vfs_aio_state vfs_aio_state;
749 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
750 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
753 static int vfswrap_asys_state_destructor(struct vfswrap_asys_state *s)
755 asys_cancel(s->asys_ctx, s->req);
759 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
761 struct tevent_context *ev,
762 struct files_struct *fsp,
764 size_t n, off_t offset)
766 struct tevent_req *req;
767 struct vfswrap_asys_state *state;
770 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
774 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
776 return tevent_req_post(req, ev);
778 state->asys_ctx = handle->conn->sconn->asys_ctx;
781 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
782 state->profile_bytes, n);
783 ret = asys_pread(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
785 tevent_req_error(req, ret);
786 return tevent_req_post(req, ev);
788 talloc_set_destructor(state, vfswrap_asys_state_destructor);
793 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
795 struct tevent_context *ev,
796 struct files_struct *fsp,
798 size_t n, off_t offset)
800 struct tevent_req *req;
801 struct vfswrap_asys_state *state;
804 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
808 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
810 return tevent_req_post(req, ev);
812 state->asys_ctx = handle->conn->sconn->asys_ctx;
815 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
816 state->profile_bytes, n);
817 ret = asys_pwrite(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
819 tevent_req_error(req, ret);
820 return tevent_req_post(req, ev);
822 talloc_set_destructor(state, vfswrap_asys_state_destructor);
827 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
829 struct tevent_context *ev,
830 struct files_struct *fsp)
832 struct tevent_req *req;
833 struct vfswrap_asys_state *state;
836 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
840 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
842 return tevent_req_post(req, ev);
844 state->asys_ctx = handle->conn->sconn->asys_ctx;
847 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
848 state->profile_basic);
849 ret = asys_fsync(state->asys_ctx, fsp->fh->fd, req);
851 tevent_req_error(req, ret);
852 return tevent_req_post(req, ev);
854 talloc_set_destructor(state, vfswrap_asys_state_destructor);
859 static void vfswrap_asys_finished(struct tevent_context *ev,
860 struct tevent_fd *fde,
861 uint16_t flags, void *p)
863 struct asys_context *asys_ctx = (struct asys_context *)p;
864 struct asys_result results[get_outstanding_aio_calls()];
867 if ((flags & TEVENT_FD_READ) == 0) {
871 ret = asys_results(asys_ctx, results, get_outstanding_aio_calls());
873 DEBUG(1, ("asys_results returned %s\n", strerror(-ret)));
877 for (i=0; i<ret; i++) {
878 struct asys_result *result = &results[i];
879 struct tevent_req *req;
880 struct vfswrap_asys_state *state;
882 if ((result->ret == -1) && (result->err == ECANCELED)) {
886 req = talloc_get_type_abort(result->private_data,
888 state = tevent_req_data(req, struct vfswrap_asys_state);
890 talloc_set_destructor(state, NULL);
892 SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
893 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
894 state->ret = result->ret;
895 state->vfs_aio_state.error = result->err;
896 state->vfs_aio_state.duration = result->duration;
897 tevent_req_defer_callback(req, ev);
898 tevent_req_done(req);
902 static ssize_t vfswrap_asys_ssize_t_recv(struct tevent_req *req,
903 struct vfs_aio_state *vfs_aio_state)
905 struct vfswrap_asys_state *state = tevent_req_data(
906 req, struct vfswrap_asys_state);
908 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
911 *vfs_aio_state = state->vfs_aio_state;
915 static int vfswrap_asys_int_recv(struct tevent_req *req,
916 struct vfs_aio_state *vfs_aio_state)
918 struct vfswrap_asys_state *state = tevent_req_data(
919 req, struct vfswrap_asys_state);
921 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
924 *vfs_aio_state = state->vfs_aio_state;
928 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
932 START_PROFILE(syscall_lseek);
934 /* Cope with 'stat' file opens. */
935 if (fsp->fh->fd != -1)
936 result = lseek(fsp->fh->fd, offset, whence);
939 * We want to maintain the fiction that we can seek
940 * on a fifo for file system purposes. This allows
941 * people to set up UNIX fifo's that feed data to Windows
945 if((result == -1) && (errno == ESPIPE)) {
950 END_PROFILE(syscall_lseek);
954 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
955 off_t offset, size_t n)
959 START_PROFILE_BYTES(syscall_sendfile, n);
960 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
961 END_PROFILE_BYTES(syscall_sendfile);
965 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
973 START_PROFILE_BYTES(syscall_recvfile, n);
974 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
975 END_PROFILE_BYTES(syscall_recvfile);
979 static int vfswrap_rename(vfs_handle_struct *handle,
980 const struct smb_filename *smb_fname_src,
981 const struct smb_filename *smb_fname_dst)
985 START_PROFILE(syscall_rename);
987 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
992 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
995 END_PROFILE(syscall_rename);
999 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
1004 START_PROFILE(syscall_fsync);
1005 result = fsync(fsp->fh->fd);
1006 END_PROFILE(syscall_fsync);
1013 static int vfswrap_stat(vfs_handle_struct *handle,
1014 struct smb_filename *smb_fname)
1018 START_PROFILE(syscall_stat);
1020 if (smb_fname->stream_name) {
1025 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1026 lp_fake_directory_create_times(SNUM(handle->conn)));
1028 END_PROFILE(syscall_stat);
1032 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1036 START_PROFILE(syscall_fstat);
1037 result = sys_fstat(fsp->fh->fd,
1038 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1039 END_PROFILE(syscall_fstat);
1043 static int vfswrap_lstat(vfs_handle_struct *handle,
1044 struct smb_filename *smb_fname)
1048 START_PROFILE(syscall_lstat);
1050 if (smb_fname->stream_name) {
1055 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1056 lp_fake_directory_create_times(SNUM(handle->conn)));
1058 END_PROFILE(syscall_lstat);
1062 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1064 enum vfs_translate_direction direction,
1065 TALLOC_CTX *mem_ctx,
1068 return NT_STATUS_NONE_MAPPED;
1072 * Implement the default fsctl operation.
1074 static bool vfswrap_logged_ioctl_message = false;
1076 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1077 struct files_struct *fsp,
1080 uint16_t req_flags, /* Needed for UNICODE ... */
1081 const uint8_t *_in_data,
1083 uint8_t **_out_data,
1084 uint32_t max_out_len,
1087 const char *in_data = (const char *)_in_data;
1088 char **out_data = (char **)_out_data;
1092 case FSCTL_SET_SPARSE:
1094 bool set_sparse = true;
1096 if (in_len >= 1 && in_data[0] == 0) {
1100 status = file_set_sparse(handle->conn, fsp, set_sparse);
1102 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1103 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1104 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1105 nt_errstr(status)));
1110 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1112 unsigned char objid[16];
1113 char *return_data = NULL;
1115 /* This should return the object-id on this file.
1116 * I think I'll make this be the inode+dev. JRA.
1119 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1120 fsp_fnum_dbg(fsp)));
1122 *out_len = MIN(max_out_len, 64);
1124 /* Hmmm, will this cause problems if less data asked for? */
1125 return_data = talloc_array(ctx, char, 64);
1126 if (return_data == NULL) {
1127 return NT_STATUS_NO_MEMORY;
1130 /* For backwards compatibility only store the dev/inode. */
1131 push_file_id_16(return_data, &fsp->file_id);
1132 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1133 push_file_id_16(return_data+32, &fsp->file_id);
1134 memset(return_data+48, 0, 16);
1135 *out_data = return_data;
1136 return NT_STATUS_OK;
1139 case FSCTL_GET_REPARSE_POINT:
1141 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1142 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1143 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1144 return NT_STATUS_NOT_A_REPARSE_POINT;
1147 case FSCTL_SET_REPARSE_POINT:
1149 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1150 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1151 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1152 return NT_STATUS_NOT_A_REPARSE_POINT;
1155 case FSCTL_GET_SHADOW_COPY_DATA:
1158 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1159 * and return their volume names. If max_data_count is 16, then it is just
1160 * asking for the number of volumes and length of the combined names.
1162 * pdata is the data allocated by our caller, but that uses
1163 * total_data_count (which is 0 in our case) rather than max_data_count.
1164 * Allocate the correct amount and return the pointer to let
1165 * it be deallocated when we return.
1167 struct shadow_copy_data *shadow_data = NULL;
1168 bool labels = False;
1169 uint32_t labels_data_count = 0;
1171 char *cur_pdata = NULL;
1173 if (max_out_len < 16) {
1174 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1176 return NT_STATUS_INVALID_PARAMETER;
1179 if (max_out_len > 16) {
1183 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1184 if (shadow_data == NULL) {
1185 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1186 return NT_STATUS_NO_MEMORY;
1190 * Call the VFS routine to actually do the work.
1192 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1195 /* broken module didn't set errno on error */
1196 status = NT_STATUS_UNSUCCESSFUL;
1198 status = map_nt_error_from_unix(errno);
1199 if (NT_STATUS_EQUAL(status,
1200 NT_STATUS_NOT_SUPPORTED)) {
1204 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1205 "connectpath %s, failed - %s.\n",
1206 fsp->conn->connectpath,
1207 nt_errstr(status)));
1208 TALLOC_FREE(shadow_data);
1212 labels_data_count = (shadow_data->num_volumes * 2 *
1213 sizeof(SHADOW_COPY_LABEL)) + 2;
1218 *out_len = 12 + labels_data_count;
1221 if (max_out_len < *out_len) {
1222 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1223 max_out_len, *out_len));
1224 TALLOC_FREE(shadow_data);
1225 return NT_STATUS_BUFFER_TOO_SMALL;
1228 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1229 if (cur_pdata == NULL) {
1230 TALLOC_FREE(shadow_data);
1231 return NT_STATUS_NO_MEMORY;
1234 *out_data = cur_pdata;
1236 /* num_volumes 4 bytes */
1237 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1240 /* num_labels 4 bytes */
1241 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1244 /* needed_data_count 4 bytes */
1245 SIVAL(cur_pdata, 8, labels_data_count);
1249 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1250 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1251 if (labels && shadow_data->labels) {
1252 for (i=0; i<shadow_data->num_volumes; i++) {
1254 status = srvstr_push(cur_pdata, req_flags,
1255 cur_pdata, shadow_data->labels[i],
1256 2 * sizeof(SHADOW_COPY_LABEL),
1257 STR_UNICODE|STR_TERMINATE, &len);
1258 if (!NT_STATUS_IS_OK(status)) {
1259 TALLOC_FREE(*out_data);
1260 TALLOC_FREE(shadow_data);
1263 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1264 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1268 TALLOC_FREE(shadow_data);
1270 return NT_STATUS_OK;
1273 case FSCTL_FIND_FILES_BY_SID:
1275 /* pretend this succeeded -
1277 * we have to send back a list with all files owned by this SID
1279 * but I have to check that --metze
1285 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1286 fsp_fnum_dbg(fsp)));
1289 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1290 return NT_STATUS_INVALID_PARAMETER;
1293 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1295 /* unknown 4 bytes: this is not the length of the sid :-( */
1296 /*unknown = IVAL(pdata,0);*/
1298 if (!sid_parse(_in_data + 4, sid_len, &sid)) {
1299 return NT_STATUS_INVALID_PARAMETER;
1301 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1303 if (!sid_to_uid(&sid, &uid)) {
1304 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1305 sid_string_dbg(&sid),
1306 (unsigned long)sid_len));
1310 /* we can take a look at the find source :-)
1312 * find ./ -uid $uid -name '*' is what we need here
1315 * and send 4bytes len and then NULL terminated unicode strings
1318 * but I don't know how to deal with the paged results
1319 * (maybe we can hang the result anywhere in the fsp struct)
1321 * but I don't know how to deal with the paged results
1322 * (maybe we can hang the result anywhere in the fsp struct)
1324 * we don't send all files at once
1325 * and at the next we should *not* start from the beginning,
1326 * so we have to cache the result
1331 /* this works for now... */
1332 return NT_STATUS_OK;
1335 case FSCTL_QUERY_ALLOCATED_RANGES:
1337 /* FIXME: This is just a dummy reply, telling that all of the
1338 * file is allocated. MKS cp needs that.
1339 * Adding the real allocated ranges via FIEMAP on Linux
1340 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1341 * this FSCTL correct for sparse files.
1343 uint64_t offset, length;
1344 char *out_data_tmp = NULL;
1347 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1349 return NT_STATUS_INVALID_PARAMETER;
1352 if (max_out_len < 16) {
1353 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1355 return NT_STATUS_INVALID_PARAMETER;
1358 offset = BVAL(in_data,0);
1359 length = BVAL(in_data,8);
1361 if (offset + length < offset) {
1362 /* No 64-bit integer wrap. */
1363 return NT_STATUS_INVALID_PARAMETER;
1366 /* Shouldn't this be SMB_VFS_STAT ... ? */
1367 status = vfs_stat_fsp(fsp);
1368 if (!NT_STATUS_IS_OK(status)) {
1373 out_data_tmp = talloc_array(ctx, char, *out_len);
1374 if (out_data_tmp == NULL) {
1375 DEBUG(10, ("unable to allocate memory for response\n"));
1376 return NT_STATUS_NO_MEMORY;
1379 if (offset > fsp->fsp_name->st.st_ex_size ||
1380 fsp->fsp_name->st.st_ex_size == 0 ||
1382 memset(out_data_tmp, 0, *out_len);
1384 uint64_t end = offset + length;
1385 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1386 SBVAL(out_data_tmp, 0, 0);
1387 SBVAL(out_data_tmp, 8, end);
1390 *out_data = out_data_tmp;
1392 return NT_STATUS_OK;
1395 case FSCTL_IS_VOLUME_DIRTY:
1397 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1398 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1400 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1401 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1403 return NT_STATUS_INVALID_PARAMETER;
1408 * Only print once ... unfortunately there could be lots of
1409 * different FSCTLs that are called.
1411 if (!vfswrap_logged_ioctl_message) {
1412 vfswrap_logged_ioctl_message = true;
1413 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1414 __func__, function));
1418 return NT_STATUS_NOT_SUPPORTED;
1421 struct vfs_cc_state {
1426 static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *handle,
1427 TALLOC_CTX *mem_ctx,
1428 struct tevent_context *ev,
1429 struct files_struct *src_fsp,
1431 struct files_struct *dest_fsp,
1435 struct tevent_req *req;
1436 struct vfs_cc_state *vfs_cc_state;
1439 DEBUG(10, ("performing server side copy chunk of length %lu\n",
1440 (unsigned long)num));
1442 req = tevent_req_create(mem_ctx, &vfs_cc_state, struct vfs_cc_state);
1447 vfs_cc_state->buf = talloc_array(vfs_cc_state, uint8_t,
1448 MIN(num, 8*1024*1024));
1449 if (tevent_req_nomem(vfs_cc_state->buf, req)) {
1450 return tevent_req_post(req, ev);
1453 status = vfs_stat_fsp(src_fsp);
1454 if (tevent_req_nterror(req, status)) {
1455 return tevent_req_post(req, ev);
1458 if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
1460 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1461 * If the SourceOffset or SourceOffset + Length extends beyond
1462 * the end of file, the server SHOULD<240> treat this as a
1463 * STATUS_END_OF_FILE error.
1465 * <240> Section 3.3.5.15.6: Windows servers will return
1466 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1468 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1469 return tevent_req_post(req, ev);
1472 /* could use 2.6.33+ sendfile here to do this in kernel */
1473 while (vfs_cc_state->copied < num) {
1475 struct lock_struct lck;
1478 off_t this_num = MIN(talloc_array_length(vfs_cc_state->buf),
1479 num - vfs_cc_state->copied);
1481 if (src_fsp->op == NULL) {
1482 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1483 return tevent_req_post(req, ev);
1485 init_strict_lock_struct(src_fsp,
1486 src_fsp->op->global->open_persistent_id,
1492 if (!SMB_VFS_STRICT_LOCK(src_fsp->conn, src_fsp, &lck)) {
1493 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1494 return tevent_req_post(req, ev);
1497 ret = SMB_VFS_PREAD(src_fsp, vfs_cc_state->buf,
1500 saved_errno = errno;
1503 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1506 errno = saved_errno;
1507 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1508 return tevent_req_post(req, ev);
1510 if (ret != this_num) {
1511 /* zero tolerance for short reads */
1512 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1513 return tevent_req_post(req, ev);
1518 if (dest_fsp->op == NULL) {
1519 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1520 return tevent_req_post(req, ev);
1523 init_strict_lock_struct(dest_fsp,
1524 dest_fsp->op->global->open_persistent_id,
1530 if (!SMB_VFS_STRICT_LOCK(dest_fsp->conn, dest_fsp, &lck)) {
1531 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1532 return tevent_req_post(req, ev);
1535 ret = SMB_VFS_PWRITE(dest_fsp, vfs_cc_state->buf,
1536 this_num, dest_off);
1538 saved_errno = errno;
1541 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1544 errno = saved_errno;
1545 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1546 return tevent_req_post(req, ev);
1548 if (ret != this_num) {
1549 /* zero tolerance for short writes */
1550 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1551 return tevent_req_post(req, ev);
1555 vfs_cc_state->copied += this_num;
1558 tevent_req_done(req);
1559 return tevent_req_post(req, ev);
1562 static NTSTATUS vfswrap_copy_chunk_recv(struct vfs_handle_struct *handle,
1563 struct tevent_req *req,
1566 struct vfs_cc_state *vfs_cc_state = tevent_req_data(req,
1567 struct vfs_cc_state);
1570 if (tevent_req_is_nterror(req, &status)) {
1571 DEBUG(2, ("server side copy chunk failed: %s\n",
1572 nt_errstr(status)));
1574 tevent_req_received(req);
1578 *copied = vfs_cc_state->copied;
1579 DEBUG(10, ("server side copy chunk copied %lu\n",
1580 (unsigned long)*copied));
1581 tevent_req_received(req);
1583 return NT_STATUS_OK;
1586 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1587 TALLOC_CTX *mem_ctx,
1588 struct files_struct *fsp,
1589 struct smb_filename *smb_fname,
1590 uint16_t *_compression_fmt)
1592 return NT_STATUS_INVALID_DEVICE_REQUEST;
1595 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1596 TALLOC_CTX *mem_ctx,
1597 struct files_struct *fsp,
1598 uint16_t compression_fmt)
1600 return NT_STATUS_INVALID_DEVICE_REQUEST;
1603 /********************************************************************
1604 Given a stat buffer return the allocated size on disk, taking into
1605 account sparse files.
1606 ********************************************************************/
1607 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1608 struct files_struct *fsp,
1609 const SMB_STRUCT_STAT *sbuf)
1613 START_PROFILE(syscall_get_alloc_size);
1615 if(S_ISDIR(sbuf->st_ex_mode)) {
1620 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1621 /* The type of st_blocksize is blkcnt_t which *MUST* be
1622 signed (according to POSIX) and can be less than 64-bits.
1623 Ensure when we're converting to 64 bits wide we don't
1625 #if defined(SIZEOF_BLKCNT_T_8)
1626 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1627 #elif defined(SIZEOF_BLKCNT_T_4)
1629 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1630 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1633 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1637 * Some file systems do not allocate a block for very
1638 * small files. But for non-empty file should report a
1642 uint64_t filesize = get_file_size_stat(sbuf);
1644 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
1648 result = get_file_size_stat(sbuf);
1651 if (fsp && fsp->initial_allocation_size)
1652 result = MAX(result,fsp->initial_allocation_size);
1654 result = smb_roundup(handle->conn, result);
1657 END_PROFILE(syscall_get_alloc_size);
1661 static int vfswrap_unlink(vfs_handle_struct *handle,
1662 const struct smb_filename *smb_fname)
1666 START_PROFILE(syscall_unlink);
1668 if (smb_fname->stream_name) {
1672 result = unlink(smb_fname->base_name);
1675 END_PROFILE(syscall_unlink);
1679 static int vfswrap_chmod(vfs_handle_struct *handle,
1680 const struct smb_filename *smb_fname,
1685 START_PROFILE(syscall_chmod);
1688 * We need to do this due to the fact that the default POSIX ACL
1689 * chmod modifies the ACL *mask* for the group owner, not the
1690 * group owner bits directly. JRA.
1695 int saved_errno = errno; /* We might get ENOSYS */
1696 result = SMB_VFS_CHMOD_ACL(handle->conn,
1697 smb_fname->base_name,
1700 END_PROFILE(syscall_chmod);
1703 /* Error - return the old errno. */
1704 errno = saved_errno;
1707 result = chmod(smb_fname->base_name, mode);
1708 END_PROFILE(syscall_chmod);
1712 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
1716 START_PROFILE(syscall_fchmod);
1719 * We need to do this due to the fact that the default POSIX ACL
1720 * chmod modifies the ACL *mask* for the group owner, not the
1721 * group owner bits directly. JRA.
1725 int saved_errno = errno; /* We might get ENOSYS */
1726 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
1727 END_PROFILE(syscall_fchmod);
1730 /* Error - return the old errno. */
1731 errno = saved_errno;
1734 #if defined(HAVE_FCHMOD)
1735 result = fchmod(fsp->fh->fd, mode);
1741 END_PROFILE(syscall_fchmod);
1745 static int vfswrap_chown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1749 START_PROFILE(syscall_chown);
1750 result = chown(path, uid, gid);
1751 END_PROFILE(syscall_chown);
1755 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
1760 START_PROFILE(syscall_fchown);
1761 result = fchown(fsp->fh->fd, uid, gid);
1762 END_PROFILE(syscall_fchown);
1770 static int vfswrap_lchown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1774 START_PROFILE(syscall_lchown);
1775 result = lchown(path, uid, gid);
1776 END_PROFILE(syscall_lchown);
1780 static int vfswrap_chdir(vfs_handle_struct *handle, const char *path)
1784 START_PROFILE(syscall_chdir);
1785 result = chdir(path);
1786 END_PROFILE(syscall_chdir);
1790 static char *vfswrap_getwd(vfs_handle_struct *handle)
1794 START_PROFILE(syscall_getwd);
1795 result = sys_getwd();
1796 END_PROFILE(syscall_getwd);
1800 /*********************************************************************
1801 nsec timestamp resolution call. Convert down to whatever the underlying
1802 system will support.
1803 **********************************************************************/
1805 static int vfswrap_ntimes(vfs_handle_struct *handle,
1806 const struct smb_filename *smb_fname,
1807 struct smb_file_time *ft)
1811 START_PROFILE(syscall_ntimes);
1813 if (smb_fname->stream_name) {
1819 if (null_timespec(ft->atime)) {
1820 ft->atime= smb_fname->st.st_ex_atime;
1823 if (null_timespec(ft->mtime)) {
1824 ft->mtime = smb_fname->st.st_ex_mtime;
1827 if (!null_timespec(ft->create_time)) {
1828 set_create_timespec_ea(handle->conn,
1833 if ((timespec_compare(&ft->atime,
1834 &smb_fname->st.st_ex_atime) == 0) &&
1835 (timespec_compare(&ft->mtime,
1836 &smb_fname->st.st_ex_mtime) == 0)) {
1841 #if defined(HAVE_UTIMENSAT)
1843 struct timespec ts[2];
1846 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
1848 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
1850 if (!((result == -1) && (errno == ENOSYS))) {
1854 #if defined(HAVE_UTIMES)
1856 struct timeval tv[2];
1857 tv[0] = convert_timespec_to_timeval(ft->atime);
1858 tv[1] = convert_timespec_to_timeval(ft->mtime);
1859 result = utimes(smb_fname->base_name, tv);
1861 result = utimes(smb_fname->base_name, NULL);
1863 if (!((result == -1) && (errno == ENOSYS))) {
1867 #if defined(HAVE_UTIME)
1869 struct utimbuf times;
1870 times.actime = convert_timespec_to_time_t(ft->atime);
1871 times.modtime = convert_timespec_to_time_t(ft->mtime);
1872 result = utime(smb_fname->base_name, ×);
1874 result = utime(smb_fname->base_name, NULL);
1876 if (!((result == -1) && (errno == ENOSYS))) {
1884 END_PROFILE(syscall_ntimes);
1888 /*********************************************************************
1889 A version of ftruncate that will write the space on disk if strict
1891 **********************************************************************/
1893 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1895 off_t space_to_write;
1896 uint64_t space_avail;
1897 uint64_t bsize,dfree,dsize;
1900 SMB_STRUCT_STAT *pst;
1902 status = vfs_stat_fsp(fsp);
1903 if (!NT_STATUS_IS_OK(status)) {
1906 pst = &fsp->fsp_name->st;
1909 if (S_ISFIFO(pst->st_ex_mode))
1913 if (pst->st_ex_size == len)
1916 /* Shrink - just ftruncate. */
1917 if (pst->st_ex_size > len)
1918 return ftruncate(fsp->fh->fd, len);
1920 space_to_write = len - pst->st_ex_size;
1922 /* for allocation try fallocate first. This can fail on some
1923 platforms e.g. when the filesystem doesn't support it and no
1924 emulation is being done by the libc (like on AIX with JFS1). In that
1925 case we do our own emulation. fallocate implementations can
1926 return ENOTSUP or EINVAL in cases like that. */
1927 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
1928 if (ret == -1 && errno == ENOSPC) {
1934 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
1935 "error %d. Falling back to slow manual allocation\n", errno));
1937 /* available disk space is enough or not? */
1938 space_avail = get_dfree_info(fsp->conn,
1939 fsp->fsp_name->base_name,
1940 &bsize, &dfree, &dsize);
1941 /* space_avail is 1k blocks */
1942 if (space_avail == (uint64_t)-1 ||
1943 ((uint64_t)space_to_write/1024 > space_avail) ) {
1948 /* Write out the real space on disk. */
1949 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
1957 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1960 SMB_STRUCT_STAT *pst;
1964 START_PROFILE(syscall_ftruncate);
1966 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
1967 result = strict_allocate_ftruncate(handle, fsp, len);
1968 END_PROFILE(syscall_ftruncate);
1972 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
1973 ftruncate if the system supports it. Then I discovered that
1974 you can have some filesystems that support ftruncate
1975 expansion and some that don't! On Linux fat can't do
1976 ftruncate extend but ext2 can. */
1978 result = ftruncate(fsp->fh->fd, len);
1980 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
1981 extend a file with ftruncate. Provide alternate implementation
1984 /* Do an fstat to see if the file is longer than the requested
1985 size in which case the ftruncate above should have
1986 succeeded or shorter, in which case seek to len - 1 and
1987 write 1 byte of zero */
1988 status = vfs_stat_fsp(fsp);
1989 if (!NT_STATUS_IS_OK(status)) {
1993 /* We need to update the files_struct after successful ftruncate */
1998 pst = &fsp->fsp_name->st;
2001 if (S_ISFIFO(pst->st_ex_mode)) {
2007 if (pst->st_ex_size == len) {
2012 if (pst->st_ex_size > len) {
2013 /* the ftruncate should have worked */
2017 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2025 END_PROFILE(syscall_ftruncate);
2029 static int vfswrap_fallocate(vfs_handle_struct *handle,
2037 START_PROFILE(syscall_fallocate);
2039 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2041 * posix_fallocate returns 0 on success, errno on error
2042 * and doesn't set errno. Make it behave like fallocate()
2043 * which returns -1, and sets errno on failure.
2050 /* sys_fallocate handles filtering of unsupported mode flags */
2051 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2053 END_PROFILE(syscall_fallocate);
2057 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2061 START_PROFILE(syscall_fcntl_lock);
2062 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2063 END_PROFILE(syscall_fcntl_lock);
2067 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2068 uint32_t share_mode, uint32_t access_mask)
2070 START_PROFILE(syscall_kernel_flock);
2071 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2072 END_PROFILE(syscall_kernel_flock);
2076 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2080 START_PROFILE(syscall_fcntl_getlock);
2081 result = fcntl_getlock(fsp->fh->fd, poffset, pcount, ptype, ppid);
2082 END_PROFILE(syscall_fcntl_getlock);
2086 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2091 START_PROFILE(syscall_linux_setlease);
2093 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2094 result = linux_setlease(fsp->fh->fd, leasetype);
2098 END_PROFILE(syscall_linux_setlease);
2102 static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2106 START_PROFILE(syscall_symlink);
2107 result = symlink(oldpath, newpath);
2108 END_PROFILE(syscall_symlink);
2112 static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
2116 START_PROFILE(syscall_readlink);
2117 result = readlink(path, buf, bufsiz);
2118 END_PROFILE(syscall_readlink);
2122 static int vfswrap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2126 START_PROFILE(syscall_link);
2127 result = link(oldpath, newpath);
2128 END_PROFILE(syscall_link);
2132 static int vfswrap_mknod(vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev)
2136 START_PROFILE(syscall_mknod);
2137 result = sys_mknod(pathname, mode, dev);
2138 END_PROFILE(syscall_mknod);
2142 static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
2146 START_PROFILE(syscall_realpath);
2147 result = sys_realpath(path);
2148 END_PROFILE(syscall_realpath);
2152 static int vfswrap_chflags(vfs_handle_struct *handle, const char *path,
2156 return chflags(path, flags);
2163 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2164 const SMB_STRUCT_STAT *sbuf)
2168 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2172 key.devid = sbuf->st_ex_dev;
2173 key.inode = sbuf->st_ex_ino;
2174 /* key.extid is unused by default. */
2179 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2180 struct files_struct *fsp,
2182 TALLOC_CTX *mem_ctx,
2183 unsigned int *pnum_streams,
2184 struct stream_struct **pstreams)
2186 SMB_STRUCT_STAT sbuf;
2187 struct stream_struct *tmp_streams = NULL;
2190 if ((fsp != NULL) && (fsp->is_directory)) {
2192 * No default streams on directories
2197 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2198 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2201 struct smb_filename smb_fname;
2203 ZERO_STRUCT(smb_fname);
2204 smb_fname.base_name = discard_const_p(char, fname);
2206 if (lp_posix_pathnames()) {
2207 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname);
2209 ret = SMB_VFS_STAT(handle->conn, &smb_fname);
2211 sbuf = smb_fname.st;
2215 return map_nt_error_from_unix(errno);
2218 if (S_ISDIR(sbuf.st_ex_mode)) {
2222 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2223 (*pnum_streams) + 1);
2224 if (tmp_streams == NULL) {
2225 return NT_STATUS_NO_MEMORY;
2227 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2228 if (tmp_streams[*pnum_streams].name == NULL) {
2229 return NT_STATUS_NO_MEMORY;
2231 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2232 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2235 *pstreams = tmp_streams;
2237 return NT_STATUS_OK;
2240 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2243 TALLOC_CTX *mem_ctx,
2247 * Don't fall back to get_real_filename so callers can differentiate
2248 * between a full directory scan and an actual case-insensitive stat.
2254 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2257 return handle->conn->connectpath;
2260 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2261 struct byte_range_lock *br_lck,
2262 struct lock_struct *plock,
2265 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2267 /* Note: blr is not used in the default implementation. */
2268 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2271 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2272 struct messaging_context *msg_ctx,
2273 struct byte_range_lock *br_lck,
2274 const struct lock_struct *plock)
2276 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2278 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2281 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2282 struct byte_range_lock *br_lck,
2283 struct lock_struct *plock)
2285 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2287 /* Note: blr is not used in the default implementation. */
2288 return brl_lock_cancel_default(br_lck, plock);
2291 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2293 struct lock_struct *plock)
2295 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2296 plock->lock_type == WRITE_LOCK);
2298 return strict_lock_default(fsp, plock);
2301 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2303 struct lock_struct *plock)
2305 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2306 plock->lock_type == WRITE_LOCK);
2308 strict_unlock_default(fsp, plock);
2311 /* NT ACL operations. */
2313 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2315 uint32_t security_info,
2316 TALLOC_CTX *mem_ctx,
2317 struct security_descriptor **ppdesc)
2321 START_PROFILE(fget_nt_acl);
2322 result = posix_fget_nt_acl(fsp, security_info,
2324 END_PROFILE(fget_nt_acl);
2328 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2329 const struct smb_filename *smb_fname,
2330 uint32_t security_info,
2331 TALLOC_CTX *mem_ctx,
2332 struct security_descriptor **ppdesc)
2336 START_PROFILE(get_nt_acl);
2337 result = posix_get_nt_acl(handle->conn,
2338 smb_fname->base_name,
2342 END_PROFILE(get_nt_acl);
2346 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2350 START_PROFILE(fset_nt_acl);
2351 result = set_nt_acl(fsp, security_info_sent, psd);
2352 END_PROFILE(fset_nt_acl);
2356 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2357 struct smb_filename *file,
2358 struct security_acl *sacl,
2359 uint32_t access_requested,
2360 uint32_t access_denied)
2362 return NT_STATUS_OK; /* Nothing to do here ... */
2365 static int vfswrap_chmod_acl(vfs_handle_struct *handle, const char *name, mode_t mode)
2373 START_PROFILE(chmod_acl);
2374 result = chmod_acl(handle->conn, name, mode);
2375 END_PROFILE(chmod_acl);
2380 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2388 START_PROFILE(fchmod_acl);
2389 result = fchmod_acl(fsp, mode);
2390 END_PROFILE(fchmod_acl);
2395 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2397 SMB_ACL_TYPE_T type,
2398 TALLOC_CTX *mem_ctx)
2400 return sys_acl_get_file(handle, path_p, type, mem_ctx);
2403 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2405 TALLOC_CTX *mem_ctx)
2407 return sys_acl_get_fd(handle, fsp, mem_ctx);
2410 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2412 return sys_acl_set_file(handle, name, acltype, theacl);
2415 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2417 return sys_acl_set_fd(handle, fsp, theacl);
2420 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
2422 return sys_acl_delete_def_file(handle, path);
2425 /****************************************************************
2426 Extended attribute operations.
2427 *****************************************************************/
2429 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
2431 return getxattr(path, name, value, size);
2434 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2436 return fgetxattr(fsp->fh->fd, name, value, size);
2439 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
2441 return listxattr(path, list, size);
2444 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2446 return flistxattr(fsp->fh->fd, list, size);
2449 static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
2451 return removexattr(path, name);
2454 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2456 return fremovexattr(fsp->fh->fd, name);
2459 static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
2461 return setxattr(path, name, value, size, flags);
2464 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2466 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2469 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2474 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2475 const struct smb_filename *fname,
2476 SMB_STRUCT_STAT *sbuf)
2480 bool offline = false;
2482 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2486 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2487 #if defined(ENOTSUP)
2493 status = get_full_smb_filename(talloc_tos(), fname, &path);
2494 if (!NT_STATUS_IS_OK(status)) {
2495 errno = map_errno_from_nt_status(status);
2499 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2506 static int vfswrap_set_offline(struct vfs_handle_struct *handle,
2507 const struct smb_filename *fname)
2509 /* We don't know how to set offline bit by default, needs to be overriden in the vfs modules */
2510 #if defined(ENOTSUP)
2516 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2517 struct files_struct *fsp,
2518 TALLOC_CTX *mem_ctx,
2521 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2524 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2525 struct files_struct *fsp,
2526 const DATA_BLOB old_cookie,
2527 TALLOC_CTX *mem_ctx,
2528 DATA_BLOB *new_cookie)
2530 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2534 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2535 struct smb_request *smb1req,
2536 struct smbXsrv_open *op,
2537 const DATA_BLOB old_cookie,
2538 TALLOC_CTX *mem_ctx,
2539 struct files_struct **fsp,
2540 DATA_BLOB *new_cookie)
2542 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2543 old_cookie, mem_ctx,
2547 static struct vfs_fn_pointers vfs_default_fns = {
2548 /* Disk operations */
2550 .connect_fn = vfswrap_connect,
2551 .disconnect_fn = vfswrap_disconnect,
2552 .disk_free_fn = vfswrap_disk_free,
2553 .get_quota_fn = vfswrap_get_quota,
2554 .set_quota_fn = vfswrap_set_quota,
2555 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2556 .statvfs_fn = vfswrap_statvfs,
2557 .fs_capabilities_fn = vfswrap_fs_capabilities,
2558 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2559 .snap_check_path_fn = vfswrap_snap_check_path,
2560 .snap_create_fn = vfswrap_snap_create,
2561 .snap_delete_fn = vfswrap_snap_delete,
2563 /* Directory operations */
2565 .opendir_fn = vfswrap_opendir,
2566 .fdopendir_fn = vfswrap_fdopendir,
2567 .readdir_fn = vfswrap_readdir,
2568 .readdir_attr_fn = vfswrap_readdir_attr,
2569 .seekdir_fn = vfswrap_seekdir,
2570 .telldir_fn = vfswrap_telldir,
2571 .rewind_dir_fn = vfswrap_rewinddir,
2572 .mkdir_fn = vfswrap_mkdir,
2573 .rmdir_fn = vfswrap_rmdir,
2574 .closedir_fn = vfswrap_closedir,
2575 .init_search_op_fn = vfswrap_init_search_op,
2577 /* File operations */
2579 .open_fn = vfswrap_open,
2580 .create_file_fn = vfswrap_create_file,
2581 .close_fn = vfswrap_close,
2582 .read_fn = vfswrap_read,
2583 .pread_fn = vfswrap_pread,
2584 .pread_send_fn = vfswrap_pread_send,
2585 .pread_recv_fn = vfswrap_asys_ssize_t_recv,
2586 .write_fn = vfswrap_write,
2587 .pwrite_fn = vfswrap_pwrite,
2588 .pwrite_send_fn = vfswrap_pwrite_send,
2589 .pwrite_recv_fn = vfswrap_asys_ssize_t_recv,
2590 .lseek_fn = vfswrap_lseek,
2591 .sendfile_fn = vfswrap_sendfile,
2592 .recvfile_fn = vfswrap_recvfile,
2593 .rename_fn = vfswrap_rename,
2594 .fsync_fn = vfswrap_fsync,
2595 .fsync_send_fn = vfswrap_fsync_send,
2596 .fsync_recv_fn = vfswrap_asys_int_recv,
2597 .stat_fn = vfswrap_stat,
2598 .fstat_fn = vfswrap_fstat,
2599 .lstat_fn = vfswrap_lstat,
2600 .get_alloc_size_fn = vfswrap_get_alloc_size,
2601 .unlink_fn = vfswrap_unlink,
2602 .chmod_fn = vfswrap_chmod,
2603 .fchmod_fn = vfswrap_fchmod,
2604 .chown_fn = vfswrap_chown,
2605 .fchown_fn = vfswrap_fchown,
2606 .lchown_fn = vfswrap_lchown,
2607 .chdir_fn = vfswrap_chdir,
2608 .getwd_fn = vfswrap_getwd,
2609 .ntimes_fn = vfswrap_ntimes,
2610 .ftruncate_fn = vfswrap_ftruncate,
2611 .fallocate_fn = vfswrap_fallocate,
2612 .lock_fn = vfswrap_lock,
2613 .kernel_flock_fn = vfswrap_kernel_flock,
2614 .linux_setlease_fn = vfswrap_linux_setlease,
2615 .getlock_fn = vfswrap_getlock,
2616 .symlink_fn = vfswrap_symlink,
2617 .readlink_fn = vfswrap_readlink,
2618 .link_fn = vfswrap_link,
2619 .mknod_fn = vfswrap_mknod,
2620 .realpath_fn = vfswrap_realpath,
2621 .chflags_fn = vfswrap_chflags,
2622 .file_id_create_fn = vfswrap_file_id_create,
2623 .streaminfo_fn = vfswrap_streaminfo,
2624 .get_real_filename_fn = vfswrap_get_real_filename,
2625 .connectpath_fn = vfswrap_connectpath,
2626 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2627 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2628 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2629 .strict_lock_fn = vfswrap_strict_lock,
2630 .strict_unlock_fn = vfswrap_strict_unlock,
2631 .translate_name_fn = vfswrap_translate_name,
2632 .fsctl_fn = vfswrap_fsctl,
2633 .copy_chunk_send_fn = vfswrap_copy_chunk_send,
2634 .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
2635 .get_compression_fn = vfswrap_get_compression,
2636 .set_compression_fn = vfswrap_set_compression,
2638 /* NT ACL operations. */
2640 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2641 .get_nt_acl_fn = vfswrap_get_nt_acl,
2642 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2643 .audit_file_fn = vfswrap_audit_file,
2645 /* POSIX ACL operations. */
2647 .chmod_acl_fn = vfswrap_chmod_acl,
2648 .fchmod_acl_fn = vfswrap_fchmod_acl,
2650 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2651 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2652 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2653 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2654 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2655 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2656 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2658 /* EA operations. */
2659 .getxattr_fn = vfswrap_getxattr,
2660 .fgetxattr_fn = vfswrap_fgetxattr,
2661 .listxattr_fn = vfswrap_listxattr,
2662 .flistxattr_fn = vfswrap_flistxattr,
2663 .removexattr_fn = vfswrap_removexattr,
2664 .fremovexattr_fn = vfswrap_fremovexattr,
2665 .setxattr_fn = vfswrap_setxattr,
2666 .fsetxattr_fn = vfswrap_fsetxattr,
2668 /* aio operations */
2669 .aio_force_fn = vfswrap_aio_force,
2671 /* offline operations */
2672 .is_offline_fn = vfswrap_is_offline,
2673 .set_offline_fn = vfswrap_set_offline,
2675 /* durable handle operations */
2676 .durable_cookie_fn = vfswrap_durable_cookie,
2677 .durable_disconnect_fn = vfswrap_durable_disconnect,
2678 .durable_reconnect_fn = vfswrap_durable_reconnect,
2681 NTSTATUS vfs_default_init(void);
2682 NTSTATUS vfs_default_init(void)
2684 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
2685 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);