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, smb_fname, mode) == -1) &&
507 END_PROFILE(syscall_mkdir);
511 static int vfswrap_rmdir(vfs_handle_struct *handle,
512 const struct smb_filename *smb_fname)
516 START_PROFILE(syscall_rmdir);
517 result = rmdir(smb_fname->base_name);
518 END_PROFILE(syscall_rmdir);
522 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
526 START_PROFILE(syscall_closedir);
527 result = closedir(dirp);
528 END_PROFILE(syscall_closedir);
532 static void vfswrap_init_search_op(vfs_handle_struct *handle,
535 /* Default behavior is a NOOP */
538 /* File operations */
540 static int vfswrap_open(vfs_handle_struct *handle,
541 struct smb_filename *smb_fname,
542 files_struct *fsp, int flags, mode_t mode)
546 START_PROFILE(syscall_open);
548 if (smb_fname->stream_name) {
553 result = open(smb_fname->base_name, flags, mode);
555 END_PROFILE(syscall_open);
559 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
560 struct smb_request *req,
561 uint16_t root_dir_fid,
562 struct smb_filename *smb_fname,
563 uint32_t access_mask,
564 uint32_t share_access,
565 uint32_t create_disposition,
566 uint32_t create_options,
567 uint32_t file_attributes,
568 uint32_t oplock_request,
569 struct smb2_lease *lease,
570 uint64_t allocation_size,
571 uint32_t private_flags,
572 struct security_descriptor *sd,
573 struct ea_list *ea_list,
574 files_struct **result,
576 const struct smb2_create_blobs *in_context_blobs,
577 struct smb2_create_blobs *out_context_blobs)
579 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
580 access_mask, share_access,
581 create_disposition, create_options,
582 file_attributes, oplock_request, lease,
583 allocation_size, private_flags,
585 pinfo, in_context_blobs, out_context_blobs);
588 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
592 START_PROFILE(syscall_close);
593 result = fd_close_posix(fsp);
594 END_PROFILE(syscall_close);
598 static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
602 START_PROFILE_BYTES(syscall_read, n);
603 result = sys_read(fsp->fh->fd, data, n);
604 END_PROFILE_BYTES(syscall_read);
608 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
609 size_t n, off_t offset)
613 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
614 START_PROFILE_BYTES(syscall_pread, n);
615 result = sys_pread(fsp->fh->fd, data, n, offset);
616 END_PROFILE_BYTES(syscall_pread);
618 if (result == -1 && errno == ESPIPE) {
619 /* Maintain the fiction that pipes can be seeked (sought?) on. */
620 result = SMB_VFS_READ(fsp, data, n);
624 #else /* HAVE_PREAD */
628 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
629 if (curr == -1 && errno == ESPIPE) {
630 /* Maintain the fiction that pipes can be seeked (sought?) on. */
631 result = SMB_VFS_READ(fsp, data, n);
636 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
641 result = SMB_VFS_READ(fsp, data, n);
644 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
647 #endif /* HAVE_PREAD */
652 static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
656 START_PROFILE_BYTES(syscall_write, n);
657 result = sys_write(fsp->fh->fd, data, n);
658 END_PROFILE_BYTES(syscall_write);
662 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
663 size_t n, off_t offset)
667 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
668 START_PROFILE_BYTES(syscall_pwrite, n);
669 result = sys_pwrite(fsp->fh->fd, data, n, offset);
670 END_PROFILE_BYTES(syscall_pwrite);
672 if (result == -1 && errno == ESPIPE) {
673 /* Maintain the fiction that pipes can be sought on. */
674 result = SMB_VFS_WRITE(fsp, data, n);
677 #else /* HAVE_PWRITE */
681 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
686 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
690 result = SMB_VFS_WRITE(fsp, data, n);
693 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
696 #endif /* HAVE_PWRITE */
701 static void vfswrap_asys_finished(struct tevent_context *ev,
702 struct tevent_fd *fde,
703 uint16_t flags, void *p);
705 static bool vfswrap_init_asys_ctx(struct smbd_server_connection *conn)
707 struct asys_context *ctx;
708 struct tevent_fd *fde;
712 if (conn->asys_ctx != NULL) {
716 ret = asys_context_init(&ctx, lp_aio_max_threads());
718 DEBUG(1, ("asys_context_init failed: %s\n", strerror(ret)));
722 fd = asys_signalfd(ctx);
724 ret = set_blocking(fd, false);
726 DBG_WARNING("set_blocking failed: %s\n", strerror(errno));
730 fde = tevent_add_fd(conn->ev_ctx, conn, fd, TEVENT_FD_READ,
731 vfswrap_asys_finished, ctx);
733 DEBUG(1, ("tevent_add_fd failed\n"));
737 conn->asys_ctx = ctx;
738 conn->asys_fde = fde;
742 asys_context_destroy(ctx);
746 struct vfswrap_asys_state {
747 struct asys_context *asys_ctx;
748 struct tevent_req *req;
750 struct vfs_aio_state vfs_aio_state;
751 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
752 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
755 static int vfswrap_asys_state_destructor(struct vfswrap_asys_state *s)
757 asys_cancel(s->asys_ctx, s->req);
761 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
763 struct tevent_context *ev,
764 struct files_struct *fsp,
766 size_t n, off_t offset)
768 struct tevent_req *req;
769 struct vfswrap_asys_state *state;
772 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
776 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
778 return tevent_req_post(req, ev);
780 state->asys_ctx = handle->conn->sconn->asys_ctx;
783 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
784 state->profile_bytes, n);
785 ret = asys_pread(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
787 tevent_req_error(req, ret);
788 return tevent_req_post(req, ev);
790 talloc_set_destructor(state, vfswrap_asys_state_destructor);
795 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
797 struct tevent_context *ev,
798 struct files_struct *fsp,
800 size_t n, off_t offset)
802 struct tevent_req *req;
803 struct vfswrap_asys_state *state;
806 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
810 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
812 return tevent_req_post(req, ev);
814 state->asys_ctx = handle->conn->sconn->asys_ctx;
817 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
818 state->profile_bytes, n);
819 ret = asys_pwrite(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
821 tevent_req_error(req, ret);
822 return tevent_req_post(req, ev);
824 talloc_set_destructor(state, vfswrap_asys_state_destructor);
829 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
831 struct tevent_context *ev,
832 struct files_struct *fsp)
834 struct tevent_req *req;
835 struct vfswrap_asys_state *state;
838 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
842 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
844 return tevent_req_post(req, ev);
846 state->asys_ctx = handle->conn->sconn->asys_ctx;
849 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
850 state->profile_basic);
851 ret = asys_fsync(state->asys_ctx, fsp->fh->fd, req);
853 tevent_req_error(req, ret);
854 return tevent_req_post(req, ev);
856 talloc_set_destructor(state, vfswrap_asys_state_destructor);
861 static void vfswrap_asys_finished(struct tevent_context *ev,
862 struct tevent_fd *fde,
863 uint16_t flags, void *p)
865 struct asys_context *asys_ctx = (struct asys_context *)p;
866 struct asys_result results[get_outstanding_aio_calls()];
869 if ((flags & TEVENT_FD_READ) == 0) {
873 ret = asys_results(asys_ctx, results, get_outstanding_aio_calls());
875 DEBUG(1, ("asys_results returned %s\n", strerror(-ret)));
879 for (i=0; i<ret; i++) {
880 struct asys_result *result = &results[i];
881 struct tevent_req *req;
882 struct vfswrap_asys_state *state;
884 if ((result->ret == -1) && (result->err == ECANCELED)) {
888 req = talloc_get_type_abort(result->private_data,
890 state = tevent_req_data(req, struct vfswrap_asys_state);
892 talloc_set_destructor(state, NULL);
894 SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
895 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
896 state->ret = result->ret;
897 state->vfs_aio_state.error = result->err;
898 state->vfs_aio_state.duration = result->duration;
899 tevent_req_defer_callback(req, ev);
900 tevent_req_done(req);
904 static ssize_t vfswrap_asys_ssize_t_recv(struct tevent_req *req,
905 struct vfs_aio_state *vfs_aio_state)
907 struct vfswrap_asys_state *state = tevent_req_data(
908 req, struct vfswrap_asys_state);
910 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
913 *vfs_aio_state = state->vfs_aio_state;
917 static int vfswrap_asys_int_recv(struct tevent_req *req,
918 struct vfs_aio_state *vfs_aio_state)
920 struct vfswrap_asys_state *state = tevent_req_data(
921 req, struct vfswrap_asys_state);
923 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
926 *vfs_aio_state = state->vfs_aio_state;
930 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
934 START_PROFILE(syscall_lseek);
936 /* Cope with 'stat' file opens. */
937 if (fsp->fh->fd != -1)
938 result = lseek(fsp->fh->fd, offset, whence);
941 * We want to maintain the fiction that we can seek
942 * on a fifo for file system purposes. This allows
943 * people to set up UNIX fifo's that feed data to Windows
947 if((result == -1) && (errno == ESPIPE)) {
952 END_PROFILE(syscall_lseek);
956 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
957 off_t offset, size_t n)
961 START_PROFILE_BYTES(syscall_sendfile, n);
962 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
963 END_PROFILE_BYTES(syscall_sendfile);
967 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
975 START_PROFILE_BYTES(syscall_recvfile, n);
976 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
977 END_PROFILE_BYTES(syscall_recvfile);
981 static int vfswrap_rename(vfs_handle_struct *handle,
982 const struct smb_filename *smb_fname_src,
983 const struct smb_filename *smb_fname_dst)
987 START_PROFILE(syscall_rename);
989 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
994 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
997 END_PROFILE(syscall_rename);
1001 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
1006 START_PROFILE(syscall_fsync);
1007 result = fsync(fsp->fh->fd);
1008 END_PROFILE(syscall_fsync);
1015 static int vfswrap_stat(vfs_handle_struct *handle,
1016 struct smb_filename *smb_fname)
1020 START_PROFILE(syscall_stat);
1022 if (smb_fname->stream_name) {
1027 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1028 lp_fake_directory_create_times(SNUM(handle->conn)));
1030 END_PROFILE(syscall_stat);
1034 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1038 START_PROFILE(syscall_fstat);
1039 result = sys_fstat(fsp->fh->fd,
1040 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1041 END_PROFILE(syscall_fstat);
1045 static int vfswrap_lstat(vfs_handle_struct *handle,
1046 struct smb_filename *smb_fname)
1050 START_PROFILE(syscall_lstat);
1052 if (smb_fname->stream_name) {
1057 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1058 lp_fake_directory_create_times(SNUM(handle->conn)));
1060 END_PROFILE(syscall_lstat);
1064 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1066 enum vfs_translate_direction direction,
1067 TALLOC_CTX *mem_ctx,
1070 return NT_STATUS_NONE_MAPPED;
1074 * Implement the default fsctl operation.
1076 static bool vfswrap_logged_ioctl_message = false;
1078 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1079 struct files_struct *fsp,
1082 uint16_t req_flags, /* Needed for UNICODE ... */
1083 const uint8_t *_in_data,
1085 uint8_t **_out_data,
1086 uint32_t max_out_len,
1089 const char *in_data = (const char *)_in_data;
1090 char **out_data = (char **)_out_data;
1094 case FSCTL_SET_SPARSE:
1096 bool set_sparse = true;
1098 if (in_len >= 1 && in_data[0] == 0) {
1102 status = file_set_sparse(handle->conn, fsp, set_sparse);
1104 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1105 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1106 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1107 nt_errstr(status)));
1112 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1114 unsigned char objid[16];
1115 char *return_data = NULL;
1117 /* This should return the object-id on this file.
1118 * I think I'll make this be the inode+dev. JRA.
1121 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1122 fsp_fnum_dbg(fsp)));
1124 *out_len = MIN(max_out_len, 64);
1126 /* Hmmm, will this cause problems if less data asked for? */
1127 return_data = talloc_array(ctx, char, 64);
1128 if (return_data == NULL) {
1129 return NT_STATUS_NO_MEMORY;
1132 /* For backwards compatibility only store the dev/inode. */
1133 push_file_id_16(return_data, &fsp->file_id);
1134 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1135 push_file_id_16(return_data+32, &fsp->file_id);
1136 memset(return_data+48, 0, 16);
1137 *out_data = return_data;
1138 return NT_STATUS_OK;
1141 case FSCTL_GET_REPARSE_POINT:
1143 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1144 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1145 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1146 return NT_STATUS_NOT_A_REPARSE_POINT;
1149 case FSCTL_SET_REPARSE_POINT:
1151 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1152 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1153 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1154 return NT_STATUS_NOT_A_REPARSE_POINT;
1157 case FSCTL_GET_SHADOW_COPY_DATA:
1160 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1161 * and return their volume names. If max_data_count is 16, then it is just
1162 * asking for the number of volumes and length of the combined names.
1164 * pdata is the data allocated by our caller, but that uses
1165 * total_data_count (which is 0 in our case) rather than max_data_count.
1166 * Allocate the correct amount and return the pointer to let
1167 * it be deallocated when we return.
1169 struct shadow_copy_data *shadow_data = NULL;
1170 bool labels = False;
1171 uint32_t labels_data_count = 0;
1173 char *cur_pdata = NULL;
1175 if (max_out_len < 16) {
1176 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1178 return NT_STATUS_INVALID_PARAMETER;
1181 if (max_out_len > 16) {
1185 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1186 if (shadow_data == NULL) {
1187 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1188 return NT_STATUS_NO_MEMORY;
1192 * Call the VFS routine to actually do the work.
1194 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1197 /* broken module didn't set errno on error */
1198 status = NT_STATUS_UNSUCCESSFUL;
1200 status = map_nt_error_from_unix(errno);
1201 if (NT_STATUS_EQUAL(status,
1202 NT_STATUS_NOT_SUPPORTED)) {
1206 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1207 "connectpath %s, failed - %s.\n",
1208 fsp->conn->connectpath,
1209 nt_errstr(status)));
1210 TALLOC_FREE(shadow_data);
1214 labels_data_count = (shadow_data->num_volumes * 2 *
1215 sizeof(SHADOW_COPY_LABEL)) + 2;
1220 *out_len = 12 + labels_data_count;
1223 if (max_out_len < *out_len) {
1224 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1225 max_out_len, *out_len));
1226 TALLOC_FREE(shadow_data);
1227 return NT_STATUS_BUFFER_TOO_SMALL;
1230 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1231 if (cur_pdata == NULL) {
1232 TALLOC_FREE(shadow_data);
1233 return NT_STATUS_NO_MEMORY;
1236 *out_data = cur_pdata;
1238 /* num_volumes 4 bytes */
1239 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1242 /* num_labels 4 bytes */
1243 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1246 /* needed_data_count 4 bytes */
1247 SIVAL(cur_pdata, 8, labels_data_count);
1251 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1252 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1253 if (labels && shadow_data->labels) {
1254 for (i=0; i<shadow_data->num_volumes; i++) {
1256 status = srvstr_push(cur_pdata, req_flags,
1257 cur_pdata, shadow_data->labels[i],
1258 2 * sizeof(SHADOW_COPY_LABEL),
1259 STR_UNICODE|STR_TERMINATE, &len);
1260 if (!NT_STATUS_IS_OK(status)) {
1261 TALLOC_FREE(*out_data);
1262 TALLOC_FREE(shadow_data);
1265 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1266 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1270 TALLOC_FREE(shadow_data);
1272 return NT_STATUS_OK;
1275 case FSCTL_FIND_FILES_BY_SID:
1277 /* pretend this succeeded -
1279 * we have to send back a list with all files owned by this SID
1281 * but I have to check that --metze
1287 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1288 fsp_fnum_dbg(fsp)));
1291 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1292 return NT_STATUS_INVALID_PARAMETER;
1295 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1297 /* unknown 4 bytes: this is not the length of the sid :-( */
1298 /*unknown = IVAL(pdata,0);*/
1300 if (!sid_parse(_in_data + 4, sid_len, &sid)) {
1301 return NT_STATUS_INVALID_PARAMETER;
1303 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1305 if (!sid_to_uid(&sid, &uid)) {
1306 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1307 sid_string_dbg(&sid),
1308 (unsigned long)sid_len));
1312 /* we can take a look at the find source :-)
1314 * find ./ -uid $uid -name '*' is what we need here
1317 * and send 4bytes len and then NULL terminated unicode strings
1320 * but I don't know how to deal with the paged results
1321 * (maybe we can hang the result anywhere in the fsp struct)
1323 * but I don't know how to deal with the paged results
1324 * (maybe we can hang the result anywhere in the fsp struct)
1326 * we don't send all files at once
1327 * and at the next we should *not* start from the beginning,
1328 * so we have to cache the result
1333 /* this works for now... */
1334 return NT_STATUS_OK;
1337 case FSCTL_QUERY_ALLOCATED_RANGES:
1339 /* FIXME: This is just a dummy reply, telling that all of the
1340 * file is allocated. MKS cp needs that.
1341 * Adding the real allocated ranges via FIEMAP on Linux
1342 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1343 * this FSCTL correct for sparse files.
1345 uint64_t offset, length;
1346 char *out_data_tmp = NULL;
1349 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1351 return NT_STATUS_INVALID_PARAMETER;
1354 if (max_out_len < 16) {
1355 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1357 return NT_STATUS_INVALID_PARAMETER;
1360 offset = BVAL(in_data,0);
1361 length = BVAL(in_data,8);
1363 if (offset + length < offset) {
1364 /* No 64-bit integer wrap. */
1365 return NT_STATUS_INVALID_PARAMETER;
1368 /* Shouldn't this be SMB_VFS_STAT ... ? */
1369 status = vfs_stat_fsp(fsp);
1370 if (!NT_STATUS_IS_OK(status)) {
1375 out_data_tmp = talloc_array(ctx, char, *out_len);
1376 if (out_data_tmp == NULL) {
1377 DEBUG(10, ("unable to allocate memory for response\n"));
1378 return NT_STATUS_NO_MEMORY;
1381 if (offset > fsp->fsp_name->st.st_ex_size ||
1382 fsp->fsp_name->st.st_ex_size == 0 ||
1384 memset(out_data_tmp, 0, *out_len);
1386 uint64_t end = offset + length;
1387 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1388 SBVAL(out_data_tmp, 0, 0);
1389 SBVAL(out_data_tmp, 8, end);
1392 *out_data = out_data_tmp;
1394 return NT_STATUS_OK;
1397 case FSCTL_IS_VOLUME_DIRTY:
1399 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1400 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1402 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1403 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1405 return NT_STATUS_INVALID_PARAMETER;
1410 * Only print once ... unfortunately there could be lots of
1411 * different FSCTLs that are called.
1413 if (!vfswrap_logged_ioctl_message) {
1414 vfswrap_logged_ioctl_message = true;
1415 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1416 __func__, function));
1420 return NT_STATUS_NOT_SUPPORTED;
1423 struct vfs_cc_state {
1428 static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *handle,
1429 TALLOC_CTX *mem_ctx,
1430 struct tevent_context *ev,
1431 struct files_struct *src_fsp,
1433 struct files_struct *dest_fsp,
1437 struct tevent_req *req;
1438 struct vfs_cc_state *vfs_cc_state;
1441 DEBUG(10, ("performing server side copy chunk of length %lu\n",
1442 (unsigned long)num));
1444 req = tevent_req_create(mem_ctx, &vfs_cc_state, struct vfs_cc_state);
1449 vfs_cc_state->buf = talloc_array(vfs_cc_state, uint8_t,
1450 MIN(num, 8*1024*1024));
1451 if (tevent_req_nomem(vfs_cc_state->buf, req)) {
1452 return tevent_req_post(req, ev);
1455 status = vfs_stat_fsp(src_fsp);
1456 if (tevent_req_nterror(req, status)) {
1457 return tevent_req_post(req, ev);
1460 if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
1462 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1463 * If the SourceOffset or SourceOffset + Length extends beyond
1464 * the end of file, the server SHOULD<240> treat this as a
1465 * STATUS_END_OF_FILE error.
1467 * <240> Section 3.3.5.15.6: Windows servers will return
1468 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1470 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1471 return tevent_req_post(req, ev);
1474 /* could use 2.6.33+ sendfile here to do this in kernel */
1475 while (vfs_cc_state->copied < num) {
1477 struct lock_struct lck;
1480 off_t this_num = MIN(talloc_array_length(vfs_cc_state->buf),
1481 num - vfs_cc_state->copied);
1483 if (src_fsp->op == NULL) {
1484 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1485 return tevent_req_post(req, ev);
1487 init_strict_lock_struct(src_fsp,
1488 src_fsp->op->global->open_persistent_id,
1494 if (!SMB_VFS_STRICT_LOCK(src_fsp->conn, src_fsp, &lck)) {
1495 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1496 return tevent_req_post(req, ev);
1499 ret = SMB_VFS_PREAD(src_fsp, vfs_cc_state->buf,
1502 saved_errno = errno;
1505 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1508 errno = saved_errno;
1509 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1510 return tevent_req_post(req, ev);
1512 if (ret != this_num) {
1513 /* zero tolerance for short reads */
1514 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1515 return tevent_req_post(req, ev);
1520 if (dest_fsp->op == NULL) {
1521 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1522 return tevent_req_post(req, ev);
1525 init_strict_lock_struct(dest_fsp,
1526 dest_fsp->op->global->open_persistent_id,
1532 if (!SMB_VFS_STRICT_LOCK(dest_fsp->conn, dest_fsp, &lck)) {
1533 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1534 return tevent_req_post(req, ev);
1537 ret = SMB_VFS_PWRITE(dest_fsp, vfs_cc_state->buf,
1538 this_num, dest_off);
1540 saved_errno = errno;
1543 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1546 errno = saved_errno;
1547 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1548 return tevent_req_post(req, ev);
1550 if (ret != this_num) {
1551 /* zero tolerance for short writes */
1552 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1553 return tevent_req_post(req, ev);
1557 vfs_cc_state->copied += this_num;
1560 tevent_req_done(req);
1561 return tevent_req_post(req, ev);
1564 static NTSTATUS vfswrap_copy_chunk_recv(struct vfs_handle_struct *handle,
1565 struct tevent_req *req,
1568 struct vfs_cc_state *vfs_cc_state = tevent_req_data(req,
1569 struct vfs_cc_state);
1572 if (tevent_req_is_nterror(req, &status)) {
1573 DEBUG(2, ("server side copy chunk failed: %s\n",
1574 nt_errstr(status)));
1576 tevent_req_received(req);
1580 *copied = vfs_cc_state->copied;
1581 DEBUG(10, ("server side copy chunk copied %lu\n",
1582 (unsigned long)*copied));
1583 tevent_req_received(req);
1585 return NT_STATUS_OK;
1588 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1589 TALLOC_CTX *mem_ctx,
1590 struct files_struct *fsp,
1591 struct smb_filename *smb_fname,
1592 uint16_t *_compression_fmt)
1594 return NT_STATUS_INVALID_DEVICE_REQUEST;
1597 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1598 TALLOC_CTX *mem_ctx,
1599 struct files_struct *fsp,
1600 uint16_t compression_fmt)
1602 return NT_STATUS_INVALID_DEVICE_REQUEST;
1605 /********************************************************************
1606 Given a stat buffer return the allocated size on disk, taking into
1607 account sparse files.
1608 ********************************************************************/
1609 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1610 struct files_struct *fsp,
1611 const SMB_STRUCT_STAT *sbuf)
1615 START_PROFILE(syscall_get_alloc_size);
1617 if(S_ISDIR(sbuf->st_ex_mode)) {
1622 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1623 /* The type of st_blocksize is blkcnt_t which *MUST* be
1624 signed (according to POSIX) and can be less than 64-bits.
1625 Ensure when we're converting to 64 bits wide we don't
1627 #if defined(SIZEOF_BLKCNT_T_8)
1628 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1629 #elif defined(SIZEOF_BLKCNT_T_4)
1631 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1632 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1635 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1639 * Some file systems do not allocate a block for very
1640 * small files. But for non-empty file should report a
1644 uint64_t filesize = get_file_size_stat(sbuf);
1646 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
1650 result = get_file_size_stat(sbuf);
1653 if (fsp && fsp->initial_allocation_size)
1654 result = MAX(result,fsp->initial_allocation_size);
1656 result = smb_roundup(handle->conn, result);
1659 END_PROFILE(syscall_get_alloc_size);
1663 static int vfswrap_unlink(vfs_handle_struct *handle,
1664 const struct smb_filename *smb_fname)
1668 START_PROFILE(syscall_unlink);
1670 if (smb_fname->stream_name) {
1674 result = unlink(smb_fname->base_name);
1677 END_PROFILE(syscall_unlink);
1681 static int vfswrap_chmod(vfs_handle_struct *handle,
1682 const struct smb_filename *smb_fname,
1687 START_PROFILE(syscall_chmod);
1690 * We need to do this due to the fact that the default POSIX ACL
1691 * chmod modifies the ACL *mask* for the group owner, not the
1692 * group owner bits directly. JRA.
1697 int saved_errno = errno; /* We might get ENOSYS */
1698 result = SMB_VFS_CHMOD_ACL(handle->conn,
1702 END_PROFILE(syscall_chmod);
1705 /* Error - return the old errno. */
1706 errno = saved_errno;
1709 result = chmod(smb_fname->base_name, mode);
1710 END_PROFILE(syscall_chmod);
1714 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
1718 START_PROFILE(syscall_fchmod);
1721 * We need to do this due to the fact that the default POSIX ACL
1722 * chmod modifies the ACL *mask* for the group owner, not the
1723 * group owner bits directly. JRA.
1727 int saved_errno = errno; /* We might get ENOSYS */
1728 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
1729 END_PROFILE(syscall_fchmod);
1732 /* Error - return the old errno. */
1733 errno = saved_errno;
1736 #if defined(HAVE_FCHMOD)
1737 result = fchmod(fsp->fh->fd, mode);
1743 END_PROFILE(syscall_fchmod);
1747 static int vfswrap_chown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1751 START_PROFILE(syscall_chown);
1752 result = chown(path, uid, gid);
1753 END_PROFILE(syscall_chown);
1757 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
1762 START_PROFILE(syscall_fchown);
1763 result = fchown(fsp->fh->fd, uid, gid);
1764 END_PROFILE(syscall_fchown);
1772 static int vfswrap_lchown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1776 START_PROFILE(syscall_lchown);
1777 result = lchown(path, uid, gid);
1778 END_PROFILE(syscall_lchown);
1782 static int vfswrap_chdir(vfs_handle_struct *handle, const char *path)
1786 START_PROFILE(syscall_chdir);
1787 result = chdir(path);
1788 END_PROFILE(syscall_chdir);
1792 static char *vfswrap_getwd(vfs_handle_struct *handle)
1796 START_PROFILE(syscall_getwd);
1797 result = sys_getwd();
1798 END_PROFILE(syscall_getwd);
1802 /*********************************************************************
1803 nsec timestamp resolution call. Convert down to whatever the underlying
1804 system will support.
1805 **********************************************************************/
1807 static int vfswrap_ntimes(vfs_handle_struct *handle,
1808 const struct smb_filename *smb_fname,
1809 struct smb_file_time *ft)
1813 START_PROFILE(syscall_ntimes);
1815 if (smb_fname->stream_name) {
1821 if (null_timespec(ft->atime)) {
1822 ft->atime= smb_fname->st.st_ex_atime;
1825 if (null_timespec(ft->mtime)) {
1826 ft->mtime = smb_fname->st.st_ex_mtime;
1829 if (!null_timespec(ft->create_time)) {
1830 set_create_timespec_ea(handle->conn,
1835 if ((timespec_compare(&ft->atime,
1836 &smb_fname->st.st_ex_atime) == 0) &&
1837 (timespec_compare(&ft->mtime,
1838 &smb_fname->st.st_ex_mtime) == 0)) {
1843 #if defined(HAVE_UTIMENSAT)
1845 struct timespec ts[2];
1848 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
1850 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
1852 if (!((result == -1) && (errno == ENOSYS))) {
1856 #if defined(HAVE_UTIMES)
1858 struct timeval tv[2];
1859 tv[0] = convert_timespec_to_timeval(ft->atime);
1860 tv[1] = convert_timespec_to_timeval(ft->mtime);
1861 result = utimes(smb_fname->base_name, tv);
1863 result = utimes(smb_fname->base_name, NULL);
1865 if (!((result == -1) && (errno == ENOSYS))) {
1869 #if defined(HAVE_UTIME)
1871 struct utimbuf times;
1872 times.actime = convert_timespec_to_time_t(ft->atime);
1873 times.modtime = convert_timespec_to_time_t(ft->mtime);
1874 result = utime(smb_fname->base_name, ×);
1876 result = utime(smb_fname->base_name, NULL);
1878 if (!((result == -1) && (errno == ENOSYS))) {
1886 END_PROFILE(syscall_ntimes);
1890 /*********************************************************************
1891 A version of ftruncate that will write the space on disk if strict
1893 **********************************************************************/
1895 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1897 off_t space_to_write;
1898 uint64_t space_avail;
1899 uint64_t bsize,dfree,dsize;
1902 SMB_STRUCT_STAT *pst;
1904 status = vfs_stat_fsp(fsp);
1905 if (!NT_STATUS_IS_OK(status)) {
1908 pst = &fsp->fsp_name->st;
1911 if (S_ISFIFO(pst->st_ex_mode))
1915 if (pst->st_ex_size == len)
1918 /* Shrink - just ftruncate. */
1919 if (pst->st_ex_size > len)
1920 return ftruncate(fsp->fh->fd, len);
1922 space_to_write = len - pst->st_ex_size;
1924 /* for allocation try fallocate first. This can fail on some
1925 platforms e.g. when the filesystem doesn't support it and no
1926 emulation is being done by the libc (like on AIX with JFS1). In that
1927 case we do our own emulation. fallocate implementations can
1928 return ENOTSUP or EINVAL in cases like that. */
1929 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
1930 if (ret == -1 && errno == ENOSPC) {
1936 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
1937 "error %d. Falling back to slow manual allocation\n", errno));
1939 /* available disk space is enough or not? */
1940 space_avail = get_dfree_info(fsp->conn,
1941 fsp->fsp_name->base_name,
1942 &bsize, &dfree, &dsize);
1943 /* space_avail is 1k blocks */
1944 if (space_avail == (uint64_t)-1 ||
1945 ((uint64_t)space_to_write/1024 > space_avail) ) {
1950 /* Write out the real space on disk. */
1951 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
1959 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1962 SMB_STRUCT_STAT *pst;
1966 START_PROFILE(syscall_ftruncate);
1968 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
1969 result = strict_allocate_ftruncate(handle, fsp, len);
1970 END_PROFILE(syscall_ftruncate);
1974 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
1975 ftruncate if the system supports it. Then I discovered that
1976 you can have some filesystems that support ftruncate
1977 expansion and some that don't! On Linux fat can't do
1978 ftruncate extend but ext2 can. */
1980 result = ftruncate(fsp->fh->fd, len);
1982 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
1983 extend a file with ftruncate. Provide alternate implementation
1986 /* Do an fstat to see if the file is longer than the requested
1987 size in which case the ftruncate above should have
1988 succeeded or shorter, in which case seek to len - 1 and
1989 write 1 byte of zero */
1990 status = vfs_stat_fsp(fsp);
1991 if (!NT_STATUS_IS_OK(status)) {
1995 /* We need to update the files_struct after successful ftruncate */
2000 pst = &fsp->fsp_name->st;
2003 if (S_ISFIFO(pst->st_ex_mode)) {
2009 if (pst->st_ex_size == len) {
2014 if (pst->st_ex_size > len) {
2015 /* the ftruncate should have worked */
2019 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2027 END_PROFILE(syscall_ftruncate);
2031 static int vfswrap_fallocate(vfs_handle_struct *handle,
2039 START_PROFILE(syscall_fallocate);
2041 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2043 * posix_fallocate returns 0 on success, errno on error
2044 * and doesn't set errno. Make it behave like fallocate()
2045 * which returns -1, and sets errno on failure.
2052 /* sys_fallocate handles filtering of unsupported mode flags */
2053 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2055 END_PROFILE(syscall_fallocate);
2059 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2063 START_PROFILE(syscall_fcntl_lock);
2064 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2065 END_PROFILE(syscall_fcntl_lock);
2069 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2070 uint32_t share_mode, uint32_t access_mask)
2072 START_PROFILE(syscall_kernel_flock);
2073 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2074 END_PROFILE(syscall_kernel_flock);
2078 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2082 START_PROFILE(syscall_fcntl_getlock);
2083 result = fcntl_getlock(fsp->fh->fd, poffset, pcount, ptype, ppid);
2084 END_PROFILE(syscall_fcntl_getlock);
2088 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2093 START_PROFILE(syscall_linux_setlease);
2095 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2096 result = linux_setlease(fsp->fh->fd, leasetype);
2100 END_PROFILE(syscall_linux_setlease);
2104 static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2108 START_PROFILE(syscall_symlink);
2109 result = symlink(oldpath, newpath);
2110 END_PROFILE(syscall_symlink);
2114 static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
2118 START_PROFILE(syscall_readlink);
2119 result = readlink(path, buf, bufsiz);
2120 END_PROFILE(syscall_readlink);
2124 static int vfswrap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2128 START_PROFILE(syscall_link);
2129 result = link(oldpath, newpath);
2130 END_PROFILE(syscall_link);
2134 static int vfswrap_mknod(vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev)
2138 START_PROFILE(syscall_mknod);
2139 result = sys_mknod(pathname, mode, dev);
2140 END_PROFILE(syscall_mknod);
2144 static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
2148 START_PROFILE(syscall_realpath);
2149 result = sys_realpath(path);
2150 END_PROFILE(syscall_realpath);
2154 static int vfswrap_chflags(vfs_handle_struct *handle, const char *path,
2158 return chflags(path, flags);
2165 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2166 const SMB_STRUCT_STAT *sbuf)
2170 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2174 key.devid = sbuf->st_ex_dev;
2175 key.inode = sbuf->st_ex_ino;
2176 /* key.extid is unused by default. */
2181 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2182 struct files_struct *fsp,
2184 TALLOC_CTX *mem_ctx,
2185 unsigned int *pnum_streams,
2186 struct stream_struct **pstreams)
2188 SMB_STRUCT_STAT sbuf;
2189 struct stream_struct *tmp_streams = NULL;
2192 if ((fsp != NULL) && (fsp->is_directory)) {
2194 * No default streams on directories
2199 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2200 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2203 struct smb_filename smb_fname;
2205 ZERO_STRUCT(smb_fname);
2206 smb_fname.base_name = discard_const_p(char, fname);
2208 if (lp_posix_pathnames()) {
2209 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname);
2211 ret = SMB_VFS_STAT(handle->conn, &smb_fname);
2213 sbuf = smb_fname.st;
2217 return map_nt_error_from_unix(errno);
2220 if (S_ISDIR(sbuf.st_ex_mode)) {
2224 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2225 (*pnum_streams) + 1);
2226 if (tmp_streams == NULL) {
2227 return NT_STATUS_NO_MEMORY;
2229 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2230 if (tmp_streams[*pnum_streams].name == NULL) {
2231 return NT_STATUS_NO_MEMORY;
2233 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2234 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2237 *pstreams = tmp_streams;
2239 return NT_STATUS_OK;
2242 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2245 TALLOC_CTX *mem_ctx,
2249 * Don't fall back to get_real_filename so callers can differentiate
2250 * between a full directory scan and an actual case-insensitive stat.
2256 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2259 return handle->conn->connectpath;
2262 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2263 struct byte_range_lock *br_lck,
2264 struct lock_struct *plock,
2267 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2269 /* Note: blr is not used in the default implementation. */
2270 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2273 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2274 struct messaging_context *msg_ctx,
2275 struct byte_range_lock *br_lck,
2276 const struct lock_struct *plock)
2278 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2280 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2283 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2284 struct byte_range_lock *br_lck,
2285 struct lock_struct *plock)
2287 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2289 /* Note: blr is not used in the default implementation. */
2290 return brl_lock_cancel_default(br_lck, plock);
2293 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2295 struct lock_struct *plock)
2297 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2298 plock->lock_type == WRITE_LOCK);
2300 return strict_lock_default(fsp, plock);
2303 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2305 struct lock_struct *plock)
2307 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2308 plock->lock_type == WRITE_LOCK);
2310 strict_unlock_default(fsp, plock);
2313 /* NT ACL operations. */
2315 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2317 uint32_t security_info,
2318 TALLOC_CTX *mem_ctx,
2319 struct security_descriptor **ppdesc)
2323 START_PROFILE(fget_nt_acl);
2324 result = posix_fget_nt_acl(fsp, security_info,
2326 END_PROFILE(fget_nt_acl);
2330 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2331 const struct smb_filename *smb_fname,
2332 uint32_t security_info,
2333 TALLOC_CTX *mem_ctx,
2334 struct security_descriptor **ppdesc)
2338 START_PROFILE(get_nt_acl);
2339 result = posix_get_nt_acl(handle->conn,
2340 smb_fname->base_name,
2344 END_PROFILE(get_nt_acl);
2348 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2352 START_PROFILE(fset_nt_acl);
2353 result = set_nt_acl(fsp, security_info_sent, psd);
2354 END_PROFILE(fset_nt_acl);
2358 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2359 struct smb_filename *file,
2360 struct security_acl *sacl,
2361 uint32_t access_requested,
2362 uint32_t access_denied)
2364 return NT_STATUS_OK; /* Nothing to do here ... */
2367 static int vfswrap_chmod_acl(vfs_handle_struct *handle,
2368 const struct smb_filename *smb_fname,
2377 START_PROFILE(chmod_acl);
2378 result = chmod_acl(handle->conn, smb_fname->base_name, mode);
2379 END_PROFILE(chmod_acl);
2384 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2392 START_PROFILE(fchmod_acl);
2393 result = fchmod_acl(fsp, mode);
2394 END_PROFILE(fchmod_acl);
2399 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2401 SMB_ACL_TYPE_T type,
2402 TALLOC_CTX *mem_ctx)
2404 return sys_acl_get_file(handle, path_p, type, mem_ctx);
2407 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2409 TALLOC_CTX *mem_ctx)
2411 return sys_acl_get_fd(handle, fsp, mem_ctx);
2414 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2416 return sys_acl_set_file(handle, name, acltype, theacl);
2419 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2421 return sys_acl_set_fd(handle, fsp, theacl);
2424 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
2426 return sys_acl_delete_def_file(handle, path);
2429 /****************************************************************
2430 Extended attribute operations.
2431 *****************************************************************/
2433 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
2435 return getxattr(path, name, value, size);
2438 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2440 return fgetxattr(fsp->fh->fd, name, value, size);
2443 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
2445 return listxattr(path, list, size);
2448 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2450 return flistxattr(fsp->fh->fd, list, size);
2453 static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
2455 return removexattr(path, name);
2458 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2460 return fremovexattr(fsp->fh->fd, name);
2463 static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
2465 return setxattr(path, name, value, size, flags);
2468 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2470 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2473 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2478 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2479 const struct smb_filename *fname,
2480 SMB_STRUCT_STAT *sbuf)
2484 bool offline = false;
2486 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2490 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2491 #if defined(ENOTSUP)
2497 status = get_full_smb_filename(talloc_tos(), fname, &path);
2498 if (!NT_STATUS_IS_OK(status)) {
2499 errno = map_errno_from_nt_status(status);
2503 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2510 static int vfswrap_set_offline(struct vfs_handle_struct *handle,
2511 const struct smb_filename *fname)
2513 /* We don't know how to set offline bit by default, needs to be overriden in the vfs modules */
2514 #if defined(ENOTSUP)
2520 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2521 struct files_struct *fsp,
2522 TALLOC_CTX *mem_ctx,
2525 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2528 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2529 struct files_struct *fsp,
2530 const DATA_BLOB old_cookie,
2531 TALLOC_CTX *mem_ctx,
2532 DATA_BLOB *new_cookie)
2534 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2538 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2539 struct smb_request *smb1req,
2540 struct smbXsrv_open *op,
2541 const DATA_BLOB old_cookie,
2542 TALLOC_CTX *mem_ctx,
2543 struct files_struct **fsp,
2544 DATA_BLOB *new_cookie)
2546 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2547 old_cookie, mem_ctx,
2551 static struct vfs_fn_pointers vfs_default_fns = {
2552 /* Disk operations */
2554 .connect_fn = vfswrap_connect,
2555 .disconnect_fn = vfswrap_disconnect,
2556 .disk_free_fn = vfswrap_disk_free,
2557 .get_quota_fn = vfswrap_get_quota,
2558 .set_quota_fn = vfswrap_set_quota,
2559 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2560 .statvfs_fn = vfswrap_statvfs,
2561 .fs_capabilities_fn = vfswrap_fs_capabilities,
2562 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2563 .snap_check_path_fn = vfswrap_snap_check_path,
2564 .snap_create_fn = vfswrap_snap_create,
2565 .snap_delete_fn = vfswrap_snap_delete,
2567 /* Directory operations */
2569 .opendir_fn = vfswrap_opendir,
2570 .fdopendir_fn = vfswrap_fdopendir,
2571 .readdir_fn = vfswrap_readdir,
2572 .readdir_attr_fn = vfswrap_readdir_attr,
2573 .seekdir_fn = vfswrap_seekdir,
2574 .telldir_fn = vfswrap_telldir,
2575 .rewind_dir_fn = vfswrap_rewinddir,
2576 .mkdir_fn = vfswrap_mkdir,
2577 .rmdir_fn = vfswrap_rmdir,
2578 .closedir_fn = vfswrap_closedir,
2579 .init_search_op_fn = vfswrap_init_search_op,
2581 /* File operations */
2583 .open_fn = vfswrap_open,
2584 .create_file_fn = vfswrap_create_file,
2585 .close_fn = vfswrap_close,
2586 .read_fn = vfswrap_read,
2587 .pread_fn = vfswrap_pread,
2588 .pread_send_fn = vfswrap_pread_send,
2589 .pread_recv_fn = vfswrap_asys_ssize_t_recv,
2590 .write_fn = vfswrap_write,
2591 .pwrite_fn = vfswrap_pwrite,
2592 .pwrite_send_fn = vfswrap_pwrite_send,
2593 .pwrite_recv_fn = vfswrap_asys_ssize_t_recv,
2594 .lseek_fn = vfswrap_lseek,
2595 .sendfile_fn = vfswrap_sendfile,
2596 .recvfile_fn = vfswrap_recvfile,
2597 .rename_fn = vfswrap_rename,
2598 .fsync_fn = vfswrap_fsync,
2599 .fsync_send_fn = vfswrap_fsync_send,
2600 .fsync_recv_fn = vfswrap_asys_int_recv,
2601 .stat_fn = vfswrap_stat,
2602 .fstat_fn = vfswrap_fstat,
2603 .lstat_fn = vfswrap_lstat,
2604 .get_alloc_size_fn = vfswrap_get_alloc_size,
2605 .unlink_fn = vfswrap_unlink,
2606 .chmod_fn = vfswrap_chmod,
2607 .fchmod_fn = vfswrap_fchmod,
2608 .chown_fn = vfswrap_chown,
2609 .fchown_fn = vfswrap_fchown,
2610 .lchown_fn = vfswrap_lchown,
2611 .chdir_fn = vfswrap_chdir,
2612 .getwd_fn = vfswrap_getwd,
2613 .ntimes_fn = vfswrap_ntimes,
2614 .ftruncate_fn = vfswrap_ftruncate,
2615 .fallocate_fn = vfswrap_fallocate,
2616 .lock_fn = vfswrap_lock,
2617 .kernel_flock_fn = vfswrap_kernel_flock,
2618 .linux_setlease_fn = vfswrap_linux_setlease,
2619 .getlock_fn = vfswrap_getlock,
2620 .symlink_fn = vfswrap_symlink,
2621 .readlink_fn = vfswrap_readlink,
2622 .link_fn = vfswrap_link,
2623 .mknod_fn = vfswrap_mknod,
2624 .realpath_fn = vfswrap_realpath,
2625 .chflags_fn = vfswrap_chflags,
2626 .file_id_create_fn = vfswrap_file_id_create,
2627 .streaminfo_fn = vfswrap_streaminfo,
2628 .get_real_filename_fn = vfswrap_get_real_filename,
2629 .connectpath_fn = vfswrap_connectpath,
2630 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2631 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2632 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2633 .strict_lock_fn = vfswrap_strict_lock,
2634 .strict_unlock_fn = vfswrap_strict_unlock,
2635 .translate_name_fn = vfswrap_translate_name,
2636 .fsctl_fn = vfswrap_fsctl,
2637 .copy_chunk_send_fn = vfswrap_copy_chunk_send,
2638 .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
2639 .get_compression_fn = vfswrap_get_compression,
2640 .set_compression_fn = vfswrap_set_compression,
2642 /* NT ACL operations. */
2644 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2645 .get_nt_acl_fn = vfswrap_get_nt_acl,
2646 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2647 .audit_file_fn = vfswrap_audit_file,
2649 /* POSIX ACL operations. */
2651 .chmod_acl_fn = vfswrap_chmod_acl,
2652 .fchmod_acl_fn = vfswrap_fchmod_acl,
2654 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2655 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2656 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2657 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2658 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2659 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2660 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2662 /* EA operations. */
2663 .getxattr_fn = vfswrap_getxattr,
2664 .fgetxattr_fn = vfswrap_fgetxattr,
2665 .listxattr_fn = vfswrap_listxattr,
2666 .flistxattr_fn = vfswrap_flistxattr,
2667 .removexattr_fn = vfswrap_removexattr,
2668 .fremovexattr_fn = vfswrap_fremovexattr,
2669 .setxattr_fn = vfswrap_setxattr,
2670 .fsetxattr_fn = vfswrap_fsetxattr,
2672 /* aio operations */
2673 .aio_force_fn = vfswrap_aio_force,
2675 /* offline operations */
2676 .is_offline_fn = vfswrap_is_offline,
2677 .set_offline_fn = vfswrap_set_offline,
2679 /* durable handle operations */
2680 .durable_cookie_fn = vfswrap_durable_cookie,
2681 .durable_disconnect_fn = vfswrap_durable_disconnect,
2682 .durable_reconnect_fn = vfswrap_durable_reconnect,
2685 NTSTATUS vfs_default_init(void);
2686 NTSTATUS vfs_default_init(void)
2688 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
2689 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);