2 Unix SMB/CIFS implementation.
3 Wrap disk only vfs functions to sidestep dodgy compilers.
4 Copyright (C) Tim Potter 1998
5 Copyright (C) Jeremy Allison 2007
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "system/time.h"
23 #include "system/filesys.h"
24 #include "smbd/smbd.h"
25 #include "smbd/globals.h"
27 #include "smbprofile.h"
28 #include "../libcli/security/security.h"
29 #include "passdb/lookup_sid.h"
30 #include "source3/include/msdfs.h"
31 #include "librpc/gen_ndr/ndr_dfsblobs.h"
32 #include "lib/util/tevent_unix.h"
33 #include "lib/asys/asys.h"
34 #include "lib/util/tevent_ntstatus.h"
35 #include "lib/util/sys_rw.h"
38 #define DBGC_CLASS DBGC_VFS
40 /* Check for NULL pointer parameters in vfswrap_* functions */
42 /* We don't want to have NULL function pointers lying around. Someone
43 is sure to try and execute them. These stubs are used to prevent
46 static int vfswrap_connect(vfs_handle_struct *handle, const char *service, const char *user)
48 return 0; /* Return >= 0 for success */
51 static void vfswrap_disconnect(vfs_handle_struct *handle)
57 static uint64_t vfswrap_disk_free(vfs_handle_struct *handle, const char *path,
58 uint64_t *bsize, uint64_t *dfree,
61 if (sys_fsusage(path, dfree, dsize) != 0) {
69 static int vfswrap_get_quota(struct vfs_handle_struct *handle, const char *path,
70 enum SMB_QUOTA_TYPE qtype, unid_t id,
73 #ifdef HAVE_SYS_QUOTAS
76 START_PROFILE(syscall_get_quota);
77 result = sys_get_quota(path, qtype, id, qt);
78 END_PROFILE(syscall_get_quota);
86 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
88 #ifdef HAVE_SYS_QUOTAS
91 START_PROFILE(syscall_set_quota);
92 result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
93 END_PROFILE(syscall_set_quota);
101 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
102 struct files_struct *fsp,
103 struct shadow_copy_data *shadow_copy_data,
107 return -1; /* Not implemented. */
110 static int vfswrap_statvfs(struct vfs_handle_struct *handle, const char *path, vfs_statvfs_struct *statbuf)
112 return sys_statvfs(path, statbuf);
115 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
116 enum timestamp_set_resolution *p_ts_res)
118 connection_struct *conn = handle->conn;
119 uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
120 struct smb_filename *smb_fname_cpath = NULL;
121 struct vfs_statvfs_struct statbuf;
124 ZERO_STRUCT(statbuf);
125 ret = sys_statvfs(conn->connectpath, &statbuf);
127 caps = statbuf.FsCapabilities;
130 *p_ts_res = TIMESTAMP_SET_SECONDS;
132 /* Work out what timestamp resolution we can
133 * use when setting a timestamp. */
135 smb_fname_cpath = synthetic_smb_fname(talloc_tos(), conn->connectpath,
137 if (smb_fname_cpath == NULL) {
141 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
143 TALLOC_FREE(smb_fname_cpath);
147 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
148 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
149 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
150 /* If any of the normal UNIX directory timestamps
151 * have a non-zero tv_nsec component assume
152 * we might be able to set sub-second timestamps.
153 * See what filetime set primitives we have.
155 #if defined(HAVE_UTIMENSAT)
156 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
157 #elif defined(HAVE_UTIMES)
158 /* utimes allows msec timestamps to be set. */
159 *p_ts_res = TIMESTAMP_SET_MSEC;
160 #elif defined(HAVE_UTIME)
161 /* utime only allows sec timestamps to be set. */
162 *p_ts_res = TIMESTAMP_SET_SECONDS;
165 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
167 "available on share %s, directory %s\n",
168 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
169 lp_servicename(talloc_tos(), conn->params->service),
170 conn->connectpath ));
172 TALLOC_FREE(smb_fname_cpath);
176 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
177 struct dfs_GetDFSReferral *r)
179 struct junction_map *junction = NULL;
181 bool self_referral = false;
182 char *pathnamep = NULL;
183 char *local_dfs_path = NULL;
186 uint16_t max_referral_level = r->in.req.max_referral_level;
189 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
192 /* get the junction entry */
193 if (r->in.req.servername == NULL) {
194 return NT_STATUS_NOT_FOUND;
198 * Trim pathname sent by client so it begins with only one backslash.
199 * Two backslashes confuse some dfs clients
202 local_dfs_path = talloc_strdup(r, r->in.req.servername);
203 if (local_dfs_path == NULL) {
204 return NT_STATUS_NO_MEMORY;
206 pathnamep = local_dfs_path;
207 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
208 IS_DIRECTORY_SEP(pathnamep[1])) {
212 junction = talloc_zero(r, struct junction_map);
213 if (junction == NULL) {
214 return NT_STATUS_NO_MEMORY;
217 /* The following call can change cwd. */
218 status = get_referred_path(r, pathnamep,
219 !handle->conn->sconn->using_smb2,
220 junction, &consumedcnt, &self_referral);
221 if (!NT_STATUS_IS_OK(status)) {
222 vfs_ChDir(handle->conn, handle->conn->connectpath);
225 vfs_ChDir(handle->conn, handle->conn->connectpath);
227 if (!self_referral) {
228 pathnamep[consumedcnt] = '\0';
231 dbgtext("Path %s to alternate path(s):",
233 for (i=0; i < junction->referral_count; i++) {
235 junction->referral_list[i].alternate_path);
241 if (r->in.req.max_referral_level <= 2) {
242 max_referral_level = 2;
244 if (r->in.req.max_referral_level >= 3) {
245 max_referral_level = 3;
248 r->out.resp = talloc_zero(r, struct dfs_referral_resp);
249 if (r->out.resp == NULL) {
250 return NT_STATUS_NO_MEMORY;
253 r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
254 r->out.resp->nb_referrals = junction->referral_count;
256 r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
258 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
261 r->out.resp->referral_entries = talloc_zero_array(r,
262 struct dfs_referral_type,
263 r->out.resp->nb_referrals);
264 if (r->out.resp->referral_entries == NULL) {
265 return NT_STATUS_NO_MEMORY;
268 switch (max_referral_level) {
270 for(i=0; i < junction->referral_count; i++) {
271 struct referral *ref = &junction->referral_list[i];
272 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
273 struct dfs_referral_type *t =
274 &r->out.resp->referral_entries[i];
275 struct dfs_referral_v2 *v2 = &t->referral.v2;
278 v2->size = VERSION2_REFERRAL_SIZE;
280 v2->server_type = DFS_SERVER_ROOT;
282 v2->server_type = DFS_SERVER_NON_ROOT;
285 v2->proximity = ref->proximity;
287 v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
288 if (v2->DFS_path == NULL) {
289 return NT_STATUS_NO_MEMORY;
291 v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
292 if (v2->DFS_alt_path == NULL) {
293 return NT_STATUS_NO_MEMORY;
295 v2->netw_address = talloc_strdup(mem_ctx,
296 ref->alternate_path);
297 if (v2->netw_address == NULL) {
298 return NT_STATUS_NO_MEMORY;
304 for(i=0; i < junction->referral_count; i++) {
305 struct referral *ref = &junction->referral_list[i];
306 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
307 struct dfs_referral_type *t =
308 &r->out.resp->referral_entries[i];
309 struct dfs_referral_v3 *v3 = &t->referral.v3;
310 struct dfs_normal_referral *r1 = &v3->referrals.r1;
313 v3->size = VERSION3_REFERRAL_SIZE;
315 v3->server_type = DFS_SERVER_ROOT;
317 v3->server_type = DFS_SERVER_NON_ROOT;
321 r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
322 if (r1->DFS_path == NULL) {
323 return NT_STATUS_NO_MEMORY;
325 r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
326 if (r1->DFS_alt_path == NULL) {
327 return NT_STATUS_NO_MEMORY;
329 r1->netw_address = talloc_strdup(mem_ctx,
330 ref->alternate_path);
331 if (r1->netw_address == NULL) {
332 return NT_STATUS_NO_MEMORY;
337 DEBUG(0,("Invalid dfs referral version: %d\n",
338 max_referral_level));
339 return NT_STATUS_INVALID_LEVEL;
343 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
349 static NTSTATUS vfswrap_snap_check_path(struct vfs_handle_struct *handle,
351 const char *service_path,
354 return NT_STATUS_NOT_SUPPORTED;
357 static NTSTATUS vfswrap_snap_create(struct vfs_handle_struct *handle,
359 const char *base_volume,
365 return NT_STATUS_NOT_SUPPORTED;
368 static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle,
373 return NT_STATUS_NOT_SUPPORTED;
376 /* Directory operations */
378 static DIR *vfswrap_opendir(vfs_handle_struct *handle,
379 const struct smb_filename *smb_fname,
385 START_PROFILE(syscall_opendir);
386 result = opendir(smb_fname->base_name);
387 END_PROFILE(syscall_opendir);
391 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
398 START_PROFILE(syscall_fdopendir);
399 result = sys_fdopendir(fsp->fh->fd);
400 END_PROFILE(syscall_fdopendir);
405 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
407 SMB_STRUCT_STAT *sbuf)
409 struct dirent *result;
411 START_PROFILE(syscall_readdir);
412 result = readdir(dirp);
413 END_PROFILE(syscall_readdir);
415 /* Default Posix readdir() does not give us stat info.
416 * Set to invalid to indicate we didn't return this info. */
417 SET_STAT_INVALID(*sbuf);
418 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
419 if (result != NULL) {
420 /* See if we can efficiently return this. */
422 int flags = (lp_posix_pathnames() ?
423 AT_SYMLINK_NOFOLLOW : 0);
424 int ret = fstatat(dirfd(dirp),
429 init_stat_ex_from_stat(sbuf,
431 lp_fake_directory_create_times(
432 SNUM(handle->conn)));
440 static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
441 const struct smb_filename *fname,
443 struct readdir_attr_data **attr_data)
445 return NT_STATUS_NOT_SUPPORTED;
448 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
450 START_PROFILE(syscall_seekdir);
451 seekdir(dirp, offset);
452 END_PROFILE(syscall_seekdir);
455 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
458 START_PROFILE(syscall_telldir);
459 result = telldir(dirp);
460 END_PROFILE(syscall_telldir);
464 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
466 START_PROFILE(syscall_rewinddir);
468 END_PROFILE(syscall_rewinddir);
471 static int vfswrap_mkdir(vfs_handle_struct *handle,
472 const struct smb_filename *smb_fname,
476 bool has_dacl = False;
477 const char *path = smb_fname->base_name;
480 START_PROFILE(syscall_mkdir);
482 if (lp_inherit_acls(SNUM(handle->conn))
483 && parent_dirname(talloc_tos(), path, &parent, NULL)
484 && (has_dacl = directory_has_default_acl(handle->conn, parent))) {
485 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
490 result = mkdir(path, mode);
492 if (result == 0 && !has_dacl) {
494 * We need to do this as the default behavior of POSIX ACLs
495 * is to set the mask to be the requested group permission
496 * bits, not the group permission bits to be the requested
497 * group permission bits. This is not what we want, as it will
498 * mess up any inherited ACL bits that were set. JRA.
500 int saved_errno = errno; /* We may get ENOSYS */
501 if ((SMB_VFS_CHMOD_ACL(handle->conn, path, mode) == -1) && (errno == ENOSYS))
505 END_PROFILE(syscall_mkdir);
509 static int vfswrap_rmdir(vfs_handle_struct *handle,
510 const struct smb_filename *smb_fname)
514 START_PROFILE(syscall_rmdir);
515 result = rmdir(smb_fname->base_name);
516 END_PROFILE(syscall_rmdir);
520 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
524 START_PROFILE(syscall_closedir);
525 result = closedir(dirp);
526 END_PROFILE(syscall_closedir);
530 static void vfswrap_init_search_op(vfs_handle_struct *handle,
533 /* Default behavior is a NOOP */
536 /* File operations */
538 static int vfswrap_open(vfs_handle_struct *handle,
539 struct smb_filename *smb_fname,
540 files_struct *fsp, int flags, mode_t mode)
544 START_PROFILE(syscall_open);
546 if (smb_fname->stream_name) {
551 result = open(smb_fname->base_name, flags, mode);
553 END_PROFILE(syscall_open);
557 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
558 struct smb_request *req,
559 uint16_t root_dir_fid,
560 struct smb_filename *smb_fname,
561 uint32_t access_mask,
562 uint32_t share_access,
563 uint32_t create_disposition,
564 uint32_t create_options,
565 uint32_t file_attributes,
566 uint32_t oplock_request,
567 struct smb2_lease *lease,
568 uint64_t allocation_size,
569 uint32_t private_flags,
570 struct security_descriptor *sd,
571 struct ea_list *ea_list,
572 files_struct **result,
574 const struct smb2_create_blobs *in_context_blobs,
575 struct smb2_create_blobs *out_context_blobs)
577 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
578 access_mask, share_access,
579 create_disposition, create_options,
580 file_attributes, oplock_request, lease,
581 allocation_size, private_flags,
583 pinfo, in_context_blobs, out_context_blobs);
586 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
590 START_PROFILE(syscall_close);
591 result = fd_close_posix(fsp);
592 END_PROFILE(syscall_close);
596 static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
600 START_PROFILE_BYTES(syscall_read, n);
601 result = sys_read(fsp->fh->fd, data, n);
602 END_PROFILE_BYTES(syscall_read);
606 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
607 size_t n, off_t offset)
611 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
612 START_PROFILE_BYTES(syscall_pread, n);
613 result = sys_pread(fsp->fh->fd, data, n, offset);
614 END_PROFILE_BYTES(syscall_pread);
616 if (result == -1 && errno == ESPIPE) {
617 /* Maintain the fiction that pipes can be seeked (sought?) on. */
618 result = SMB_VFS_READ(fsp, data, n);
622 #else /* HAVE_PREAD */
626 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
627 if (curr == -1 && errno == ESPIPE) {
628 /* Maintain the fiction that pipes can be seeked (sought?) on. */
629 result = SMB_VFS_READ(fsp, data, n);
634 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
639 result = SMB_VFS_READ(fsp, data, n);
642 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
645 #endif /* HAVE_PREAD */
650 static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
654 START_PROFILE_BYTES(syscall_write, n);
655 result = sys_write(fsp->fh->fd, data, n);
656 END_PROFILE_BYTES(syscall_write);
660 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
661 size_t n, off_t offset)
665 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
666 START_PROFILE_BYTES(syscall_pwrite, n);
667 result = sys_pwrite(fsp->fh->fd, data, n, offset);
668 END_PROFILE_BYTES(syscall_pwrite);
670 if (result == -1 && errno == ESPIPE) {
671 /* Maintain the fiction that pipes can be sought on. */
672 result = SMB_VFS_WRITE(fsp, data, n);
675 #else /* HAVE_PWRITE */
679 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
684 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
688 result = SMB_VFS_WRITE(fsp, data, n);
691 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
694 #endif /* HAVE_PWRITE */
699 static void vfswrap_asys_finished(struct tevent_context *ev,
700 struct tevent_fd *fde,
701 uint16_t flags, void *p);
703 static bool vfswrap_init_asys_ctx(struct smbd_server_connection *conn)
705 struct asys_context *ctx;
706 struct tevent_fd *fde;
710 if (conn->asys_ctx != NULL) {
714 ret = asys_context_init(&ctx, lp_aio_max_threads());
716 DEBUG(1, ("asys_context_init failed: %s\n", strerror(ret)));
720 fd = asys_signalfd(ctx);
722 ret = set_blocking(fd, false);
724 DBG_WARNING("set_blocking failed: %s\n", strerror(errno));
728 fde = tevent_add_fd(conn->ev_ctx, conn, fd, TEVENT_FD_READ,
729 vfswrap_asys_finished, ctx);
731 DEBUG(1, ("tevent_add_fd failed\n"));
735 conn->asys_ctx = ctx;
736 conn->asys_fde = fde;
740 asys_context_destroy(ctx);
744 struct vfswrap_asys_state {
745 struct asys_context *asys_ctx;
746 struct tevent_req *req;
749 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
750 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
753 static int vfswrap_asys_state_destructor(struct vfswrap_asys_state *s)
755 asys_cancel(s->asys_ctx, s->req);
759 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
761 struct tevent_context *ev,
762 struct files_struct *fsp,
764 size_t n, off_t offset)
766 struct tevent_req *req;
767 struct vfswrap_asys_state *state;
770 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
774 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
776 return tevent_req_post(req, ev);
778 state->asys_ctx = handle->conn->sconn->asys_ctx;
781 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
782 state->profile_bytes, n);
783 ret = asys_pread(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
785 tevent_req_error(req, ret);
786 return tevent_req_post(req, ev);
788 talloc_set_destructor(state, vfswrap_asys_state_destructor);
793 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
795 struct tevent_context *ev,
796 struct files_struct *fsp,
798 size_t n, off_t offset)
800 struct tevent_req *req;
801 struct vfswrap_asys_state *state;
804 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
808 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
810 return tevent_req_post(req, ev);
812 state->asys_ctx = handle->conn->sconn->asys_ctx;
815 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
816 state->profile_bytes, n);
817 ret = asys_pwrite(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
819 tevent_req_error(req, ret);
820 return tevent_req_post(req, ev);
822 talloc_set_destructor(state, vfswrap_asys_state_destructor);
827 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
829 struct tevent_context *ev,
830 struct files_struct *fsp)
832 struct tevent_req *req;
833 struct vfswrap_asys_state *state;
836 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
840 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
842 return tevent_req_post(req, ev);
844 state->asys_ctx = handle->conn->sconn->asys_ctx;
847 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
848 state->profile_basic);
849 ret = asys_fsync(state->asys_ctx, fsp->fh->fd, req);
851 tevent_req_error(req, ret);
852 return tevent_req_post(req, ev);
854 talloc_set_destructor(state, vfswrap_asys_state_destructor);
859 static void vfswrap_asys_finished(struct tevent_context *ev,
860 struct tevent_fd *fde,
861 uint16_t flags, void *p)
863 struct asys_context *asys_ctx = (struct asys_context *)p;
864 struct asys_result results[get_outstanding_aio_calls()];
867 if ((flags & TEVENT_FD_READ) == 0) {
871 ret = asys_results(asys_ctx, results, get_outstanding_aio_calls());
873 DEBUG(1, ("asys_results returned %s\n", strerror(-ret)));
877 for (i=0; i<ret; i++) {
878 struct asys_result *result = &results[i];
879 struct tevent_req *req;
880 struct vfswrap_asys_state *state;
882 if ((result->ret == -1) && (result->err == ECANCELED)) {
886 req = talloc_get_type_abort(result->private_data,
888 state = tevent_req_data(req, struct vfswrap_asys_state);
890 talloc_set_destructor(state, NULL);
892 SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
893 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
894 state->ret = result->ret;
895 state->err = result->err;
896 tevent_req_defer_callback(req, ev);
897 tevent_req_done(req);
901 static ssize_t vfswrap_asys_ssize_t_recv(struct tevent_req *req, int *err)
903 struct vfswrap_asys_state *state = tevent_req_data(
904 req, struct vfswrap_asys_state);
906 if (tevent_req_is_unix_error(req, err)) {
913 static int vfswrap_asys_int_recv(struct tevent_req *req, int *err)
915 struct vfswrap_asys_state *state = tevent_req_data(
916 req, struct vfswrap_asys_state);
918 if (tevent_req_is_unix_error(req, err)) {
925 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
929 START_PROFILE(syscall_lseek);
931 /* Cope with 'stat' file opens. */
932 if (fsp->fh->fd != -1)
933 result = lseek(fsp->fh->fd, offset, whence);
936 * We want to maintain the fiction that we can seek
937 * on a fifo for file system purposes. This allows
938 * people to set up UNIX fifo's that feed data to Windows
942 if((result == -1) && (errno == ESPIPE)) {
947 END_PROFILE(syscall_lseek);
951 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
952 off_t offset, size_t n)
956 START_PROFILE_BYTES(syscall_sendfile, n);
957 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
958 END_PROFILE_BYTES(syscall_sendfile);
962 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
970 START_PROFILE_BYTES(syscall_recvfile, n);
971 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
972 END_PROFILE_BYTES(syscall_recvfile);
976 static int vfswrap_rename(vfs_handle_struct *handle,
977 const struct smb_filename *smb_fname_src,
978 const struct smb_filename *smb_fname_dst)
982 START_PROFILE(syscall_rename);
984 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
989 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
992 END_PROFILE(syscall_rename);
996 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
1001 START_PROFILE(syscall_fsync);
1002 result = fsync(fsp->fh->fd);
1003 END_PROFILE(syscall_fsync);
1010 static int vfswrap_stat(vfs_handle_struct *handle,
1011 struct smb_filename *smb_fname)
1015 START_PROFILE(syscall_stat);
1017 if (smb_fname->stream_name) {
1022 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1023 lp_fake_directory_create_times(SNUM(handle->conn)));
1025 END_PROFILE(syscall_stat);
1029 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1033 START_PROFILE(syscall_fstat);
1034 result = sys_fstat(fsp->fh->fd,
1035 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1036 END_PROFILE(syscall_fstat);
1040 static int vfswrap_lstat(vfs_handle_struct *handle,
1041 struct smb_filename *smb_fname)
1045 START_PROFILE(syscall_lstat);
1047 if (smb_fname->stream_name) {
1052 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1053 lp_fake_directory_create_times(SNUM(handle->conn)));
1055 END_PROFILE(syscall_lstat);
1059 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1061 enum vfs_translate_direction direction,
1062 TALLOC_CTX *mem_ctx,
1065 return NT_STATUS_NONE_MAPPED;
1069 * Implement the default fsctl operation.
1071 static bool vfswrap_logged_ioctl_message = false;
1073 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1074 struct files_struct *fsp,
1077 uint16_t req_flags, /* Needed for UNICODE ... */
1078 const uint8_t *_in_data,
1080 uint8_t **_out_data,
1081 uint32_t max_out_len,
1084 const char *in_data = (const char *)_in_data;
1085 char **out_data = (char **)_out_data;
1089 case FSCTL_SET_SPARSE:
1091 bool set_sparse = true;
1093 if (in_len >= 1 && in_data[0] == 0) {
1097 status = file_set_sparse(handle->conn, fsp, set_sparse);
1099 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1100 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1101 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1102 nt_errstr(status)));
1107 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1109 unsigned char objid[16];
1110 char *return_data = NULL;
1112 /* This should return the object-id on this file.
1113 * I think I'll make this be the inode+dev. JRA.
1116 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1117 fsp_fnum_dbg(fsp)));
1119 *out_len = MIN(max_out_len, 64);
1121 /* Hmmm, will this cause problems if less data asked for? */
1122 return_data = talloc_array(ctx, char, 64);
1123 if (return_data == NULL) {
1124 return NT_STATUS_NO_MEMORY;
1127 /* For backwards compatibility only store the dev/inode. */
1128 push_file_id_16(return_data, &fsp->file_id);
1129 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1130 push_file_id_16(return_data+32, &fsp->file_id);
1131 memset(return_data+48, 0, 16);
1132 *out_data = return_data;
1133 return NT_STATUS_OK;
1136 case FSCTL_GET_REPARSE_POINT:
1138 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1139 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1140 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1141 return NT_STATUS_NOT_A_REPARSE_POINT;
1144 case FSCTL_SET_REPARSE_POINT:
1146 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1147 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1148 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1149 return NT_STATUS_NOT_A_REPARSE_POINT;
1152 case FSCTL_GET_SHADOW_COPY_DATA:
1155 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1156 * and return their volume names. If max_data_count is 16, then it is just
1157 * asking for the number of volumes and length of the combined names.
1159 * pdata is the data allocated by our caller, but that uses
1160 * total_data_count (which is 0 in our case) rather than max_data_count.
1161 * Allocate the correct amount and return the pointer to let
1162 * it be deallocated when we return.
1164 struct shadow_copy_data *shadow_data = NULL;
1165 bool labels = False;
1166 uint32_t labels_data_count = 0;
1168 char *cur_pdata = NULL;
1170 if (max_out_len < 16) {
1171 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1173 return NT_STATUS_INVALID_PARAMETER;
1176 if (max_out_len > 16) {
1180 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1181 if (shadow_data == NULL) {
1182 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1183 return NT_STATUS_NO_MEMORY;
1187 * Call the VFS routine to actually do the work.
1189 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1192 /* broken module didn't set errno on error */
1193 status = NT_STATUS_UNSUCCESSFUL;
1195 status = map_nt_error_from_unix(errno);
1196 if (NT_STATUS_EQUAL(status,
1197 NT_STATUS_NOT_SUPPORTED)) {
1201 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1202 "connectpath %s, failed - %s.\n",
1203 fsp->conn->connectpath,
1204 nt_errstr(status)));
1205 TALLOC_FREE(shadow_data);
1209 labels_data_count = (shadow_data->num_volumes * 2 *
1210 sizeof(SHADOW_COPY_LABEL)) + 2;
1215 *out_len = 12 + labels_data_count;
1218 if (max_out_len < *out_len) {
1219 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1220 max_out_len, *out_len));
1221 TALLOC_FREE(shadow_data);
1222 return NT_STATUS_BUFFER_TOO_SMALL;
1225 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1226 if (cur_pdata == NULL) {
1227 TALLOC_FREE(shadow_data);
1228 return NT_STATUS_NO_MEMORY;
1231 *out_data = cur_pdata;
1233 /* num_volumes 4 bytes */
1234 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1237 /* num_labels 4 bytes */
1238 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1241 /* needed_data_count 4 bytes */
1242 SIVAL(cur_pdata, 8, labels_data_count);
1246 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1247 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1248 if (labels && shadow_data->labels) {
1249 for (i=0; i<shadow_data->num_volumes; i++) {
1251 status = srvstr_push(cur_pdata, req_flags,
1252 cur_pdata, shadow_data->labels[i],
1253 2 * sizeof(SHADOW_COPY_LABEL),
1254 STR_UNICODE|STR_TERMINATE, &len);
1255 if (!NT_STATUS_IS_OK(status)) {
1256 TALLOC_FREE(*out_data);
1257 TALLOC_FREE(shadow_data);
1260 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1261 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1265 TALLOC_FREE(shadow_data);
1267 return NT_STATUS_OK;
1270 case FSCTL_FIND_FILES_BY_SID:
1272 /* pretend this succeeded -
1274 * we have to send back a list with all files owned by this SID
1276 * but I have to check that --metze
1282 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1283 fsp_fnum_dbg(fsp)));
1286 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1287 return NT_STATUS_INVALID_PARAMETER;
1290 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1292 /* unknown 4 bytes: this is not the length of the sid :-( */
1293 /*unknown = IVAL(pdata,0);*/
1295 if (!sid_parse(_in_data + 4, sid_len, &sid)) {
1296 return NT_STATUS_INVALID_PARAMETER;
1298 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1300 if (!sid_to_uid(&sid, &uid)) {
1301 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1302 sid_string_dbg(&sid),
1303 (unsigned long)sid_len));
1307 /* we can take a look at the find source :-)
1309 * find ./ -uid $uid -name '*' is what we need here
1312 * and send 4bytes len and then NULL terminated unicode strings
1315 * but I don't know how to deal with the paged results
1316 * (maybe we can hang the result anywhere in the fsp struct)
1318 * but I don't know how to deal with the paged results
1319 * (maybe we can hang the result anywhere in the fsp struct)
1321 * we don't send all files at once
1322 * and at the next we should *not* start from the beginning,
1323 * so we have to cache the result
1328 /* this works for now... */
1329 return NT_STATUS_OK;
1332 case FSCTL_QUERY_ALLOCATED_RANGES:
1334 /* FIXME: This is just a dummy reply, telling that all of the
1335 * file is allocated. MKS cp needs that.
1336 * Adding the real allocated ranges via FIEMAP on Linux
1337 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1338 * this FSCTL correct for sparse files.
1340 uint64_t offset, length;
1341 char *out_data_tmp = NULL;
1344 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1346 return NT_STATUS_INVALID_PARAMETER;
1349 if (max_out_len < 16) {
1350 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1352 return NT_STATUS_INVALID_PARAMETER;
1355 offset = BVAL(in_data,0);
1356 length = BVAL(in_data,8);
1358 if (offset + length < offset) {
1359 /* No 64-bit integer wrap. */
1360 return NT_STATUS_INVALID_PARAMETER;
1363 /* Shouldn't this be SMB_VFS_STAT ... ? */
1364 status = vfs_stat_fsp(fsp);
1365 if (!NT_STATUS_IS_OK(status)) {
1370 out_data_tmp = talloc_array(ctx, char, *out_len);
1371 if (out_data_tmp == NULL) {
1372 DEBUG(10, ("unable to allocate memory for response\n"));
1373 return NT_STATUS_NO_MEMORY;
1376 if (offset > fsp->fsp_name->st.st_ex_size ||
1377 fsp->fsp_name->st.st_ex_size == 0 ||
1379 memset(out_data_tmp, 0, *out_len);
1381 uint64_t end = offset + length;
1382 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1383 SBVAL(out_data_tmp, 0, 0);
1384 SBVAL(out_data_tmp, 8, end);
1387 *out_data = out_data_tmp;
1389 return NT_STATUS_OK;
1392 case FSCTL_IS_VOLUME_DIRTY:
1394 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1395 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1397 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1398 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1400 return NT_STATUS_INVALID_PARAMETER;
1405 * Only print once ... unfortunately there could be lots of
1406 * different FSCTLs that are called.
1408 if (!vfswrap_logged_ioctl_message) {
1409 vfswrap_logged_ioctl_message = true;
1410 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1411 __func__, function));
1415 return NT_STATUS_NOT_SUPPORTED;
1418 struct vfs_cc_state {
1423 static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *handle,
1424 TALLOC_CTX *mem_ctx,
1425 struct tevent_context *ev,
1426 struct files_struct *src_fsp,
1428 struct files_struct *dest_fsp,
1432 struct tevent_req *req;
1433 struct vfs_cc_state *vfs_cc_state;
1436 DEBUG(10, ("performing server side copy chunk of length %lu\n",
1437 (unsigned long)num));
1439 req = tevent_req_create(mem_ctx, &vfs_cc_state, struct vfs_cc_state);
1444 vfs_cc_state->buf = talloc_array(vfs_cc_state, uint8_t,
1445 MIN(num, 8*1024*1024));
1446 if (tevent_req_nomem(vfs_cc_state->buf, req)) {
1447 return tevent_req_post(req, ev);
1450 status = vfs_stat_fsp(src_fsp);
1451 if (tevent_req_nterror(req, status)) {
1452 return tevent_req_post(req, ev);
1455 if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
1457 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1458 * If the SourceOffset or SourceOffset + Length extends beyond
1459 * the end of file, the server SHOULD<240> treat this as a
1460 * STATUS_END_OF_FILE error.
1462 * <240> Section 3.3.5.15.6: Windows servers will return
1463 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1465 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1466 return tevent_req_post(req, ev);
1469 /* could use 2.6.33+ sendfile here to do this in kernel */
1470 while (vfs_cc_state->copied < num) {
1472 struct lock_struct lck;
1475 off_t this_num = MIN(talloc_array_length(vfs_cc_state->buf),
1476 num - vfs_cc_state->copied);
1478 if (src_fsp->op == NULL) {
1479 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1480 return tevent_req_post(req, ev);
1482 init_strict_lock_struct(src_fsp,
1483 src_fsp->op->global->open_persistent_id,
1489 if (!SMB_VFS_STRICT_LOCK(src_fsp->conn, src_fsp, &lck)) {
1490 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1491 return tevent_req_post(req, ev);
1494 ret = SMB_VFS_PREAD(src_fsp, vfs_cc_state->buf,
1497 saved_errno = errno;
1500 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1503 errno = saved_errno;
1504 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1505 return tevent_req_post(req, ev);
1507 if (ret != this_num) {
1508 /* zero tolerance for short reads */
1509 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1510 return tevent_req_post(req, ev);
1515 if (dest_fsp->op == NULL) {
1516 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1517 return tevent_req_post(req, ev);
1520 init_strict_lock_struct(dest_fsp,
1521 dest_fsp->op->global->open_persistent_id,
1527 if (!SMB_VFS_STRICT_LOCK(dest_fsp->conn, dest_fsp, &lck)) {
1528 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1529 return tevent_req_post(req, ev);
1532 ret = SMB_VFS_PWRITE(dest_fsp, vfs_cc_state->buf,
1533 this_num, dest_off);
1535 saved_errno = errno;
1538 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1541 errno = saved_errno;
1542 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1543 return tevent_req_post(req, ev);
1545 if (ret != this_num) {
1546 /* zero tolerance for short writes */
1547 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1548 return tevent_req_post(req, ev);
1552 vfs_cc_state->copied += this_num;
1555 tevent_req_done(req);
1556 return tevent_req_post(req, ev);
1559 static NTSTATUS vfswrap_copy_chunk_recv(struct vfs_handle_struct *handle,
1560 struct tevent_req *req,
1563 struct vfs_cc_state *vfs_cc_state = tevent_req_data(req,
1564 struct vfs_cc_state);
1567 if (tevent_req_is_nterror(req, &status)) {
1568 DEBUG(2, ("server side copy chunk failed: %s\n",
1569 nt_errstr(status)));
1571 tevent_req_received(req);
1575 *copied = vfs_cc_state->copied;
1576 DEBUG(10, ("server side copy chunk copied %lu\n",
1577 (unsigned long)*copied));
1578 tevent_req_received(req);
1580 return NT_STATUS_OK;
1583 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1584 TALLOC_CTX *mem_ctx,
1585 struct files_struct *fsp,
1586 struct smb_filename *smb_fname,
1587 uint16_t *_compression_fmt)
1589 return NT_STATUS_INVALID_DEVICE_REQUEST;
1592 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1593 TALLOC_CTX *mem_ctx,
1594 struct files_struct *fsp,
1595 uint16_t compression_fmt)
1597 return NT_STATUS_INVALID_DEVICE_REQUEST;
1600 /********************************************************************
1601 Given a stat buffer return the allocated size on disk, taking into
1602 account sparse files.
1603 ********************************************************************/
1604 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1605 struct files_struct *fsp,
1606 const SMB_STRUCT_STAT *sbuf)
1610 START_PROFILE(syscall_get_alloc_size);
1612 if(S_ISDIR(sbuf->st_ex_mode)) {
1617 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1618 /* The type of st_blocksize is blkcnt_t which *MUST* be
1619 signed (according to POSIX) and can be less than 64-bits.
1620 Ensure when we're converting to 64 bits wide we don't
1622 #if defined(SIZEOF_BLKCNT_T_8)
1623 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1624 #elif defined(SIZEOF_BLKCNT_T_4)
1626 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1627 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1630 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1634 * Some file systems do not allocate a block for very
1635 * small files. But for non-empty file should report a
1639 uint64_t filesize = get_file_size_stat(sbuf);
1641 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
1645 result = get_file_size_stat(sbuf);
1648 if (fsp && fsp->initial_allocation_size)
1649 result = MAX(result,fsp->initial_allocation_size);
1651 result = smb_roundup(handle->conn, result);
1654 END_PROFILE(syscall_get_alloc_size);
1658 static int vfswrap_unlink(vfs_handle_struct *handle,
1659 const struct smb_filename *smb_fname)
1663 START_PROFILE(syscall_unlink);
1665 if (smb_fname->stream_name) {
1669 result = unlink(smb_fname->base_name);
1672 END_PROFILE(syscall_unlink);
1676 static int vfswrap_chmod(vfs_handle_struct *handle, const char *path, mode_t mode)
1680 START_PROFILE(syscall_chmod);
1683 * We need to do this due to the fact that the default POSIX ACL
1684 * chmod modifies the ACL *mask* for the group owner, not the
1685 * group owner bits directly. JRA.
1690 int saved_errno = errno; /* We might get ENOSYS */
1691 if ((result = SMB_VFS_CHMOD_ACL(handle->conn, path, mode)) == 0) {
1692 END_PROFILE(syscall_chmod);
1695 /* Error - return the old errno. */
1696 errno = saved_errno;
1699 result = chmod(path, mode);
1700 END_PROFILE(syscall_chmod);
1704 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
1708 START_PROFILE(syscall_fchmod);
1711 * We need to do this due to the fact that the default POSIX ACL
1712 * chmod modifies the ACL *mask* for the group owner, not the
1713 * group owner bits directly. JRA.
1717 int saved_errno = errno; /* We might get ENOSYS */
1718 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
1719 END_PROFILE(syscall_fchmod);
1722 /* Error - return the old errno. */
1723 errno = saved_errno;
1726 #if defined(HAVE_FCHMOD)
1727 result = fchmod(fsp->fh->fd, mode);
1733 END_PROFILE(syscall_fchmod);
1737 static int vfswrap_chown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1741 START_PROFILE(syscall_chown);
1742 result = chown(path, uid, gid);
1743 END_PROFILE(syscall_chown);
1747 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
1752 START_PROFILE(syscall_fchown);
1753 result = fchown(fsp->fh->fd, uid, gid);
1754 END_PROFILE(syscall_fchown);
1762 static int vfswrap_lchown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1766 START_PROFILE(syscall_lchown);
1767 result = lchown(path, uid, gid);
1768 END_PROFILE(syscall_lchown);
1772 static int vfswrap_chdir(vfs_handle_struct *handle, const char *path)
1776 START_PROFILE(syscall_chdir);
1777 result = chdir(path);
1778 END_PROFILE(syscall_chdir);
1782 static char *vfswrap_getwd(vfs_handle_struct *handle)
1786 START_PROFILE(syscall_getwd);
1787 result = sys_getwd();
1788 END_PROFILE(syscall_getwd);
1792 /*********************************************************************
1793 nsec timestamp resolution call. Convert down to whatever the underlying
1794 system will support.
1795 **********************************************************************/
1797 static int vfswrap_ntimes(vfs_handle_struct *handle,
1798 const struct smb_filename *smb_fname,
1799 struct smb_file_time *ft)
1803 START_PROFILE(syscall_ntimes);
1805 if (smb_fname->stream_name) {
1811 if (null_timespec(ft->atime)) {
1812 ft->atime= smb_fname->st.st_ex_atime;
1815 if (null_timespec(ft->mtime)) {
1816 ft->mtime = smb_fname->st.st_ex_mtime;
1819 if (!null_timespec(ft->create_time)) {
1820 set_create_timespec_ea(handle->conn,
1825 if ((timespec_compare(&ft->atime,
1826 &smb_fname->st.st_ex_atime) == 0) &&
1827 (timespec_compare(&ft->mtime,
1828 &smb_fname->st.st_ex_mtime) == 0)) {
1833 #if defined(HAVE_UTIMENSAT)
1835 struct timespec ts[2];
1838 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
1840 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
1842 if (!((result == -1) && (errno == ENOSYS))) {
1846 #if defined(HAVE_UTIMES)
1848 struct timeval tv[2];
1849 tv[0] = convert_timespec_to_timeval(ft->atime);
1850 tv[1] = convert_timespec_to_timeval(ft->mtime);
1851 result = utimes(smb_fname->base_name, tv);
1853 result = utimes(smb_fname->base_name, NULL);
1855 if (!((result == -1) && (errno == ENOSYS))) {
1859 #if defined(HAVE_UTIME)
1861 struct utimbuf times;
1862 times.actime = convert_timespec_to_time_t(ft->atime);
1863 times.modtime = convert_timespec_to_time_t(ft->mtime);
1864 result = utime(smb_fname->base_name, ×);
1866 result = utime(smb_fname->base_name, NULL);
1868 if (!((result == -1) && (errno == ENOSYS))) {
1876 END_PROFILE(syscall_ntimes);
1880 /*********************************************************************
1881 A version of ftruncate that will write the space on disk if strict
1883 **********************************************************************/
1885 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1887 off_t space_to_write;
1888 uint64_t space_avail;
1889 uint64_t bsize,dfree,dsize;
1892 SMB_STRUCT_STAT *pst;
1894 status = vfs_stat_fsp(fsp);
1895 if (!NT_STATUS_IS_OK(status)) {
1898 pst = &fsp->fsp_name->st;
1901 if (S_ISFIFO(pst->st_ex_mode))
1905 if (pst->st_ex_size == len)
1908 /* Shrink - just ftruncate. */
1909 if (pst->st_ex_size > len)
1910 return ftruncate(fsp->fh->fd, len);
1912 space_to_write = len - pst->st_ex_size;
1914 /* for allocation try fallocate first. This can fail on some
1915 platforms e.g. when the filesystem doesn't support it and no
1916 emulation is being done by the libc (like on AIX with JFS1). In that
1917 case we do our own emulation. fallocate implementations can
1918 return ENOTSUP or EINVAL in cases like that. */
1919 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
1920 if (ret == -1 && errno == ENOSPC) {
1926 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
1927 "error %d. Falling back to slow manual allocation\n", errno));
1929 /* available disk space is enough or not? */
1930 space_avail = get_dfree_info(fsp->conn,
1931 fsp->fsp_name->base_name,
1932 &bsize, &dfree, &dsize);
1933 /* space_avail is 1k blocks */
1934 if (space_avail == (uint64_t)-1 ||
1935 ((uint64_t)space_to_write/1024 > space_avail) ) {
1940 /* Write out the real space on disk. */
1941 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
1949 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1952 SMB_STRUCT_STAT *pst;
1956 START_PROFILE(syscall_ftruncate);
1958 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
1959 result = strict_allocate_ftruncate(handle, fsp, len);
1960 END_PROFILE(syscall_ftruncate);
1964 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
1965 ftruncate if the system supports it. Then I discovered that
1966 you can have some filesystems that support ftruncate
1967 expansion and some that don't! On Linux fat can't do
1968 ftruncate extend but ext2 can. */
1970 result = ftruncate(fsp->fh->fd, len);
1972 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
1973 extend a file with ftruncate. Provide alternate implementation
1976 /* Do an fstat to see if the file is longer than the requested
1977 size in which case the ftruncate above should have
1978 succeeded or shorter, in which case seek to len - 1 and
1979 write 1 byte of zero */
1980 status = vfs_stat_fsp(fsp);
1981 if (!NT_STATUS_IS_OK(status)) {
1985 /* We need to update the files_struct after successful ftruncate */
1990 pst = &fsp->fsp_name->st;
1993 if (S_ISFIFO(pst->st_ex_mode)) {
1999 if (pst->st_ex_size == len) {
2004 if (pst->st_ex_size > len) {
2005 /* the ftruncate should have worked */
2009 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2017 END_PROFILE(syscall_ftruncate);
2021 static int vfswrap_fallocate(vfs_handle_struct *handle,
2029 START_PROFILE(syscall_fallocate);
2031 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2033 * posix_fallocate returns 0 on success, errno on error
2034 * and doesn't set errno. Make it behave like fallocate()
2035 * which returns -1, and sets errno on failure.
2042 /* sys_fallocate handles filtering of unsupported mode flags */
2043 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2045 END_PROFILE(syscall_fallocate);
2049 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2053 START_PROFILE(syscall_fcntl_lock);
2054 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2055 END_PROFILE(syscall_fcntl_lock);
2059 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2060 uint32_t share_mode, uint32_t access_mask)
2062 START_PROFILE(syscall_kernel_flock);
2063 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2064 END_PROFILE(syscall_kernel_flock);
2068 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2072 START_PROFILE(syscall_fcntl_getlock);
2073 result = fcntl_getlock(fsp->fh->fd, poffset, pcount, ptype, ppid);
2074 END_PROFILE(syscall_fcntl_getlock);
2078 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2083 START_PROFILE(syscall_linux_setlease);
2085 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2086 result = linux_setlease(fsp->fh->fd, leasetype);
2090 END_PROFILE(syscall_linux_setlease);
2094 static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2098 START_PROFILE(syscall_symlink);
2099 result = symlink(oldpath, newpath);
2100 END_PROFILE(syscall_symlink);
2104 static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
2108 START_PROFILE(syscall_readlink);
2109 result = readlink(path, buf, bufsiz);
2110 END_PROFILE(syscall_readlink);
2114 static int vfswrap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2118 START_PROFILE(syscall_link);
2119 result = link(oldpath, newpath);
2120 END_PROFILE(syscall_link);
2124 static int vfswrap_mknod(vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev)
2128 START_PROFILE(syscall_mknod);
2129 result = sys_mknod(pathname, mode, dev);
2130 END_PROFILE(syscall_mknod);
2134 static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
2138 START_PROFILE(syscall_realpath);
2139 result = sys_realpath(path);
2140 END_PROFILE(syscall_realpath);
2144 static int vfswrap_chflags(vfs_handle_struct *handle, const char *path,
2148 return chflags(path, flags);
2155 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2156 const SMB_STRUCT_STAT *sbuf)
2160 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2164 key.devid = sbuf->st_ex_dev;
2165 key.inode = sbuf->st_ex_ino;
2166 /* key.extid is unused by default. */
2171 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2172 struct files_struct *fsp,
2174 TALLOC_CTX *mem_ctx,
2175 unsigned int *pnum_streams,
2176 struct stream_struct **pstreams)
2178 SMB_STRUCT_STAT sbuf;
2179 struct stream_struct *tmp_streams = NULL;
2182 if ((fsp != NULL) && (fsp->is_directory)) {
2184 * No default streams on directories
2189 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2190 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2193 struct smb_filename smb_fname;
2195 ZERO_STRUCT(smb_fname);
2196 smb_fname.base_name = discard_const_p(char, fname);
2198 if (lp_posix_pathnames()) {
2199 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname);
2201 ret = SMB_VFS_STAT(handle->conn, &smb_fname);
2203 sbuf = smb_fname.st;
2207 return map_nt_error_from_unix(errno);
2210 if (S_ISDIR(sbuf.st_ex_mode)) {
2214 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2215 (*pnum_streams) + 1);
2216 if (tmp_streams == NULL) {
2217 return NT_STATUS_NO_MEMORY;
2219 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2220 if (tmp_streams[*pnum_streams].name == NULL) {
2221 return NT_STATUS_NO_MEMORY;
2223 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2224 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2227 *pstreams = tmp_streams;
2229 return NT_STATUS_OK;
2232 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2235 TALLOC_CTX *mem_ctx,
2239 * Don't fall back to get_real_filename so callers can differentiate
2240 * between a full directory scan and an actual case-insensitive stat.
2246 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2249 return handle->conn->connectpath;
2252 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2253 struct byte_range_lock *br_lck,
2254 struct lock_struct *plock,
2257 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2259 /* Note: blr is not used in the default implementation. */
2260 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2263 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2264 struct messaging_context *msg_ctx,
2265 struct byte_range_lock *br_lck,
2266 const struct lock_struct *plock)
2268 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2270 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2273 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2274 struct byte_range_lock *br_lck,
2275 struct lock_struct *plock)
2277 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2279 /* Note: blr is not used in the default implementation. */
2280 return brl_lock_cancel_default(br_lck, plock);
2283 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2285 struct lock_struct *plock)
2287 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2288 plock->lock_type == WRITE_LOCK);
2290 return strict_lock_default(fsp, plock);
2293 static void vfswrap_strict_unlock(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 strict_unlock_default(fsp, plock);
2303 /* NT ACL operations. */
2305 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2307 uint32_t security_info,
2308 TALLOC_CTX *mem_ctx,
2309 struct security_descriptor **ppdesc)
2313 START_PROFILE(fget_nt_acl);
2314 result = posix_fget_nt_acl(fsp, security_info,
2316 END_PROFILE(fget_nt_acl);
2320 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2321 const struct smb_filename *smb_fname,
2322 uint32_t security_info,
2323 TALLOC_CTX *mem_ctx,
2324 struct security_descriptor **ppdesc)
2328 START_PROFILE(get_nt_acl);
2329 result = posix_get_nt_acl(handle->conn,
2330 smb_fname->base_name,
2334 END_PROFILE(get_nt_acl);
2338 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2342 START_PROFILE(fset_nt_acl);
2343 result = set_nt_acl(fsp, security_info_sent, psd);
2344 END_PROFILE(fset_nt_acl);
2348 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2349 struct smb_filename *file,
2350 struct security_acl *sacl,
2351 uint32_t access_requested,
2352 uint32_t access_denied)
2354 return NT_STATUS_OK; /* Nothing to do here ... */
2357 static int vfswrap_chmod_acl(vfs_handle_struct *handle, const char *name, mode_t mode)
2365 START_PROFILE(chmod_acl);
2366 result = chmod_acl(handle->conn, name, mode);
2367 END_PROFILE(chmod_acl);
2372 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2380 START_PROFILE(fchmod_acl);
2381 result = fchmod_acl(fsp, mode);
2382 END_PROFILE(fchmod_acl);
2387 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2389 SMB_ACL_TYPE_T type,
2390 TALLOC_CTX *mem_ctx)
2392 return sys_acl_get_file(handle, path_p, type, mem_ctx);
2395 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2397 TALLOC_CTX *mem_ctx)
2399 return sys_acl_get_fd(handle, fsp, mem_ctx);
2402 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2404 return sys_acl_set_file(handle, name, acltype, theacl);
2407 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2409 return sys_acl_set_fd(handle, fsp, theacl);
2412 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
2414 return sys_acl_delete_def_file(handle, path);
2417 /****************************************************************
2418 Extended attribute operations.
2419 *****************************************************************/
2421 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
2423 return getxattr(path, name, value, size);
2426 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2428 return fgetxattr(fsp->fh->fd, name, value, size);
2431 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
2433 return listxattr(path, list, size);
2436 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2438 return flistxattr(fsp->fh->fd, list, size);
2441 static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
2443 return removexattr(path, name);
2446 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2448 return fremovexattr(fsp->fh->fd, name);
2451 static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
2453 return setxattr(path, name, value, size, flags);
2456 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2458 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2461 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2466 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2467 const struct smb_filename *fname,
2468 SMB_STRUCT_STAT *sbuf)
2472 bool offline = false;
2474 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2478 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2479 #if defined(ENOTSUP)
2485 status = get_full_smb_filename(talloc_tos(), fname, &path);
2486 if (!NT_STATUS_IS_OK(status)) {
2487 errno = map_errno_from_nt_status(status);
2491 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2498 static int vfswrap_set_offline(struct vfs_handle_struct *handle,
2499 const struct smb_filename *fname)
2501 /* We don't know how to set offline bit by default, needs to be overriden in the vfs modules */
2502 #if defined(ENOTSUP)
2508 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2509 struct files_struct *fsp,
2510 TALLOC_CTX *mem_ctx,
2513 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2516 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2517 struct files_struct *fsp,
2518 const DATA_BLOB old_cookie,
2519 TALLOC_CTX *mem_ctx,
2520 DATA_BLOB *new_cookie)
2522 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2526 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2527 struct smb_request *smb1req,
2528 struct smbXsrv_open *op,
2529 const DATA_BLOB old_cookie,
2530 TALLOC_CTX *mem_ctx,
2531 struct files_struct **fsp,
2532 DATA_BLOB *new_cookie)
2534 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2535 old_cookie, mem_ctx,
2539 static struct vfs_fn_pointers vfs_default_fns = {
2540 /* Disk operations */
2542 .connect_fn = vfswrap_connect,
2543 .disconnect_fn = vfswrap_disconnect,
2544 .disk_free_fn = vfswrap_disk_free,
2545 .get_quota_fn = vfswrap_get_quota,
2546 .set_quota_fn = vfswrap_set_quota,
2547 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2548 .statvfs_fn = vfswrap_statvfs,
2549 .fs_capabilities_fn = vfswrap_fs_capabilities,
2550 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2551 .snap_check_path_fn = vfswrap_snap_check_path,
2552 .snap_create_fn = vfswrap_snap_create,
2553 .snap_delete_fn = vfswrap_snap_delete,
2555 /* Directory operations */
2557 .opendir_fn = vfswrap_opendir,
2558 .fdopendir_fn = vfswrap_fdopendir,
2559 .readdir_fn = vfswrap_readdir,
2560 .readdir_attr_fn = vfswrap_readdir_attr,
2561 .seekdir_fn = vfswrap_seekdir,
2562 .telldir_fn = vfswrap_telldir,
2563 .rewind_dir_fn = vfswrap_rewinddir,
2564 .mkdir_fn = vfswrap_mkdir,
2565 .rmdir_fn = vfswrap_rmdir,
2566 .closedir_fn = vfswrap_closedir,
2567 .init_search_op_fn = vfswrap_init_search_op,
2569 /* File operations */
2571 .open_fn = vfswrap_open,
2572 .create_file_fn = vfswrap_create_file,
2573 .close_fn = vfswrap_close,
2574 .read_fn = vfswrap_read,
2575 .pread_fn = vfswrap_pread,
2576 .pread_send_fn = vfswrap_pread_send,
2577 .pread_recv_fn = vfswrap_asys_ssize_t_recv,
2578 .write_fn = vfswrap_write,
2579 .pwrite_fn = vfswrap_pwrite,
2580 .pwrite_send_fn = vfswrap_pwrite_send,
2581 .pwrite_recv_fn = vfswrap_asys_ssize_t_recv,
2582 .lseek_fn = vfswrap_lseek,
2583 .sendfile_fn = vfswrap_sendfile,
2584 .recvfile_fn = vfswrap_recvfile,
2585 .rename_fn = vfswrap_rename,
2586 .fsync_fn = vfswrap_fsync,
2587 .fsync_send_fn = vfswrap_fsync_send,
2588 .fsync_recv_fn = vfswrap_asys_int_recv,
2589 .stat_fn = vfswrap_stat,
2590 .fstat_fn = vfswrap_fstat,
2591 .lstat_fn = vfswrap_lstat,
2592 .get_alloc_size_fn = vfswrap_get_alloc_size,
2593 .unlink_fn = vfswrap_unlink,
2594 .chmod_fn = vfswrap_chmod,
2595 .fchmod_fn = vfswrap_fchmod,
2596 .chown_fn = vfswrap_chown,
2597 .fchown_fn = vfswrap_fchown,
2598 .lchown_fn = vfswrap_lchown,
2599 .chdir_fn = vfswrap_chdir,
2600 .getwd_fn = vfswrap_getwd,
2601 .ntimes_fn = vfswrap_ntimes,
2602 .ftruncate_fn = vfswrap_ftruncate,
2603 .fallocate_fn = vfswrap_fallocate,
2604 .lock_fn = vfswrap_lock,
2605 .kernel_flock_fn = vfswrap_kernel_flock,
2606 .linux_setlease_fn = vfswrap_linux_setlease,
2607 .getlock_fn = vfswrap_getlock,
2608 .symlink_fn = vfswrap_symlink,
2609 .readlink_fn = vfswrap_readlink,
2610 .link_fn = vfswrap_link,
2611 .mknod_fn = vfswrap_mknod,
2612 .realpath_fn = vfswrap_realpath,
2613 .chflags_fn = vfswrap_chflags,
2614 .file_id_create_fn = vfswrap_file_id_create,
2615 .streaminfo_fn = vfswrap_streaminfo,
2616 .get_real_filename_fn = vfswrap_get_real_filename,
2617 .connectpath_fn = vfswrap_connectpath,
2618 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2619 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2620 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2621 .strict_lock_fn = vfswrap_strict_lock,
2622 .strict_unlock_fn = vfswrap_strict_unlock,
2623 .translate_name_fn = vfswrap_translate_name,
2624 .fsctl_fn = vfswrap_fsctl,
2625 .copy_chunk_send_fn = vfswrap_copy_chunk_send,
2626 .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
2627 .get_compression_fn = vfswrap_get_compression,
2628 .set_compression_fn = vfswrap_set_compression,
2630 /* NT ACL operations. */
2632 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2633 .get_nt_acl_fn = vfswrap_get_nt_acl,
2634 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2635 .audit_file_fn = vfswrap_audit_file,
2637 /* POSIX ACL operations. */
2639 .chmod_acl_fn = vfswrap_chmod_acl,
2640 .fchmod_acl_fn = vfswrap_fchmod_acl,
2642 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2643 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2644 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2645 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2646 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2647 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2648 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2650 /* EA operations. */
2651 .getxattr_fn = vfswrap_getxattr,
2652 .fgetxattr_fn = vfswrap_fgetxattr,
2653 .listxattr_fn = vfswrap_listxattr,
2654 .flistxattr_fn = vfswrap_flistxattr,
2655 .removexattr_fn = vfswrap_removexattr,
2656 .fremovexattr_fn = vfswrap_fremovexattr,
2657 .setxattr_fn = vfswrap_setxattr,
2658 .fsetxattr_fn = vfswrap_fsetxattr,
2660 /* aio operations */
2661 .aio_force_fn = vfswrap_aio_force,
2663 /* offline operations */
2664 .is_offline_fn = vfswrap_is_offline,
2665 .set_offline_fn = vfswrap_set_offline,
2667 /* durable handle operations */
2668 .durable_cookie_fn = vfswrap_durable_cookie,
2669 .durable_disconnect_fn = vfswrap_durable_disconnect,
2670 .durable_reconnect_fn = vfswrap_durable_reconnect,
2673 NTSTATUS vfs_default_init(void);
2674 NTSTATUS vfs_default_init(void)
2676 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
2677 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);