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,
1748 const struct smb_filename *smb_fname,
1754 START_PROFILE(syscall_chown);
1755 result = chown(smb_fname->base_name, uid, gid);
1756 END_PROFILE(syscall_chown);
1760 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
1765 START_PROFILE(syscall_fchown);
1766 result = fchown(fsp->fh->fd, uid, gid);
1767 END_PROFILE(syscall_fchown);
1775 static int vfswrap_lchown(vfs_handle_struct *handle,
1776 const struct smb_filename *smb_fname,
1782 START_PROFILE(syscall_lchown);
1783 result = lchown(smb_fname->base_name, uid, gid);
1784 END_PROFILE(syscall_lchown);
1788 static int vfswrap_chdir(vfs_handle_struct *handle, const char *path)
1792 START_PROFILE(syscall_chdir);
1793 result = chdir(path);
1794 END_PROFILE(syscall_chdir);
1798 static char *vfswrap_getwd(vfs_handle_struct *handle)
1802 START_PROFILE(syscall_getwd);
1803 result = sys_getwd();
1804 END_PROFILE(syscall_getwd);
1808 /*********************************************************************
1809 nsec timestamp resolution call. Convert down to whatever the underlying
1810 system will support.
1811 **********************************************************************/
1813 static int vfswrap_ntimes(vfs_handle_struct *handle,
1814 const struct smb_filename *smb_fname,
1815 struct smb_file_time *ft)
1819 START_PROFILE(syscall_ntimes);
1821 if (smb_fname->stream_name) {
1827 if (null_timespec(ft->atime)) {
1828 ft->atime= smb_fname->st.st_ex_atime;
1831 if (null_timespec(ft->mtime)) {
1832 ft->mtime = smb_fname->st.st_ex_mtime;
1835 if (!null_timespec(ft->create_time)) {
1836 set_create_timespec_ea(handle->conn,
1841 if ((timespec_compare(&ft->atime,
1842 &smb_fname->st.st_ex_atime) == 0) &&
1843 (timespec_compare(&ft->mtime,
1844 &smb_fname->st.st_ex_mtime) == 0)) {
1849 #if defined(HAVE_UTIMENSAT)
1851 struct timespec ts[2];
1854 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
1856 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
1858 if (!((result == -1) && (errno == ENOSYS))) {
1862 #if defined(HAVE_UTIMES)
1864 struct timeval tv[2];
1865 tv[0] = convert_timespec_to_timeval(ft->atime);
1866 tv[1] = convert_timespec_to_timeval(ft->mtime);
1867 result = utimes(smb_fname->base_name, tv);
1869 result = utimes(smb_fname->base_name, NULL);
1871 if (!((result == -1) && (errno == ENOSYS))) {
1875 #if defined(HAVE_UTIME)
1877 struct utimbuf times;
1878 times.actime = convert_timespec_to_time_t(ft->atime);
1879 times.modtime = convert_timespec_to_time_t(ft->mtime);
1880 result = utime(smb_fname->base_name, ×);
1882 result = utime(smb_fname->base_name, NULL);
1884 if (!((result == -1) && (errno == ENOSYS))) {
1892 END_PROFILE(syscall_ntimes);
1896 /*********************************************************************
1897 A version of ftruncate that will write the space on disk if strict
1899 **********************************************************************/
1901 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1903 off_t space_to_write;
1904 uint64_t space_avail;
1905 uint64_t bsize,dfree,dsize;
1908 SMB_STRUCT_STAT *pst;
1910 status = vfs_stat_fsp(fsp);
1911 if (!NT_STATUS_IS_OK(status)) {
1914 pst = &fsp->fsp_name->st;
1917 if (S_ISFIFO(pst->st_ex_mode))
1921 if (pst->st_ex_size == len)
1924 /* Shrink - just ftruncate. */
1925 if (pst->st_ex_size > len)
1926 return ftruncate(fsp->fh->fd, len);
1928 space_to_write = len - pst->st_ex_size;
1930 /* for allocation try fallocate first. This can fail on some
1931 platforms e.g. when the filesystem doesn't support it and no
1932 emulation is being done by the libc (like on AIX with JFS1). In that
1933 case we do our own emulation. fallocate implementations can
1934 return ENOTSUP or EINVAL in cases like that. */
1935 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
1936 if (ret == -1 && errno == ENOSPC) {
1942 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
1943 "error %d. Falling back to slow manual allocation\n", errno));
1945 /* available disk space is enough or not? */
1946 space_avail = get_dfree_info(fsp->conn,
1947 fsp->fsp_name->base_name,
1948 &bsize, &dfree, &dsize);
1949 /* space_avail is 1k blocks */
1950 if (space_avail == (uint64_t)-1 ||
1951 ((uint64_t)space_to_write/1024 > space_avail) ) {
1956 /* Write out the real space on disk. */
1957 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
1965 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1968 SMB_STRUCT_STAT *pst;
1972 START_PROFILE(syscall_ftruncate);
1974 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
1975 result = strict_allocate_ftruncate(handle, fsp, len);
1976 END_PROFILE(syscall_ftruncate);
1980 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
1981 ftruncate if the system supports it. Then I discovered that
1982 you can have some filesystems that support ftruncate
1983 expansion and some that don't! On Linux fat can't do
1984 ftruncate extend but ext2 can. */
1986 result = ftruncate(fsp->fh->fd, len);
1988 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
1989 extend a file with ftruncate. Provide alternate implementation
1992 /* Do an fstat to see if the file is longer than the requested
1993 size in which case the ftruncate above should have
1994 succeeded or shorter, in which case seek to len - 1 and
1995 write 1 byte of zero */
1996 status = vfs_stat_fsp(fsp);
1997 if (!NT_STATUS_IS_OK(status)) {
2001 /* We need to update the files_struct after successful ftruncate */
2006 pst = &fsp->fsp_name->st;
2009 if (S_ISFIFO(pst->st_ex_mode)) {
2015 if (pst->st_ex_size == len) {
2020 if (pst->st_ex_size > len) {
2021 /* the ftruncate should have worked */
2025 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2033 END_PROFILE(syscall_ftruncate);
2037 static int vfswrap_fallocate(vfs_handle_struct *handle,
2045 START_PROFILE(syscall_fallocate);
2047 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2049 * posix_fallocate returns 0 on success, errno on error
2050 * and doesn't set errno. Make it behave like fallocate()
2051 * which returns -1, and sets errno on failure.
2058 /* sys_fallocate handles filtering of unsupported mode flags */
2059 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2061 END_PROFILE(syscall_fallocate);
2065 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2069 START_PROFILE(syscall_fcntl_lock);
2070 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2071 END_PROFILE(syscall_fcntl_lock);
2075 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2076 uint32_t share_mode, uint32_t access_mask)
2078 START_PROFILE(syscall_kernel_flock);
2079 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2080 END_PROFILE(syscall_kernel_flock);
2084 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2088 START_PROFILE(syscall_fcntl_getlock);
2089 result = fcntl_getlock(fsp->fh->fd, poffset, pcount, ptype, ppid);
2090 END_PROFILE(syscall_fcntl_getlock);
2094 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2099 START_PROFILE(syscall_linux_setlease);
2101 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2102 result = linux_setlease(fsp->fh->fd, leasetype);
2106 END_PROFILE(syscall_linux_setlease);
2110 static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2114 START_PROFILE(syscall_symlink);
2115 result = symlink(oldpath, newpath);
2116 END_PROFILE(syscall_symlink);
2120 static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
2124 START_PROFILE(syscall_readlink);
2125 result = readlink(path, buf, bufsiz);
2126 END_PROFILE(syscall_readlink);
2130 static int vfswrap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2134 START_PROFILE(syscall_link);
2135 result = link(oldpath, newpath);
2136 END_PROFILE(syscall_link);
2140 static int vfswrap_mknod(vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev)
2144 START_PROFILE(syscall_mknod);
2145 result = sys_mknod(pathname, mode, dev);
2146 END_PROFILE(syscall_mknod);
2150 static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
2154 START_PROFILE(syscall_realpath);
2155 result = sys_realpath(path);
2156 END_PROFILE(syscall_realpath);
2160 static int vfswrap_chflags(vfs_handle_struct *handle, const char *path,
2164 return chflags(path, flags);
2171 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2172 const SMB_STRUCT_STAT *sbuf)
2176 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2180 key.devid = sbuf->st_ex_dev;
2181 key.inode = sbuf->st_ex_ino;
2182 /* key.extid is unused by default. */
2187 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2188 struct files_struct *fsp,
2189 const struct smb_filename *smb_fname,
2190 TALLOC_CTX *mem_ctx,
2191 unsigned int *pnum_streams,
2192 struct stream_struct **pstreams)
2194 SMB_STRUCT_STAT sbuf;
2195 struct stream_struct *tmp_streams = NULL;
2198 if ((fsp != NULL) && (fsp->is_directory)) {
2200 * No default streams on directories
2205 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2206 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2209 struct smb_filename smb_fname_cp;
2211 ZERO_STRUCT(smb_fname_cp);
2212 smb_fname_cp.base_name = discard_const_p(char,
2213 smb_fname->base_name);
2215 if (lp_posix_pathnames()) {
2216 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2218 ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2220 sbuf = smb_fname_cp.st;
2224 return map_nt_error_from_unix(errno);
2227 if (S_ISDIR(sbuf.st_ex_mode)) {
2231 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2232 (*pnum_streams) + 1);
2233 if (tmp_streams == NULL) {
2234 return NT_STATUS_NO_MEMORY;
2236 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2237 if (tmp_streams[*pnum_streams].name == NULL) {
2238 return NT_STATUS_NO_MEMORY;
2240 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2241 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2244 *pstreams = tmp_streams;
2246 return NT_STATUS_OK;
2249 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2252 TALLOC_CTX *mem_ctx,
2256 * Don't fall back to get_real_filename so callers can differentiate
2257 * between a full directory scan and an actual case-insensitive stat.
2263 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2266 return handle->conn->connectpath;
2269 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2270 struct byte_range_lock *br_lck,
2271 struct lock_struct *plock,
2274 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2276 /* Note: blr is not used in the default implementation. */
2277 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2280 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2281 struct messaging_context *msg_ctx,
2282 struct byte_range_lock *br_lck,
2283 const struct lock_struct *plock)
2285 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2287 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2290 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2291 struct byte_range_lock *br_lck,
2292 struct lock_struct *plock)
2294 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2296 /* Note: blr is not used in the default implementation. */
2297 return brl_lock_cancel_default(br_lck, plock);
2300 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2302 struct lock_struct *plock)
2304 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2305 plock->lock_type == WRITE_LOCK);
2307 return strict_lock_default(fsp, plock);
2310 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2312 struct lock_struct *plock)
2314 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2315 plock->lock_type == WRITE_LOCK);
2317 strict_unlock_default(fsp, plock);
2320 /* NT ACL operations. */
2322 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2324 uint32_t security_info,
2325 TALLOC_CTX *mem_ctx,
2326 struct security_descriptor **ppdesc)
2330 START_PROFILE(fget_nt_acl);
2331 result = posix_fget_nt_acl(fsp, security_info,
2333 END_PROFILE(fget_nt_acl);
2337 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2338 const struct smb_filename *smb_fname,
2339 uint32_t security_info,
2340 TALLOC_CTX *mem_ctx,
2341 struct security_descriptor **ppdesc)
2345 START_PROFILE(get_nt_acl);
2346 result = posix_get_nt_acl(handle->conn,
2351 END_PROFILE(get_nt_acl);
2355 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2359 START_PROFILE(fset_nt_acl);
2360 result = set_nt_acl(fsp, security_info_sent, psd);
2361 END_PROFILE(fset_nt_acl);
2365 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2366 struct smb_filename *file,
2367 struct security_acl *sacl,
2368 uint32_t access_requested,
2369 uint32_t access_denied)
2371 return NT_STATUS_OK; /* Nothing to do here ... */
2374 static int vfswrap_chmod_acl(vfs_handle_struct *handle,
2375 const struct smb_filename *smb_fname,
2384 START_PROFILE(chmod_acl);
2385 result = chmod_acl(handle->conn, smb_fname->base_name, mode);
2386 END_PROFILE(chmod_acl);
2391 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2399 START_PROFILE(fchmod_acl);
2400 result = fchmod_acl(fsp, mode);
2401 END_PROFILE(fchmod_acl);
2406 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2408 SMB_ACL_TYPE_T type,
2409 TALLOC_CTX *mem_ctx)
2411 return sys_acl_get_file(handle, path_p, type, mem_ctx);
2414 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2416 TALLOC_CTX *mem_ctx)
2418 return sys_acl_get_fd(handle, fsp, mem_ctx);
2421 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2423 return sys_acl_set_file(handle, name, acltype, theacl);
2426 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2428 return sys_acl_set_fd(handle, fsp, theacl);
2431 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
2433 return sys_acl_delete_def_file(handle, path);
2436 /****************************************************************
2437 Extended attribute operations.
2438 *****************************************************************/
2440 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
2442 return getxattr(path, name, value, size);
2445 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2447 return fgetxattr(fsp->fh->fd, name, value, size);
2450 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
2452 return listxattr(path, list, size);
2455 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2457 return flistxattr(fsp->fh->fd, list, size);
2460 static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
2462 return removexattr(path, name);
2465 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2467 return fremovexattr(fsp->fh->fd, name);
2470 static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
2472 return setxattr(path, name, value, size, flags);
2475 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2477 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2480 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2485 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2486 const struct smb_filename *fname,
2487 SMB_STRUCT_STAT *sbuf)
2491 bool offline = false;
2493 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2497 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2498 #if defined(ENOTSUP)
2504 status = get_full_smb_filename(talloc_tos(), fname, &path);
2505 if (!NT_STATUS_IS_OK(status)) {
2506 errno = map_errno_from_nt_status(status);
2510 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2517 static int vfswrap_set_offline(struct vfs_handle_struct *handle,
2518 const struct smb_filename *fname)
2520 /* We don't know how to set offline bit by default, needs to be overriden in the vfs modules */
2521 #if defined(ENOTSUP)
2527 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2528 struct files_struct *fsp,
2529 TALLOC_CTX *mem_ctx,
2532 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2535 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2536 struct files_struct *fsp,
2537 const DATA_BLOB old_cookie,
2538 TALLOC_CTX *mem_ctx,
2539 DATA_BLOB *new_cookie)
2541 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2545 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2546 struct smb_request *smb1req,
2547 struct smbXsrv_open *op,
2548 const DATA_BLOB old_cookie,
2549 TALLOC_CTX *mem_ctx,
2550 struct files_struct **fsp,
2551 DATA_BLOB *new_cookie)
2553 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2554 old_cookie, mem_ctx,
2558 static struct vfs_fn_pointers vfs_default_fns = {
2559 /* Disk operations */
2561 .connect_fn = vfswrap_connect,
2562 .disconnect_fn = vfswrap_disconnect,
2563 .disk_free_fn = vfswrap_disk_free,
2564 .get_quota_fn = vfswrap_get_quota,
2565 .set_quota_fn = vfswrap_set_quota,
2566 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2567 .statvfs_fn = vfswrap_statvfs,
2568 .fs_capabilities_fn = vfswrap_fs_capabilities,
2569 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2570 .snap_check_path_fn = vfswrap_snap_check_path,
2571 .snap_create_fn = vfswrap_snap_create,
2572 .snap_delete_fn = vfswrap_snap_delete,
2574 /* Directory operations */
2576 .opendir_fn = vfswrap_opendir,
2577 .fdopendir_fn = vfswrap_fdopendir,
2578 .readdir_fn = vfswrap_readdir,
2579 .readdir_attr_fn = vfswrap_readdir_attr,
2580 .seekdir_fn = vfswrap_seekdir,
2581 .telldir_fn = vfswrap_telldir,
2582 .rewind_dir_fn = vfswrap_rewinddir,
2583 .mkdir_fn = vfswrap_mkdir,
2584 .rmdir_fn = vfswrap_rmdir,
2585 .closedir_fn = vfswrap_closedir,
2586 .init_search_op_fn = vfswrap_init_search_op,
2588 /* File operations */
2590 .open_fn = vfswrap_open,
2591 .create_file_fn = vfswrap_create_file,
2592 .close_fn = vfswrap_close,
2593 .read_fn = vfswrap_read,
2594 .pread_fn = vfswrap_pread,
2595 .pread_send_fn = vfswrap_pread_send,
2596 .pread_recv_fn = vfswrap_asys_ssize_t_recv,
2597 .write_fn = vfswrap_write,
2598 .pwrite_fn = vfswrap_pwrite,
2599 .pwrite_send_fn = vfswrap_pwrite_send,
2600 .pwrite_recv_fn = vfswrap_asys_ssize_t_recv,
2601 .lseek_fn = vfswrap_lseek,
2602 .sendfile_fn = vfswrap_sendfile,
2603 .recvfile_fn = vfswrap_recvfile,
2604 .rename_fn = vfswrap_rename,
2605 .fsync_fn = vfswrap_fsync,
2606 .fsync_send_fn = vfswrap_fsync_send,
2607 .fsync_recv_fn = vfswrap_asys_int_recv,
2608 .stat_fn = vfswrap_stat,
2609 .fstat_fn = vfswrap_fstat,
2610 .lstat_fn = vfswrap_lstat,
2611 .get_alloc_size_fn = vfswrap_get_alloc_size,
2612 .unlink_fn = vfswrap_unlink,
2613 .chmod_fn = vfswrap_chmod,
2614 .fchmod_fn = vfswrap_fchmod,
2615 .chown_fn = vfswrap_chown,
2616 .fchown_fn = vfswrap_fchown,
2617 .lchown_fn = vfswrap_lchown,
2618 .chdir_fn = vfswrap_chdir,
2619 .getwd_fn = vfswrap_getwd,
2620 .ntimes_fn = vfswrap_ntimes,
2621 .ftruncate_fn = vfswrap_ftruncate,
2622 .fallocate_fn = vfswrap_fallocate,
2623 .lock_fn = vfswrap_lock,
2624 .kernel_flock_fn = vfswrap_kernel_flock,
2625 .linux_setlease_fn = vfswrap_linux_setlease,
2626 .getlock_fn = vfswrap_getlock,
2627 .symlink_fn = vfswrap_symlink,
2628 .readlink_fn = vfswrap_readlink,
2629 .link_fn = vfswrap_link,
2630 .mknod_fn = vfswrap_mknod,
2631 .realpath_fn = vfswrap_realpath,
2632 .chflags_fn = vfswrap_chflags,
2633 .file_id_create_fn = vfswrap_file_id_create,
2634 .streaminfo_fn = vfswrap_streaminfo,
2635 .get_real_filename_fn = vfswrap_get_real_filename,
2636 .connectpath_fn = vfswrap_connectpath,
2637 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2638 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2639 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2640 .strict_lock_fn = vfswrap_strict_lock,
2641 .strict_unlock_fn = vfswrap_strict_unlock,
2642 .translate_name_fn = vfswrap_translate_name,
2643 .fsctl_fn = vfswrap_fsctl,
2644 .copy_chunk_send_fn = vfswrap_copy_chunk_send,
2645 .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
2646 .get_compression_fn = vfswrap_get_compression,
2647 .set_compression_fn = vfswrap_set_compression,
2649 /* NT ACL operations. */
2651 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2652 .get_nt_acl_fn = vfswrap_get_nt_acl,
2653 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2654 .audit_file_fn = vfswrap_audit_file,
2656 /* POSIX ACL operations. */
2658 .chmod_acl_fn = vfswrap_chmod_acl,
2659 .fchmod_acl_fn = vfswrap_fchmod_acl,
2661 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2662 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2663 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2664 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2665 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2666 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2667 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2669 /* EA operations. */
2670 .getxattr_fn = vfswrap_getxattr,
2671 .fgetxattr_fn = vfswrap_fgetxattr,
2672 .listxattr_fn = vfswrap_listxattr,
2673 .flistxattr_fn = vfswrap_flistxattr,
2674 .removexattr_fn = vfswrap_removexattr,
2675 .fremovexattr_fn = vfswrap_fremovexattr,
2676 .setxattr_fn = vfswrap_setxattr,
2677 .fsetxattr_fn = vfswrap_fsetxattr,
2679 /* aio operations */
2680 .aio_force_fn = vfswrap_aio_force,
2682 /* offline operations */
2683 .is_offline_fn = vfswrap_is_offline,
2684 .set_offline_fn = vfswrap_set_offline,
2686 /* durable handle operations */
2687 .durable_cookie_fn = vfswrap_durable_cookie,
2688 .durable_disconnect_fn = vfswrap_durable_disconnect,
2689 .durable_reconnect_fn = vfswrap_durable_reconnect,
2692 NTSTATUS vfs_default_init(void);
2693 NTSTATUS vfs_default_init(void)
2695 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
2696 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);