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/util/tevent_ntstatus.h"
34 #include "lib/util/sys_rw.h"
35 #include "lib/pthreadpool/pthreadpool_tevent.h"
36 #include "librpc/gen_ndr/ndr_ioctl.h"
37 #include "offload_token.h"
40 #define DBGC_CLASS DBGC_VFS
42 /* Check for NULL pointer parameters in vfswrap_* functions */
44 /* We don't want to have NULL function pointers lying around. Someone
45 is sure to try and execute them. These stubs are used to prevent
48 static int vfswrap_connect(vfs_handle_struct *handle, const char *service, const char *user)
50 return 0; /* Return >= 0 for success */
53 static void vfswrap_disconnect(vfs_handle_struct *handle)
59 static uint64_t vfswrap_disk_free(vfs_handle_struct *handle,
60 const struct smb_filename *smb_fname,
65 if (sys_fsusage(smb_fname->base_name, dfree, dsize) != 0) {
73 static int vfswrap_get_quota(struct vfs_handle_struct *handle,
74 const struct smb_filename *smb_fname,
75 enum SMB_QUOTA_TYPE qtype,
79 #ifdef HAVE_SYS_QUOTAS
82 START_PROFILE(syscall_get_quota);
83 result = sys_get_quota(smb_fname->base_name, qtype, id, qt);
84 END_PROFILE(syscall_get_quota);
92 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
94 #ifdef HAVE_SYS_QUOTAS
97 START_PROFILE(syscall_set_quota);
98 result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
99 END_PROFILE(syscall_set_quota);
107 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
108 struct files_struct *fsp,
109 struct shadow_copy_data *shadow_copy_data,
113 return -1; /* Not implemented. */
116 static int vfswrap_statvfs(struct vfs_handle_struct *handle,
117 const struct smb_filename *smb_fname,
118 vfs_statvfs_struct *statbuf)
120 return sys_statvfs(smb_fname->base_name, statbuf);
123 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
124 enum timestamp_set_resolution *p_ts_res)
126 connection_struct *conn = handle->conn;
127 uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
128 struct smb_filename *smb_fname_cpath = NULL;
129 struct vfs_statvfs_struct statbuf;
132 smb_fname_cpath = synthetic_smb_fname(talloc_tos(), conn->connectpath,
134 if (smb_fname_cpath == NULL) {
138 ZERO_STRUCT(statbuf);
139 ret = SMB_VFS_STATVFS(conn, smb_fname_cpath, &statbuf);
141 caps = statbuf.FsCapabilities;
144 *p_ts_res = TIMESTAMP_SET_SECONDS;
146 /* Work out what timestamp resolution we can
147 * use when setting a timestamp. */
149 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
151 TALLOC_FREE(smb_fname_cpath);
155 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
156 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
157 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
158 /* If any of the normal UNIX directory timestamps
159 * have a non-zero tv_nsec component assume
160 * we might be able to set sub-second timestamps.
161 * See what filetime set primitives we have.
163 #if defined(HAVE_UTIMENSAT)
164 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
165 #elif defined(HAVE_UTIMES)
166 /* utimes allows msec timestamps to be set. */
167 *p_ts_res = TIMESTAMP_SET_MSEC;
168 #elif defined(HAVE_UTIME)
169 /* utime only allows sec timestamps to be set. */
170 *p_ts_res = TIMESTAMP_SET_SECONDS;
173 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
175 "available on share %s, directory %s\n",
176 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
177 lp_servicename(talloc_tos(), conn->params->service),
178 conn->connectpath ));
180 TALLOC_FREE(smb_fname_cpath);
184 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
185 struct dfs_GetDFSReferral *r)
187 struct junction_map *junction = NULL;
189 bool self_referral = false;
190 char *pathnamep = NULL;
191 char *local_dfs_path = NULL;
194 uint16_t max_referral_level = r->in.req.max_referral_level;
197 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
200 /* get the junction entry */
201 if (r->in.req.servername == NULL) {
202 return NT_STATUS_NOT_FOUND;
206 * Trim pathname sent by client so it begins with only one backslash.
207 * Two backslashes confuse some dfs clients
210 local_dfs_path = talloc_strdup(r, r->in.req.servername);
211 if (local_dfs_path == NULL) {
212 return NT_STATUS_NO_MEMORY;
214 pathnamep = local_dfs_path;
215 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
216 IS_DIRECTORY_SEP(pathnamep[1])) {
220 junction = talloc_zero(r, struct junction_map);
221 if (junction == NULL) {
222 return NT_STATUS_NO_MEMORY;
225 /* The following call can change cwd. */
226 status = get_referred_path(r, pathnamep,
227 handle->conn->sconn->remote_address,
228 handle->conn->sconn->local_address,
229 !handle->conn->sconn->using_smb2,
230 junction, &consumedcnt, &self_referral);
231 if (!NT_STATUS_IS_OK(status)) {
232 struct smb_filename connectpath_fname = {
233 .base_name = handle->conn->connectpath
235 vfs_ChDir(handle->conn, &connectpath_fname);
239 struct smb_filename connectpath_fname = {
240 .base_name = handle->conn->connectpath
242 vfs_ChDir(handle->conn, &connectpath_fname);
245 if (!self_referral) {
246 pathnamep[consumedcnt] = '\0';
249 dbgtext("Path %s to alternate path(s):",
251 for (i=0; i < junction->referral_count; i++) {
253 junction->referral_list[i].alternate_path);
259 if (r->in.req.max_referral_level <= 2) {
260 max_referral_level = 2;
262 if (r->in.req.max_referral_level >= 3) {
263 max_referral_level = 3;
266 r->out.resp = talloc_zero(r, struct dfs_referral_resp);
267 if (r->out.resp == NULL) {
268 return NT_STATUS_NO_MEMORY;
271 r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
272 r->out.resp->nb_referrals = junction->referral_count;
274 r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
276 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
279 r->out.resp->referral_entries = talloc_zero_array(r,
280 struct dfs_referral_type,
281 r->out.resp->nb_referrals);
282 if (r->out.resp->referral_entries == NULL) {
283 return NT_STATUS_NO_MEMORY;
286 switch (max_referral_level) {
288 for(i=0; i < junction->referral_count; i++) {
289 struct referral *ref = &junction->referral_list[i];
290 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
291 struct dfs_referral_type *t =
292 &r->out.resp->referral_entries[i];
293 struct dfs_referral_v2 *v2 = &t->referral.v2;
296 v2->size = VERSION2_REFERRAL_SIZE;
298 v2->server_type = DFS_SERVER_ROOT;
300 v2->server_type = DFS_SERVER_NON_ROOT;
303 v2->proximity = ref->proximity;
305 v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
306 if (v2->DFS_path == NULL) {
307 return NT_STATUS_NO_MEMORY;
309 v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
310 if (v2->DFS_alt_path == NULL) {
311 return NT_STATUS_NO_MEMORY;
313 v2->netw_address = talloc_strdup(mem_ctx,
314 ref->alternate_path);
315 if (v2->netw_address == NULL) {
316 return NT_STATUS_NO_MEMORY;
322 for(i=0; i < junction->referral_count; i++) {
323 struct referral *ref = &junction->referral_list[i];
324 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
325 struct dfs_referral_type *t =
326 &r->out.resp->referral_entries[i];
327 struct dfs_referral_v3 *v3 = &t->referral.v3;
328 struct dfs_normal_referral *r1 = &v3->referrals.r1;
331 v3->size = VERSION3_REFERRAL_SIZE;
333 v3->server_type = DFS_SERVER_ROOT;
335 v3->server_type = DFS_SERVER_NON_ROOT;
339 r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
340 if (r1->DFS_path == NULL) {
341 return NT_STATUS_NO_MEMORY;
343 r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
344 if (r1->DFS_alt_path == NULL) {
345 return NT_STATUS_NO_MEMORY;
347 r1->netw_address = talloc_strdup(mem_ctx,
348 ref->alternate_path);
349 if (r1->netw_address == NULL) {
350 return NT_STATUS_NO_MEMORY;
355 DEBUG(0,("Invalid dfs referral version: %d\n",
356 max_referral_level));
357 return NT_STATUS_INVALID_LEVEL;
361 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
367 static NTSTATUS vfswrap_snap_check_path(struct vfs_handle_struct *handle,
369 const char *service_path,
372 return NT_STATUS_NOT_SUPPORTED;
375 static NTSTATUS vfswrap_snap_create(struct vfs_handle_struct *handle,
377 const char *base_volume,
383 return NT_STATUS_NOT_SUPPORTED;
386 static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle,
391 return NT_STATUS_NOT_SUPPORTED;
394 /* Directory operations */
396 static DIR *vfswrap_opendir(vfs_handle_struct *handle,
397 const struct smb_filename *smb_fname,
403 START_PROFILE(syscall_opendir);
404 result = opendir(smb_fname->base_name);
405 END_PROFILE(syscall_opendir);
409 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
416 START_PROFILE(syscall_fdopendir);
417 result = sys_fdopendir(fsp->fh->fd);
418 END_PROFILE(syscall_fdopendir);
423 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
425 SMB_STRUCT_STAT *sbuf)
427 struct dirent *result;
429 START_PROFILE(syscall_readdir);
430 result = readdir(dirp);
431 END_PROFILE(syscall_readdir);
433 /* Default Posix readdir() does not give us stat info.
434 * Set to invalid to indicate we didn't return this info. */
435 SET_STAT_INVALID(*sbuf);
436 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
437 if (result != NULL) {
438 /* See if we can efficiently return this. */
440 int flags = AT_SYMLINK_NOFOLLOW;
441 int ret = fstatat(dirfd(dirp),
446 * As this is an optimization,
447 * ignore it if we stat'ed a
448 * symlink. Make the caller
449 * do it again as we don't
450 * know if they wanted the link
451 * info, or its target info.
453 if ((ret == 0) && (!S_ISLNK(st.st_mode))) {
454 init_stat_ex_from_stat(sbuf,
456 lp_fake_directory_create_times(
457 SNUM(handle->conn)));
465 static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
466 const struct smb_filename *fname,
468 struct readdir_attr_data **attr_data)
470 return NT_STATUS_NOT_SUPPORTED;
473 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
475 START_PROFILE(syscall_seekdir);
476 seekdir(dirp, offset);
477 END_PROFILE(syscall_seekdir);
480 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
483 START_PROFILE(syscall_telldir);
484 result = telldir(dirp);
485 END_PROFILE(syscall_telldir);
489 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
491 START_PROFILE(syscall_rewinddir);
493 END_PROFILE(syscall_rewinddir);
496 static int vfswrap_mkdir(vfs_handle_struct *handle,
497 const struct smb_filename *smb_fname,
501 const char *path = smb_fname->base_name;
504 START_PROFILE(syscall_mkdir);
506 if (lp_inherit_acls(SNUM(handle->conn))
507 && parent_dirname(talloc_tos(), path, &parent, NULL)
508 && directory_has_default_acl(handle->conn, parent)) {
509 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
514 result = mkdir(path, mode);
516 END_PROFILE(syscall_mkdir);
520 static int vfswrap_rmdir(vfs_handle_struct *handle,
521 const struct smb_filename *smb_fname)
525 START_PROFILE(syscall_rmdir);
526 result = rmdir(smb_fname->base_name);
527 END_PROFILE(syscall_rmdir);
531 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
535 START_PROFILE(syscall_closedir);
536 result = closedir(dirp);
537 END_PROFILE(syscall_closedir);
541 /* File operations */
543 static int vfswrap_open(vfs_handle_struct *handle,
544 struct smb_filename *smb_fname,
545 files_struct *fsp, int flags, mode_t mode)
549 START_PROFILE(syscall_open);
551 if (smb_fname->stream_name) {
556 result = open(smb_fname->base_name, flags, mode);
558 END_PROFILE(syscall_open);
562 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
563 struct smb_request *req,
564 uint16_t root_dir_fid,
565 struct smb_filename *smb_fname,
566 uint32_t access_mask,
567 uint32_t share_access,
568 uint32_t create_disposition,
569 uint32_t create_options,
570 uint32_t file_attributes,
571 uint32_t oplock_request,
572 struct smb2_lease *lease,
573 uint64_t allocation_size,
574 uint32_t private_flags,
575 struct security_descriptor *sd,
576 struct ea_list *ea_list,
577 files_struct **result,
579 const struct smb2_create_blobs *in_context_blobs,
580 struct smb2_create_blobs *out_context_blobs)
582 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
583 access_mask, share_access,
584 create_disposition, create_options,
585 file_attributes, oplock_request, lease,
586 allocation_size, private_flags,
588 pinfo, in_context_blobs, out_context_blobs);
591 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
595 START_PROFILE(syscall_close);
596 result = fd_close_posix(fsp);
597 END_PROFILE(syscall_close);
601 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
602 size_t n, off_t offset)
606 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
607 START_PROFILE_BYTES(syscall_pread, n);
608 result = sys_pread(fsp->fh->fd, data, n, offset);
609 END_PROFILE_BYTES(syscall_pread);
611 if (result == -1 && errno == ESPIPE) {
612 /* Maintain the fiction that pipes can be seeked (sought?) on. */
613 result = sys_read(fsp->fh->fd, data, n);
617 #else /* HAVE_PREAD */
620 #endif /* HAVE_PREAD */
625 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
626 size_t n, off_t offset)
630 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
631 START_PROFILE_BYTES(syscall_pwrite, n);
632 result = sys_pwrite(fsp->fh->fd, data, n, offset);
633 END_PROFILE_BYTES(syscall_pwrite);
635 if (result == -1 && errno == ESPIPE) {
636 /* Maintain the fiction that pipes can be sought on. */
637 result = sys_write(fsp->fh->fd, data, n);
640 #else /* HAVE_PWRITE */
643 #endif /* HAVE_PWRITE */
648 struct vfswrap_pread_state {
655 struct vfs_aio_state vfs_aio_state;
656 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
659 static void vfs_pread_do(void *private_data);
660 static void vfs_pread_done(struct tevent_req *subreq);
661 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state);
663 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
665 struct tevent_context *ev,
666 struct files_struct *fsp,
668 size_t n, off_t offset)
670 struct tevent_req *req, *subreq;
671 struct vfswrap_pread_state *state;
673 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
679 state->fd = fsp->fh->fd;
682 state->offset = offset;
684 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
685 state->profile_bytes, n);
686 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
688 subreq = pthreadpool_tevent_job_send(
689 state, ev, handle->conn->sconn->pool,
690 vfs_pread_do, state);
691 if (tevent_req_nomem(subreq, req)) {
692 return tevent_req_post(req, ev);
694 tevent_req_set_callback(subreq, vfs_pread_done, req);
696 talloc_set_destructor(state, vfs_pread_state_destructor);
701 static void vfs_pread_do(void *private_data)
703 struct vfswrap_pread_state *state = talloc_get_type_abort(
704 private_data, struct vfswrap_pread_state);
705 struct timespec start_time;
706 struct timespec end_time;
708 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
710 PROFILE_TIMESTAMP(&start_time);
713 state->ret = pread(state->fd, state->buf, state->count,
715 } while ((state->ret == -1) && (errno == EINTR));
717 if (state->ret == -1) {
718 state->vfs_aio_state.error = errno;
721 PROFILE_TIMESTAMP(&end_time);
723 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
725 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
728 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state)
733 static void vfs_pread_done(struct tevent_req *subreq)
735 struct tevent_req *req = tevent_req_callback_data(
736 subreq, struct tevent_req);
737 struct vfswrap_pread_state *state = tevent_req_data(
738 req, struct vfswrap_pread_state);
741 ret = pthreadpool_tevent_job_recv(subreq);
743 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
744 talloc_set_destructor(state, NULL);
745 if (tevent_req_error(req, ret)) {
749 tevent_req_done(req);
752 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
753 struct vfs_aio_state *vfs_aio_state)
755 struct vfswrap_pread_state *state = tevent_req_data(
756 req, struct vfswrap_pread_state);
758 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
762 *vfs_aio_state = state->vfs_aio_state;
766 struct vfswrap_pwrite_state {
773 struct vfs_aio_state vfs_aio_state;
774 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
777 static void vfs_pwrite_do(void *private_data);
778 static void vfs_pwrite_done(struct tevent_req *subreq);
779 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state);
781 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
783 struct tevent_context *ev,
784 struct files_struct *fsp,
786 size_t n, off_t offset)
788 struct tevent_req *req, *subreq;
789 struct vfswrap_pwrite_state *state;
791 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
797 state->fd = fsp->fh->fd;
800 state->offset = offset;
802 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
803 state->profile_bytes, n);
804 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
806 subreq = pthreadpool_tevent_job_send(
807 state, ev, handle->conn->sconn->pool,
808 vfs_pwrite_do, state);
809 if (tevent_req_nomem(subreq, req)) {
810 return tevent_req_post(req, ev);
812 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
814 talloc_set_destructor(state, vfs_pwrite_state_destructor);
819 static void vfs_pwrite_do(void *private_data)
821 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
822 private_data, struct vfswrap_pwrite_state);
823 struct timespec start_time;
824 struct timespec end_time;
826 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
828 PROFILE_TIMESTAMP(&start_time);
831 state->ret = pwrite(state->fd, state->buf, state->count,
833 } while ((state->ret == -1) && (errno == EINTR));
835 if (state->ret == -1) {
836 state->vfs_aio_state.error = errno;
839 PROFILE_TIMESTAMP(&end_time);
841 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
843 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
846 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state)
851 static void vfs_pwrite_done(struct tevent_req *subreq)
853 struct tevent_req *req = tevent_req_callback_data(
854 subreq, struct tevent_req);
855 struct vfswrap_pwrite_state *state = tevent_req_data(
856 req, struct vfswrap_pwrite_state);
859 ret = pthreadpool_tevent_job_recv(subreq);
861 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
862 talloc_set_destructor(state, NULL);
863 if (tevent_req_error(req, ret)) {
867 tevent_req_done(req);
870 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
871 struct vfs_aio_state *vfs_aio_state)
873 struct vfswrap_pwrite_state *state = tevent_req_data(
874 req, struct vfswrap_pwrite_state);
876 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
880 *vfs_aio_state = state->vfs_aio_state;
884 struct vfswrap_fsync_state {
888 struct vfs_aio_state vfs_aio_state;
889 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
892 static void vfs_fsync_do(void *private_data);
893 static void vfs_fsync_done(struct tevent_req *subreq);
894 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state);
896 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
898 struct tevent_context *ev,
899 struct files_struct *fsp)
901 struct tevent_req *req, *subreq;
902 struct vfswrap_fsync_state *state;
904 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
910 state->fd = fsp->fh->fd;
912 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_fsync, profile_p,
913 state->profile_bytes, 0);
914 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
916 subreq = pthreadpool_tevent_job_send(
917 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
918 if (tevent_req_nomem(subreq, req)) {
919 return tevent_req_post(req, ev);
921 tevent_req_set_callback(subreq, vfs_fsync_done, req);
923 talloc_set_destructor(state, vfs_fsync_state_destructor);
928 static void vfs_fsync_do(void *private_data)
930 struct vfswrap_fsync_state *state = talloc_get_type_abort(
931 private_data, struct vfswrap_fsync_state);
932 struct timespec start_time;
933 struct timespec end_time;
935 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
937 PROFILE_TIMESTAMP(&start_time);
940 state->ret = fsync(state->fd);
941 } while ((state->ret == -1) && (errno == EINTR));
943 if (state->ret == -1) {
944 state->vfs_aio_state.error = errno;
947 PROFILE_TIMESTAMP(&end_time);
949 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
951 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
954 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state)
959 static void vfs_fsync_done(struct tevent_req *subreq)
961 struct tevent_req *req = tevent_req_callback_data(
962 subreq, struct tevent_req);
963 struct vfswrap_fsync_state *state = tevent_req_data(
964 req, struct vfswrap_fsync_state);
967 ret = pthreadpool_tevent_job_recv(subreq);
969 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
970 talloc_set_destructor(state, NULL);
971 if (tevent_req_error(req, ret)) {
975 tevent_req_done(req);
978 static int vfswrap_fsync_recv(struct tevent_req *req,
979 struct vfs_aio_state *vfs_aio_state)
981 struct vfswrap_fsync_state *state = tevent_req_data(
982 req, struct vfswrap_fsync_state);
984 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
988 *vfs_aio_state = state->vfs_aio_state;
992 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
996 START_PROFILE(syscall_lseek);
998 /* Cope with 'stat' file opens. */
999 if (fsp->fh->fd != -1)
1000 result = lseek(fsp->fh->fd, offset, whence);
1003 * We want to maintain the fiction that we can seek
1004 * on a fifo for file system purposes. This allows
1005 * people to set up UNIX fifo's that feed data to Windows
1006 * applications. JRA.
1009 if((result == -1) && (errno == ESPIPE)) {
1014 END_PROFILE(syscall_lseek);
1018 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1019 off_t offset, size_t n)
1023 START_PROFILE_BYTES(syscall_sendfile, n);
1024 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
1025 END_PROFILE_BYTES(syscall_sendfile);
1029 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1031 files_struct *tofsp,
1037 START_PROFILE_BYTES(syscall_recvfile, n);
1038 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
1039 END_PROFILE_BYTES(syscall_recvfile);
1043 static int vfswrap_rename(vfs_handle_struct *handle,
1044 const struct smb_filename *smb_fname_src,
1045 const struct smb_filename *smb_fname_dst)
1049 START_PROFILE(syscall_rename);
1051 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
1056 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
1059 END_PROFILE(syscall_rename);
1063 static int vfswrap_stat(vfs_handle_struct *handle,
1064 struct smb_filename *smb_fname)
1068 START_PROFILE(syscall_stat);
1070 if (smb_fname->stream_name) {
1075 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1076 lp_fake_directory_create_times(SNUM(handle->conn)));
1078 END_PROFILE(syscall_stat);
1082 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1086 START_PROFILE(syscall_fstat);
1087 result = sys_fstat(fsp->fh->fd,
1088 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1089 END_PROFILE(syscall_fstat);
1093 static int vfswrap_lstat(vfs_handle_struct *handle,
1094 struct smb_filename *smb_fname)
1098 START_PROFILE(syscall_lstat);
1100 if (smb_fname->stream_name) {
1105 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1106 lp_fake_directory_create_times(SNUM(handle->conn)));
1108 END_PROFILE(syscall_lstat);
1112 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1114 enum vfs_translate_direction direction,
1115 TALLOC_CTX *mem_ctx,
1118 return NT_STATUS_NONE_MAPPED;
1122 * Implement the default fsctl operation.
1124 static bool vfswrap_logged_ioctl_message = false;
1126 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1127 struct files_struct *fsp,
1130 uint16_t req_flags, /* Needed for UNICODE ... */
1131 const uint8_t *_in_data,
1133 uint8_t **_out_data,
1134 uint32_t max_out_len,
1137 const char *in_data = (const char *)_in_data;
1138 char **out_data = (char **)_out_data;
1142 case FSCTL_SET_SPARSE:
1144 bool set_sparse = true;
1146 if (in_len >= 1 && in_data[0] == 0) {
1150 status = file_set_sparse(handle->conn, fsp, set_sparse);
1152 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1153 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1154 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1155 nt_errstr(status)));
1160 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1162 unsigned char objid[16];
1163 char *return_data = NULL;
1165 /* This should return the object-id on this file.
1166 * I think I'll make this be the inode+dev. JRA.
1169 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1170 fsp_fnum_dbg(fsp)));
1172 *out_len = MIN(max_out_len, 64);
1174 /* Hmmm, will this cause problems if less data asked for? */
1175 return_data = talloc_array(ctx, char, 64);
1176 if (return_data == NULL) {
1177 return NT_STATUS_NO_MEMORY;
1180 /* For backwards compatibility only store the dev/inode. */
1181 push_file_id_16(return_data, &fsp->file_id);
1182 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1183 push_file_id_16(return_data+32, &fsp->file_id);
1184 memset(return_data+48, 0, 16);
1185 *out_data = return_data;
1186 return NT_STATUS_OK;
1189 case FSCTL_GET_REPARSE_POINT:
1191 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1192 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1193 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1194 return NT_STATUS_NOT_A_REPARSE_POINT;
1197 case FSCTL_SET_REPARSE_POINT:
1199 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1200 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1201 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1202 return NT_STATUS_NOT_A_REPARSE_POINT;
1205 case FSCTL_GET_SHADOW_COPY_DATA:
1208 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1209 * and return their volume names. If max_data_count is 16, then it is just
1210 * asking for the number of volumes and length of the combined names.
1212 * pdata is the data allocated by our caller, but that uses
1213 * total_data_count (which is 0 in our case) rather than max_data_count.
1214 * Allocate the correct amount and return the pointer to let
1215 * it be deallocated when we return.
1217 struct shadow_copy_data *shadow_data = NULL;
1218 bool labels = False;
1219 uint32_t labels_data_count = 0;
1221 char *cur_pdata = NULL;
1223 if (max_out_len < 16) {
1224 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1226 return NT_STATUS_INVALID_PARAMETER;
1229 if (max_out_len > 16) {
1233 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1234 if (shadow_data == NULL) {
1235 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1236 return NT_STATUS_NO_MEMORY;
1240 * Call the VFS routine to actually do the work.
1242 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1245 /* broken module didn't set errno on error */
1246 status = NT_STATUS_UNSUCCESSFUL;
1248 status = map_nt_error_from_unix(errno);
1249 if (NT_STATUS_EQUAL(status,
1250 NT_STATUS_NOT_SUPPORTED)) {
1254 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1255 "connectpath %s, failed - %s.\n",
1256 fsp->conn->connectpath,
1257 nt_errstr(status)));
1258 TALLOC_FREE(shadow_data);
1262 labels_data_count = (shadow_data->num_volumes * 2 *
1263 sizeof(SHADOW_COPY_LABEL)) + 2;
1268 *out_len = 12 + labels_data_count;
1271 if (max_out_len < *out_len) {
1272 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1273 max_out_len, *out_len));
1274 TALLOC_FREE(shadow_data);
1275 return NT_STATUS_BUFFER_TOO_SMALL;
1278 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1279 if (cur_pdata == NULL) {
1280 TALLOC_FREE(shadow_data);
1281 return NT_STATUS_NO_MEMORY;
1284 *out_data = cur_pdata;
1286 /* num_volumes 4 bytes */
1287 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1290 /* num_labels 4 bytes */
1291 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1294 /* needed_data_count 4 bytes */
1295 SIVAL(cur_pdata, 8, labels_data_count);
1299 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1300 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1301 if (labels && shadow_data->labels) {
1302 for (i=0; i<shadow_data->num_volumes; i++) {
1304 status = srvstr_push(cur_pdata, req_flags,
1305 cur_pdata, shadow_data->labels[i],
1306 2 * sizeof(SHADOW_COPY_LABEL),
1307 STR_UNICODE|STR_TERMINATE, &len);
1308 if (!NT_STATUS_IS_OK(status)) {
1309 TALLOC_FREE(*out_data);
1310 TALLOC_FREE(shadow_data);
1313 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1314 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1318 TALLOC_FREE(shadow_data);
1320 return NT_STATUS_OK;
1323 case FSCTL_FIND_FILES_BY_SID:
1325 /* pretend this succeeded -
1327 * we have to send back a list with all files owned by this SID
1329 * but I have to check that --metze
1332 struct dom_sid_buf buf;
1336 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1337 fsp_fnum_dbg(fsp)));
1340 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1341 return NT_STATUS_INVALID_PARAMETER;
1344 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1346 /* unknown 4 bytes: this is not the length of the sid :-( */
1347 /*unknown = IVAL(pdata,0);*/
1349 if (!sid_parse(_in_data + 4, sid_len, &sid)) {
1350 return NT_STATUS_INVALID_PARAMETER;
1352 DEBUGADD(10, ("for SID: %s\n",
1353 dom_sid_str_buf(&sid, &buf)));
1355 if (!sid_to_uid(&sid, &uid)) {
1356 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1357 dom_sid_str_buf(&sid, &buf),
1358 (unsigned long)sid_len));
1362 /* we can take a look at the find source :-)
1364 * find ./ -uid $uid -name '*' is what we need here
1367 * and send 4bytes len and then NULL terminated unicode strings
1370 * but I don't know how to deal with the paged results
1371 * (maybe we can hang the result anywhere in the fsp struct)
1373 * but I don't know how to deal with the paged results
1374 * (maybe we can hang the result anywhere in the fsp struct)
1376 * we don't send all files at once
1377 * and at the next we should *not* start from the beginning,
1378 * so we have to cache the result
1383 /* this works for now... */
1384 return NT_STATUS_OK;
1387 case FSCTL_QUERY_ALLOCATED_RANGES:
1389 /* FIXME: This is just a dummy reply, telling that all of the
1390 * file is allocated. MKS cp needs that.
1391 * Adding the real allocated ranges via FIEMAP on Linux
1392 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1393 * this FSCTL correct for sparse files.
1395 uint64_t offset, length;
1396 char *out_data_tmp = NULL;
1399 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1401 return NT_STATUS_INVALID_PARAMETER;
1404 if (max_out_len < 16) {
1405 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1407 return NT_STATUS_INVALID_PARAMETER;
1410 offset = BVAL(in_data,0);
1411 length = BVAL(in_data,8);
1413 if (offset + length < offset) {
1414 /* No 64-bit integer wrap. */
1415 return NT_STATUS_INVALID_PARAMETER;
1418 /* Shouldn't this be SMB_VFS_STAT ... ? */
1419 status = vfs_stat_fsp(fsp);
1420 if (!NT_STATUS_IS_OK(status)) {
1425 out_data_tmp = talloc_array(ctx, char, *out_len);
1426 if (out_data_tmp == NULL) {
1427 DEBUG(10, ("unable to allocate memory for response\n"));
1428 return NT_STATUS_NO_MEMORY;
1431 if (offset > fsp->fsp_name->st.st_ex_size ||
1432 fsp->fsp_name->st.st_ex_size == 0 ||
1434 memset(out_data_tmp, 0, *out_len);
1436 uint64_t end = offset + length;
1437 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1438 SBVAL(out_data_tmp, 0, 0);
1439 SBVAL(out_data_tmp, 8, end);
1442 *out_data = out_data_tmp;
1444 return NT_STATUS_OK;
1447 case FSCTL_IS_VOLUME_DIRTY:
1449 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1450 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1452 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1453 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1455 return NT_STATUS_INVALID_PARAMETER;
1460 * Only print once ... unfortunately there could be lots of
1461 * different FSCTLs that are called.
1463 if (!vfswrap_logged_ioctl_message) {
1464 vfswrap_logged_ioctl_message = true;
1465 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1466 __func__, function));
1470 return NT_STATUS_NOT_SUPPORTED;
1473 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
1474 const struct smb_filename *fname,
1475 SMB_STRUCT_STAT *sbuf);
1477 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1478 struct smb_filename *smb_fname,
1483 offline = vfswrap_is_offline(handle, smb_fname, &smb_fname->st);
1485 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1488 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1491 struct vfswrap_get_dos_attributes_state {
1492 struct vfs_aio_state aio_state;
1493 connection_struct *conn;
1494 TALLOC_CTX *mem_ctx;
1495 struct tevent_context *ev;
1496 files_struct *dir_fsp;
1497 struct smb_filename *smb_fname;
1502 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq);
1504 static struct tevent_req *vfswrap_get_dos_attributes_send(
1505 TALLOC_CTX *mem_ctx,
1506 struct tevent_context *ev,
1507 struct vfs_handle_struct *handle,
1508 files_struct *dir_fsp,
1509 struct smb_filename *smb_fname)
1511 struct tevent_req *req = NULL;
1512 struct tevent_req *subreq = NULL;
1513 struct vfswrap_get_dos_attributes_state *state = NULL;
1515 req = tevent_req_create(mem_ctx, &state,
1516 struct vfswrap_get_dos_attributes_state);
1521 *state = (struct vfswrap_get_dos_attributes_state) {
1522 .conn = dir_fsp->conn,
1526 .smb_fname = smb_fname,
1529 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1533 SAMBA_XATTR_DOS_ATTRIB,
1535 if (tevent_req_nomem(subreq, req)) {
1536 return tevent_req_post(req, ev);
1538 tevent_req_set_callback(subreq,
1539 vfswrap_get_dos_attributes_getxattr_done,
1545 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq)
1547 struct tevent_req *req =
1548 tevent_req_callback_data(subreq,
1550 struct vfswrap_get_dos_attributes_state *state =
1551 tevent_req_data(req,
1552 struct vfswrap_get_dos_attributes_state);
1554 DATA_BLOB blob = {0};
1557 xattr_size = SMB_VFS_GETXATTRAT_RECV(subreq,
1561 TALLOC_FREE(subreq);
1562 if (xattr_size == -1) {
1563 status = map_nt_error_from_unix(state->aio_state.error);
1565 if (state->as_root) {
1566 tevent_req_nterror(req, status);
1569 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1570 tevent_req_nterror(req, status);
1574 state->as_root = true;
1577 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1581 SAMBA_XATTR_DOS_ATTRIB,
1584 if (tevent_req_nomem(subreq, req)) {
1587 tevent_req_set_callback(subreq,
1588 vfswrap_get_dos_attributes_getxattr_done,
1593 blob.length = xattr_size;
1595 status = parse_dos_attribute_blob(state->smb_fname,
1598 if (!NT_STATUS_IS_OK(status)) {
1599 tevent_req_nterror(req, status);
1603 tevent_req_done(req);
1607 static NTSTATUS vfswrap_get_dos_attributes_recv(struct tevent_req *req,
1608 struct vfs_aio_state *aio_state,
1611 struct vfswrap_get_dos_attributes_state *state =
1612 tevent_req_data(req,
1613 struct vfswrap_get_dos_attributes_state);
1616 if (tevent_req_is_nterror(req, &status)) {
1617 tevent_req_received(req);
1621 *aio_state = state->aio_state;
1622 *dosmode = state->dosmode;
1623 tevent_req_received(req);
1624 return NT_STATUS_OK;
1627 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1628 struct files_struct *fsp,
1633 offline = vfswrap_is_offline(handle, fsp->fsp_name, &fsp->fsp_name->st);
1635 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1638 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1641 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1642 const struct smb_filename *smb_fname,
1645 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1648 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1649 struct files_struct *fsp,
1652 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1655 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1657 struct vfswrap_offload_read_state {
1661 static struct tevent_req *vfswrap_offload_read_send(
1662 TALLOC_CTX *mem_ctx,
1663 struct tevent_context *ev,
1664 struct vfs_handle_struct *handle,
1665 struct files_struct *fsp,
1671 struct tevent_req *req = NULL;
1672 struct vfswrap_offload_read_state *state = NULL;
1675 req = tevent_req_create(mem_ctx, &state,
1676 struct vfswrap_offload_read_state);
1681 status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1682 &vfswrap_offload_ctx);
1683 if (tevent_req_nterror(req, status)) {
1684 return tevent_req_post(req, ev);
1687 if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1688 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1689 return tevent_req_post(req, ev);
1692 status = vfs_offload_token_create_blob(state, fsp, fsctl,
1694 if (tevent_req_nterror(req, status)) {
1695 return tevent_req_post(req, ev);
1698 status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1700 if (tevent_req_nterror(req, status)) {
1701 return tevent_req_post(req, ev);
1704 tevent_req_done(req);
1705 return tevent_req_post(req, ev);
1708 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
1709 struct vfs_handle_struct *handle,
1710 TALLOC_CTX *mem_ctx,
1713 struct vfswrap_offload_read_state *state = tevent_req_data(
1714 req, struct vfswrap_offload_read_state);
1717 if (tevent_req_is_nterror(req, &status)) {
1718 tevent_req_received(req);
1722 token->length = state->token.length;
1723 token->data = talloc_move(mem_ctx, &state->token.data);
1725 tevent_req_received(req);
1726 return NT_STATUS_OK;
1729 struct vfswrap_offload_write_state {
1731 bool read_lck_locked;
1732 bool write_lck_locked;
1734 struct tevent_context *src_ev;
1735 struct files_struct *src_fsp;
1737 struct tevent_context *dst_ev;
1738 struct files_struct *dst_fsp;
1742 size_t next_io_size;
1745 static void vfswrap_offload_write_cleanup(struct tevent_req *req,
1746 enum tevent_req_state req_state)
1748 struct vfswrap_offload_write_state *state = tevent_req_data(
1749 req, struct vfswrap_offload_write_state);
1752 if (state->dst_fsp == NULL) {
1756 ok = change_to_user_by_fsp(state->dst_fsp);
1758 state->dst_fsp = NULL;
1761 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
1763 static struct tevent_req *vfswrap_offload_write_send(
1764 struct vfs_handle_struct *handle,
1765 TALLOC_CTX *mem_ctx,
1766 struct tevent_context *ev,
1769 off_t transfer_offset,
1770 struct files_struct *dest_fsp,
1774 struct tevent_req *req;
1775 struct vfswrap_offload_write_state *state = NULL;
1776 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
1777 files_struct *src_fsp = NULL;
1781 req = tevent_req_create(mem_ctx, &state,
1782 struct vfswrap_offload_write_state);
1787 *state = (struct vfswrap_offload_write_state) {
1789 .src_off = transfer_offset,
1791 .dst_fsp = dest_fsp,
1792 .dst_off = dest_off,
1794 .remaining = to_copy,
1797 tevent_req_set_cleanup_fn(req, vfswrap_offload_write_cleanup);
1800 case FSCTL_SRV_COPYCHUNK:
1801 case FSCTL_SRV_COPYCHUNK_WRITE:
1804 case FSCTL_OFFLOAD_WRITE:
1805 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
1806 return tevent_req_post(req, ev);
1808 case FSCTL_DUP_EXTENTS_TO_FILE:
1809 DBG_DEBUG("COW clones not supported by vfs_default\n");
1810 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1811 return tevent_req_post(req, ev);
1814 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1815 return tevent_req_post(req, ev);
1819 * From here on we assume a copy-chunk fsctl
1823 tevent_req_done(req);
1824 return tevent_req_post(req, ev);
1827 status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
1829 if (tevent_req_nterror(req, status)) {
1830 return tevent_req_post(req, ev);
1833 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
1835 status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
1836 if (!NT_STATUS_IS_OK(status)) {
1837 tevent_req_nterror(req, status);
1838 return tevent_req_post(req, ev);
1841 ok = change_to_user_by_fsp(src_fsp);
1843 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1844 return tevent_req_post(req, ev);
1847 state->src_ev = src_fsp->conn->sconn->ev_ctx;
1848 state->src_fsp = src_fsp;
1850 state->buf = talloc_array(state, uint8_t, num);
1851 if (tevent_req_nomem(state->buf, req)) {
1852 return tevent_req_post(req, ev);
1855 status = vfs_stat_fsp(src_fsp);
1856 if (tevent_req_nterror(req, status)) {
1857 return tevent_req_post(req, ev);
1860 if (src_fsp->fsp_name->st.st_ex_size < state->src_off + num) {
1862 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1863 * If the SourceOffset or SourceOffset + Length extends beyond
1864 * the end of file, the server SHOULD<240> treat this as a
1865 * STATUS_END_OF_FILE error.
1867 * <240> Section 3.3.5.15.6: Windows servers will return
1868 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1870 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1871 return tevent_req_post(req, ev);
1874 status = vfswrap_offload_write_loop(req);
1875 if (!NT_STATUS_IS_OK(status)) {
1876 tevent_req_nterror(req, status);
1877 return tevent_req_post(req, ev);
1883 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
1885 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
1887 struct vfswrap_offload_write_state *state = tevent_req_data(
1888 req, struct vfswrap_offload_write_state);
1889 struct tevent_req *subreq = NULL;
1890 struct lock_struct read_lck;
1894 * This is called under the context of state->src_fsp.
1897 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
1899 init_strict_lock_struct(state->src_fsp,
1900 state->src_fsp->op->global->open_persistent_id,
1902 state->next_io_size,
1906 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
1910 return NT_STATUS_FILE_LOCK_CONFLICT;
1913 subreq = SMB_VFS_PREAD_SEND(state,
1917 state->next_io_size,
1919 if (subreq == NULL) {
1920 return NT_STATUS_NO_MEMORY;
1922 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
1924 return NT_STATUS_OK;
1927 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
1929 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
1931 struct tevent_req *req = tevent_req_callback_data(
1932 subreq, struct tevent_req);
1933 struct vfswrap_offload_write_state *state = tevent_req_data(
1934 req, struct vfswrap_offload_write_state);
1935 struct vfs_aio_state aio_state;
1936 struct lock_struct write_lck;
1940 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
1941 TALLOC_FREE(subreq);
1943 DBG_ERR("read failed: %s\n", strerror(errno));
1944 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1947 if (nread != state->next_io_size) {
1948 DBG_ERR("Short read, only %zd of %zu\n",
1949 nread, state->next_io_size);
1950 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1954 state->src_off += nread;
1956 ok = change_to_user_by_fsp(state->dst_fsp);
1958 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1962 init_strict_lock_struct(state->dst_fsp,
1963 state->dst_fsp->op->global->open_persistent_id,
1965 state->next_io_size,
1969 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
1973 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1977 subreq = SMB_VFS_PWRITE_SEND(state,
1981 state->next_io_size,
1983 if (subreq == NULL) {
1984 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1987 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
1990 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
1992 struct tevent_req *req = tevent_req_callback_data(
1993 subreq, struct tevent_req);
1994 struct vfswrap_offload_write_state *state = tevent_req_data(
1995 req, struct vfswrap_offload_write_state);
1996 struct vfs_aio_state aio_state;
2001 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
2002 TALLOC_FREE(subreq);
2003 if (nwritten == -1) {
2004 DBG_ERR("write failed: %s\n", strerror(errno));
2005 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2008 if (nwritten != state->next_io_size) {
2009 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
2010 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2014 state->dst_off += nwritten;
2016 if (state->remaining < nwritten) {
2017 /* Paranoia check */
2018 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2021 state->remaining -= nwritten;
2022 if (state->remaining == 0) {
2023 tevent_req_done(req);
2027 ok = change_to_user_by_fsp(state->src_fsp);
2029 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2033 status = vfswrap_offload_write_loop(req);
2034 if (!NT_STATUS_IS_OK(status)) {
2035 tevent_req_nterror(req, status);
2042 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
2043 struct tevent_req *req,
2046 struct vfswrap_offload_write_state *state = tevent_req_data(
2047 req, struct vfswrap_offload_write_state);
2050 if (tevent_req_is_nterror(req, &status)) {
2051 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
2053 tevent_req_received(req);
2057 *copied = state->to_copy;
2058 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
2059 tevent_req_received(req);
2061 return NT_STATUS_OK;
2064 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
2065 TALLOC_CTX *mem_ctx,
2066 struct files_struct *fsp,
2067 struct smb_filename *smb_fname,
2068 uint16_t *_compression_fmt)
2070 return NT_STATUS_INVALID_DEVICE_REQUEST;
2073 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
2074 TALLOC_CTX *mem_ctx,
2075 struct files_struct *fsp,
2076 uint16_t compression_fmt)
2078 return NT_STATUS_INVALID_DEVICE_REQUEST;
2081 /********************************************************************
2082 Given a stat buffer return the allocated size on disk, taking into
2083 account sparse files.
2084 ********************************************************************/
2085 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
2086 struct files_struct *fsp,
2087 const SMB_STRUCT_STAT *sbuf)
2091 START_PROFILE(syscall_get_alloc_size);
2093 if(S_ISDIR(sbuf->st_ex_mode)) {
2098 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2099 /* The type of st_blocksize is blkcnt_t which *MUST* be
2100 signed (according to POSIX) and can be less than 64-bits.
2101 Ensure when we're converting to 64 bits wide we don't
2103 #if defined(SIZEOF_BLKCNT_T_8)
2104 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2105 #elif defined(SIZEOF_BLKCNT_T_4)
2107 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2108 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2111 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2115 * Some file systems do not allocate a block for very
2116 * small files. But for non-empty file should report a
2120 uint64_t filesize = get_file_size_stat(sbuf);
2122 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2126 result = get_file_size_stat(sbuf);
2129 if (fsp && fsp->initial_allocation_size)
2130 result = MAX(result,fsp->initial_allocation_size);
2132 result = smb_roundup(handle->conn, result);
2135 END_PROFILE(syscall_get_alloc_size);
2139 static int vfswrap_unlink(vfs_handle_struct *handle,
2140 const struct smb_filename *smb_fname)
2144 START_PROFILE(syscall_unlink);
2146 if (smb_fname->stream_name) {
2150 result = unlink(smb_fname->base_name);
2153 END_PROFILE(syscall_unlink);
2157 static int vfswrap_chmod(vfs_handle_struct *handle,
2158 const struct smb_filename *smb_fname,
2163 START_PROFILE(syscall_chmod);
2164 result = chmod(smb_fname->base_name, mode);
2165 END_PROFILE(syscall_chmod);
2169 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2173 START_PROFILE(syscall_fchmod);
2174 #if defined(HAVE_FCHMOD)
2175 result = fchmod(fsp->fh->fd, mode);
2181 END_PROFILE(syscall_fchmod);
2185 static int vfswrap_chown(vfs_handle_struct *handle,
2186 const struct smb_filename *smb_fname,
2192 START_PROFILE(syscall_chown);
2193 result = chown(smb_fname->base_name, uid, gid);
2194 END_PROFILE(syscall_chown);
2198 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2203 START_PROFILE(syscall_fchown);
2204 result = fchown(fsp->fh->fd, uid, gid);
2205 END_PROFILE(syscall_fchown);
2213 static int vfswrap_lchown(vfs_handle_struct *handle,
2214 const struct smb_filename *smb_fname,
2220 START_PROFILE(syscall_lchown);
2221 result = lchown(smb_fname->base_name, uid, gid);
2222 END_PROFILE(syscall_lchown);
2226 static int vfswrap_chdir(vfs_handle_struct *handle,
2227 const struct smb_filename *smb_fname)
2231 START_PROFILE(syscall_chdir);
2232 result = chdir(smb_fname->base_name);
2233 END_PROFILE(syscall_chdir);
2237 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2241 struct smb_filename *smb_fname = NULL;
2243 START_PROFILE(syscall_getwd);
2244 result = sys_getwd();
2245 END_PROFILE(syscall_getwd);
2247 if (result == NULL) {
2250 smb_fname = synthetic_smb_fname(ctx,
2256 * sys_getwd() *always* returns malloced memory.
2257 * We must free here to avoid leaks:
2258 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2264 /*********************************************************************
2265 nsec timestamp resolution call. Convert down to whatever the underlying
2266 system will support.
2267 **********************************************************************/
2269 static int vfswrap_ntimes(vfs_handle_struct *handle,
2270 const struct smb_filename *smb_fname,
2271 struct smb_file_time *ft)
2275 START_PROFILE(syscall_ntimes);
2277 if (smb_fname->stream_name) {
2283 if (null_timespec(ft->atime)) {
2284 ft->atime= smb_fname->st.st_ex_atime;
2287 if (null_timespec(ft->mtime)) {
2288 ft->mtime = smb_fname->st.st_ex_mtime;
2291 if (!null_timespec(ft->create_time)) {
2292 set_create_timespec_ea(handle->conn,
2297 if ((timespec_compare(&ft->atime,
2298 &smb_fname->st.st_ex_atime) == 0) &&
2299 (timespec_compare(&ft->mtime,
2300 &smb_fname->st.st_ex_mtime) == 0)) {
2305 #if defined(HAVE_UTIMENSAT)
2307 struct timespec ts[2];
2310 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2312 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2314 if (!((result == -1) && (errno == ENOSYS))) {
2318 #if defined(HAVE_UTIMES)
2320 struct timeval tv[2];
2321 tv[0] = convert_timespec_to_timeval(ft->atime);
2322 tv[1] = convert_timespec_to_timeval(ft->mtime);
2323 result = utimes(smb_fname->base_name, tv);
2325 result = utimes(smb_fname->base_name, NULL);
2327 if (!((result == -1) && (errno == ENOSYS))) {
2331 #if defined(HAVE_UTIME)
2333 struct utimbuf times;
2334 times.actime = convert_timespec_to_time_t(ft->atime);
2335 times.modtime = convert_timespec_to_time_t(ft->mtime);
2336 result = utime(smb_fname->base_name, ×);
2338 result = utime(smb_fname->base_name, NULL);
2340 if (!((result == -1) && (errno == ENOSYS))) {
2348 END_PROFILE(syscall_ntimes);
2352 /*********************************************************************
2353 A version of ftruncate that will write the space on disk if strict
2355 **********************************************************************/
2357 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2359 off_t space_to_write;
2360 uint64_t space_avail;
2361 uint64_t bsize,dfree,dsize;
2364 SMB_STRUCT_STAT *pst;
2366 status = vfs_stat_fsp(fsp);
2367 if (!NT_STATUS_IS_OK(status)) {
2370 pst = &fsp->fsp_name->st;
2373 if (S_ISFIFO(pst->st_ex_mode))
2377 if (pst->st_ex_size == len)
2380 /* Shrink - just ftruncate. */
2381 if (pst->st_ex_size > len)
2382 return ftruncate(fsp->fh->fd, len);
2384 space_to_write = len - pst->st_ex_size;
2386 /* for allocation try fallocate first. This can fail on some
2387 platforms e.g. when the filesystem doesn't support it and no
2388 emulation is being done by the libc (like on AIX with JFS1). In that
2389 case we do our own emulation. fallocate implementations can
2390 return ENOTSUP or EINVAL in cases like that. */
2391 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2392 if (ret == -1 && errno == ENOSPC) {
2398 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2399 "error %d. Falling back to slow manual allocation\n", errno));
2401 /* available disk space is enough or not? */
2403 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2404 /* space_avail is 1k blocks */
2405 if (space_avail == (uint64_t)-1 ||
2406 ((uint64_t)space_to_write/1024 > space_avail) ) {
2411 /* Write out the real space on disk. */
2412 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2420 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2423 SMB_STRUCT_STAT *pst;
2427 START_PROFILE(syscall_ftruncate);
2429 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2430 result = strict_allocate_ftruncate(handle, fsp, len);
2431 END_PROFILE(syscall_ftruncate);
2435 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2436 ftruncate if the system supports it. Then I discovered that
2437 you can have some filesystems that support ftruncate
2438 expansion and some that don't! On Linux fat can't do
2439 ftruncate extend but ext2 can. */
2441 result = ftruncate(fsp->fh->fd, len);
2443 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2444 extend a file with ftruncate. Provide alternate implementation
2447 /* Do an fstat to see if the file is longer than the requested
2448 size in which case the ftruncate above should have
2449 succeeded or shorter, in which case seek to len - 1 and
2450 write 1 byte of zero */
2451 status = vfs_stat_fsp(fsp);
2452 if (!NT_STATUS_IS_OK(status)) {
2456 /* We need to update the files_struct after successful ftruncate */
2461 pst = &fsp->fsp_name->st;
2464 if (S_ISFIFO(pst->st_ex_mode)) {
2470 if (pst->st_ex_size == len) {
2475 if (pst->st_ex_size > len) {
2476 /* the ftruncate should have worked */
2480 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2488 END_PROFILE(syscall_ftruncate);
2492 static int vfswrap_fallocate(vfs_handle_struct *handle,
2500 START_PROFILE(syscall_fallocate);
2502 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2504 * posix_fallocate returns 0 on success, errno on error
2505 * and doesn't set errno. Make it behave like fallocate()
2506 * which returns -1, and sets errno on failure.
2513 /* sys_fallocate handles filtering of unsupported mode flags */
2514 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2516 END_PROFILE(syscall_fallocate);
2520 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2524 START_PROFILE(syscall_fcntl_lock);
2526 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2528 "force process locks",
2530 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2533 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2534 END_PROFILE(syscall_fcntl_lock);
2538 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2539 uint32_t share_mode, uint32_t access_mask)
2541 START_PROFILE(syscall_kernel_flock);
2542 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2543 END_PROFILE(syscall_kernel_flock);
2547 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2552 START_PROFILE(syscall_fcntl_getlock);
2554 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2556 "force process locks",
2558 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2561 result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2562 END_PROFILE(syscall_fcntl_getlock);
2566 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2571 START_PROFILE(syscall_linux_setlease);
2573 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2574 result = linux_setlease(fsp->fh->fd, leasetype);
2578 END_PROFILE(syscall_linux_setlease);
2582 static int vfswrap_symlink(vfs_handle_struct *handle,
2583 const char *link_target,
2584 const struct smb_filename *new_smb_fname)
2588 START_PROFILE(syscall_symlink);
2589 result = symlink(link_target, new_smb_fname->base_name);
2590 END_PROFILE(syscall_symlink);
2594 static int vfswrap_readlink(vfs_handle_struct *handle,
2595 const struct smb_filename *smb_fname,
2601 START_PROFILE(syscall_readlink);
2602 result = readlink(smb_fname->base_name, buf, bufsiz);
2603 END_PROFILE(syscall_readlink);
2607 static int vfswrap_link(vfs_handle_struct *handle,
2608 const struct smb_filename *old_smb_fname,
2609 const struct smb_filename *new_smb_fname)
2613 START_PROFILE(syscall_link);
2614 result = link(old_smb_fname->base_name, new_smb_fname->base_name);
2615 END_PROFILE(syscall_link);
2619 static int vfswrap_mknod(vfs_handle_struct *handle,
2620 const struct smb_filename *smb_fname,
2626 START_PROFILE(syscall_mknod);
2627 result = sys_mknod(smb_fname->base_name, mode, dev);
2628 END_PROFILE(syscall_mknod);
2632 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2634 const struct smb_filename *smb_fname)
2637 struct smb_filename *result_fname = NULL;
2639 START_PROFILE(syscall_realpath);
2640 result = sys_realpath(smb_fname->base_name);
2641 END_PROFILE(syscall_realpath);
2643 result_fname = synthetic_smb_fname(ctx, result, NULL, NULL, 0);
2646 return result_fname;
2649 static int vfswrap_chflags(vfs_handle_struct *handle,
2650 const struct smb_filename *smb_fname,
2654 return chflags(smb_fname->base_name, flags);
2661 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2662 const SMB_STRUCT_STAT *sbuf)
2666 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2670 key.devid = sbuf->st_ex_dev;
2671 key.inode = sbuf->st_ex_ino;
2672 /* key.extid is unused by default. */
2677 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2678 struct files_struct *fsp,
2679 const struct smb_filename *smb_fname,
2680 TALLOC_CTX *mem_ctx,
2681 unsigned int *pnum_streams,
2682 struct stream_struct **pstreams)
2684 SMB_STRUCT_STAT sbuf;
2685 struct stream_struct *tmp_streams = NULL;
2688 if ((fsp != NULL) && (fsp->is_directory)) {
2690 * No default streams on directories
2695 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2696 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2699 struct smb_filename smb_fname_cp;
2701 ZERO_STRUCT(smb_fname_cp);
2702 smb_fname_cp.base_name = discard_const_p(char,
2703 smb_fname->base_name);
2704 smb_fname_cp.flags = smb_fname->flags;
2706 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
2707 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2709 ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2711 sbuf = smb_fname_cp.st;
2715 return map_nt_error_from_unix(errno);
2718 if (S_ISDIR(sbuf.st_ex_mode)) {
2722 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2723 (*pnum_streams) + 1);
2724 if (tmp_streams == NULL) {
2725 return NT_STATUS_NO_MEMORY;
2727 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2728 if (tmp_streams[*pnum_streams].name == NULL) {
2729 return NT_STATUS_NO_MEMORY;
2731 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2732 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2735 *pstreams = tmp_streams;
2737 return NT_STATUS_OK;
2740 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2743 TALLOC_CTX *mem_ctx,
2747 * Don't fall back to get_real_filename so callers can differentiate
2748 * between a full directory scan and an actual case-insensitive stat.
2754 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2755 const struct smb_filename *smb_fname)
2757 return handle->conn->connectpath;
2760 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2761 struct byte_range_lock *br_lck,
2762 struct lock_struct *plock,
2765 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2767 /* Note: blr is not used in the default implementation. */
2768 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2771 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2772 struct messaging_context *msg_ctx,
2773 struct byte_range_lock *br_lck,
2774 const struct lock_struct *plock)
2776 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2778 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2781 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2782 struct byte_range_lock *br_lck,
2783 struct lock_struct *plock)
2785 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2787 /* Note: blr is not used in the default implementation. */
2788 return brl_lock_cancel_default(br_lck, plock);
2791 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
2793 struct lock_struct *plock)
2795 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2796 plock->lock_type == WRITE_LOCK);
2798 return strict_lock_check_default(fsp, plock);
2801 /* NT ACL operations. */
2803 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2805 uint32_t security_info,
2806 TALLOC_CTX *mem_ctx,
2807 struct security_descriptor **ppdesc)
2811 START_PROFILE(fget_nt_acl);
2812 result = posix_fget_nt_acl(fsp, security_info,
2814 END_PROFILE(fget_nt_acl);
2818 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2819 const struct smb_filename *smb_fname,
2820 uint32_t security_info,
2821 TALLOC_CTX *mem_ctx,
2822 struct security_descriptor **ppdesc)
2826 START_PROFILE(get_nt_acl);
2827 result = posix_get_nt_acl(handle->conn,
2832 END_PROFILE(get_nt_acl);
2836 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2840 START_PROFILE(fset_nt_acl);
2841 result = set_nt_acl(fsp, security_info_sent, psd);
2842 END_PROFILE(fset_nt_acl);
2846 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2847 struct smb_filename *file,
2848 struct security_acl *sacl,
2849 uint32_t access_requested,
2850 uint32_t access_denied)
2852 return NT_STATUS_OK; /* Nothing to do here ... */
2855 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2856 const struct smb_filename *smb_fname,
2857 SMB_ACL_TYPE_T type,
2858 TALLOC_CTX *mem_ctx)
2860 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
2863 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2865 TALLOC_CTX *mem_ctx)
2867 return sys_acl_get_fd(handle, fsp, mem_ctx);
2870 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
2871 const struct smb_filename *smb_fname,
2872 SMB_ACL_TYPE_T acltype,
2875 return sys_acl_set_file(handle, smb_fname, acltype, theacl);
2878 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2880 return sys_acl_set_fd(handle, fsp, theacl);
2883 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
2884 const struct smb_filename *smb_fname)
2886 return sys_acl_delete_def_file(handle, smb_fname);
2889 /****************************************************************
2890 Extended attribute operations.
2891 *****************************************************************/
2893 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
2894 const struct smb_filename *smb_fname,
2899 return getxattr(smb_fname->base_name, name, value, size);
2902 struct vfswrap_getxattrat_state {
2903 struct tevent_context *ev;
2904 files_struct *dir_fsp;
2905 const struct smb_filename *smb_fname;
2906 struct tevent_req *req;
2909 * The following variables are talloced off "state" which is protected
2910 * by a destructor and thus are guaranteed to be safe to be used in the
2911 * job function in the worker thread.
2914 const char *xattr_name;
2915 uint8_t *xattr_value;
2916 struct security_unix_token *token;
2919 struct vfs_aio_state vfs_aio_state;
2920 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
2923 static int vfswrap_getxattrat_state_destructor(
2924 struct vfswrap_getxattrat_state *state)
2929 static void vfswrap_getxattrat_do_sync(struct tevent_req *req);
2930 static void vfswrap_getxattrat_do_async(void *private_data);
2931 static void vfswrap_getxattrat_done(struct tevent_req *subreq);
2933 static struct tevent_req *vfswrap_getxattrat_send(
2934 TALLOC_CTX *mem_ctx,
2935 struct tevent_context *ev,
2936 struct vfs_handle_struct *handle,
2937 files_struct *dir_fsp,
2938 const struct smb_filename *smb_fname,
2939 const char *xattr_name,
2942 struct tevent_req *req = NULL;
2943 struct tevent_req *subreq = NULL;
2944 struct vfswrap_getxattrat_state *state = NULL;
2945 size_t max_threads = 0;
2946 bool have_per_thread_cwd = false;
2947 bool have_per_thread_creds = false;
2948 bool do_async = false;
2950 req = tevent_req_create(mem_ctx, &state,
2951 struct vfswrap_getxattrat_state);
2955 *state = (struct vfswrap_getxattrat_state) {
2958 .smb_fname = smb_fname,
2962 max_threads = pthreadpool_tevent_max_threads(dir_fsp->conn->sconn->pool);
2963 if (max_threads >= 1) {
2965 * We need a non sync threadpool!
2967 have_per_thread_cwd = per_thread_cwd_supported();
2969 #ifdef HAVE_LINUX_THREAD_CREDENTIALS
2970 have_per_thread_creds = true;
2972 if (have_per_thread_cwd && have_per_thread_creds) {
2976 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat, profile_p,
2977 state->profile_bytes, 0);
2979 if (dir_fsp->fh->fd == -1) {
2980 DBG_ERR("Need a valid directory fd\n");
2981 tevent_req_error(req, EINVAL);
2982 return tevent_req_post(req, ev);
2985 if (alloc_hint > 0) {
2986 state->xattr_value = talloc_zero_array(state,
2989 if (tevent_req_nomem(state->xattr_value, req)) {
2990 return tevent_req_post(req, ev);
2995 vfswrap_getxattrat_do_sync(req);
2996 return tevent_req_post(req, ev);
3000 * Now allocate all parameters from a memory context that won't go away
3001 * no matter what. These paremeters will get used in threads and we
3002 * can't reliably cancel threads, so all buffers passed to the threads
3003 * must not be freed before all referencing threads terminate.
3006 state->name = talloc_strdup(state, smb_fname->base_name);
3007 if (tevent_req_nomem(state->name, req)) {
3008 return tevent_req_post(req, ev);
3011 state->xattr_name = talloc_strdup(state, xattr_name);
3012 if (tevent_req_nomem(state->xattr_name, req)) {
3013 return tevent_req_post(req, ev);
3017 * This is a hot codepath so at first glance one might think we should
3018 * somehow optimize away the token allocation and do a
3019 * talloc_reference() or similar black magic instead. But due to the
3020 * talloc_stackframe pool per SMB2 request this should be a simple copy
3021 * without a malloc in most cases.
3023 if (geteuid() == sec_initial_uid()) {
3024 state->token = root_unix_token(state);
3026 state->token = copy_unix_token(
3028 dir_fsp->conn->session_info->unix_token);
3030 if (tevent_req_nomem(state->token, req)) {
3031 return tevent_req_post(req, ev);
3034 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3036 subreq = pthreadpool_tevent_job_send(
3039 dir_fsp->conn->sconn->pool,
3040 vfswrap_getxattrat_do_async,
3042 if (tevent_req_nomem(subreq, req)) {
3043 return tevent_req_post(req, ev);
3045 tevent_req_set_callback(subreq, vfswrap_getxattrat_done, req);
3047 talloc_set_destructor(state, vfswrap_getxattrat_state_destructor);
3052 static void vfswrap_getxattrat_do_sync(struct tevent_req *req)
3054 struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3055 req, struct vfswrap_getxattrat_state);
3057 char *tofree = NULL;
3058 char pathbuf[PATH_MAX+1];
3062 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
3063 state->smb_fname->base_name,
3068 if (pathlen == -1) {
3069 tevent_req_error(req, ENOMEM);
3073 state->xattr_size = getxattr(path,
3076 talloc_array_length(state->xattr_value));
3078 TALLOC_FREE(tofree);
3079 if (state->xattr_size == -1) {
3080 tevent_req_error(req, err);
3084 tevent_req_done(req);
3088 static void vfswrap_getxattrat_do_async(void *private_data)
3090 struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3091 private_data, struct vfswrap_getxattrat_state);
3092 struct timespec start_time;
3093 struct timespec end_time;
3096 PROFILE_TIMESTAMP(&start_time);
3097 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
3100 * Here we simulate a getxattrat()
3101 * call using fchdir();getxattr()
3104 per_thread_cwd_activate();
3106 /* Become the correct credential on this thread. */
3107 ret = set_thread_credentials(state->token->uid,
3109 (size_t)state->token->ngroups,
3110 state->token->groups);
3112 state->xattr_size = -1;
3113 state->vfs_aio_state.error = errno;
3117 ret = fchdir(state->dir_fsp->fh->fd);
3119 state->xattr_size = -1;
3120 state->vfs_aio_state.error = errno;
3124 state->xattr_size = getxattr(state->name,
3127 talloc_array_length(state->xattr_value));
3128 if (state->xattr_size == -1) {
3129 state->vfs_aio_state.error = errno;
3133 PROFILE_TIMESTAMP(&end_time);
3134 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
3135 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3138 static void vfswrap_getxattrat_done(struct tevent_req *subreq)
3140 struct tevent_req *req = tevent_req_callback_data(
3141 subreq, struct tevent_req);
3142 struct vfswrap_getxattrat_state *state = tevent_req_data(
3143 req, struct vfswrap_getxattrat_state);
3148 * Make sure we run as the user again
3150 ok = change_to_user(state->dir_fsp->conn,
3151 state->dir_fsp->vuid);
3153 smb_panic("Can't change to user");
3157 ret = pthreadpool_tevent_job_recv(subreq);
3158 TALLOC_FREE(subreq);
3159 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
3160 talloc_set_destructor(state, NULL);
3162 if (ret != EAGAIN) {
3163 tevent_req_error(req, ret);
3167 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
3168 * means the lower level pthreadpool failed to create a new
3169 * thread. Fallback to sync processing in that case to allow
3170 * some progress for the client.
3172 vfswrap_getxattrat_do_sync(req);
3176 if (state->xattr_size == -1) {
3177 tevent_req_error(req, state->vfs_aio_state.error);
3181 if (state->xattr_value == NULL) {
3183 * The caller only wanted the size.
3185 tevent_req_done(req);
3190 * shrink the buffer to the returned size.
3191 * (can't fail). It means NULL if size is 0.
3193 state->xattr_value = talloc_realloc(state,
3198 tevent_req_done(req);
3201 static ssize_t vfswrap_getxattrat_recv(struct tevent_req *req,
3202 struct vfs_aio_state *aio_state,
3203 TALLOC_CTX *mem_ctx,
3204 uint8_t **xattr_value)
3206 struct vfswrap_getxattrat_state *state = tevent_req_data(
3207 req, struct vfswrap_getxattrat_state);
3210 if (tevent_req_is_unix_error(req, &aio_state->error)) {
3211 tevent_req_received(req);
3215 *aio_state = state->vfs_aio_state;
3216 xattr_size = state->xattr_size;
3217 if (xattr_value != NULL) {
3218 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
3221 tevent_req_received(req);
3225 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
3227 return fgetxattr(fsp->fh->fd, name, value, size);
3230 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
3231 const struct smb_filename *smb_fname,
3235 return listxattr(smb_fname->base_name, list, size);
3238 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
3240 return flistxattr(fsp->fh->fd, list, size);
3243 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
3244 const struct smb_filename *smb_fname,
3247 return removexattr(smb_fname->base_name, name);
3250 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
3252 return fremovexattr(fsp->fh->fd, name);
3255 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
3256 const struct smb_filename *smb_fname,
3262 return setxattr(smb_fname->base_name, name, value, size, flags);
3265 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
3267 return fsetxattr(fsp->fh->fd, name, value, size, flags);
3270 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
3275 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
3276 const struct smb_filename *fname,
3277 SMB_STRUCT_STAT *sbuf)
3281 bool offline = false;
3283 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
3287 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
3288 #if defined(ENOTSUP)
3294 status = get_full_smb_filename(talloc_tos(), fname, &path);
3295 if (!NT_STATUS_IS_OK(status)) {
3296 errno = map_errno_from_nt_status(status);
3300 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
3307 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
3308 struct files_struct *fsp,
3309 TALLOC_CTX *mem_ctx,
3312 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
3315 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
3316 struct files_struct *fsp,
3317 const DATA_BLOB old_cookie,
3318 TALLOC_CTX *mem_ctx,
3319 DATA_BLOB *new_cookie)
3321 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
3325 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
3326 struct smb_request *smb1req,
3327 struct smbXsrv_open *op,
3328 const DATA_BLOB old_cookie,
3329 TALLOC_CTX *mem_ctx,
3330 struct files_struct **fsp,
3331 DATA_BLOB *new_cookie)
3333 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
3334 old_cookie, mem_ctx,
3338 static struct vfs_fn_pointers vfs_default_fns = {
3339 /* Disk operations */
3341 .connect_fn = vfswrap_connect,
3342 .disconnect_fn = vfswrap_disconnect,
3343 .disk_free_fn = vfswrap_disk_free,
3344 .get_quota_fn = vfswrap_get_quota,
3345 .set_quota_fn = vfswrap_set_quota,
3346 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3347 .statvfs_fn = vfswrap_statvfs,
3348 .fs_capabilities_fn = vfswrap_fs_capabilities,
3349 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3350 .snap_check_path_fn = vfswrap_snap_check_path,
3351 .snap_create_fn = vfswrap_snap_create,
3352 .snap_delete_fn = vfswrap_snap_delete,
3354 /* Directory operations */
3356 .opendir_fn = vfswrap_opendir,
3357 .fdopendir_fn = vfswrap_fdopendir,
3358 .readdir_fn = vfswrap_readdir,
3359 .readdir_attr_fn = vfswrap_readdir_attr,
3360 .seekdir_fn = vfswrap_seekdir,
3361 .telldir_fn = vfswrap_telldir,
3362 .rewind_dir_fn = vfswrap_rewinddir,
3363 .mkdir_fn = vfswrap_mkdir,
3364 .rmdir_fn = vfswrap_rmdir,
3365 .closedir_fn = vfswrap_closedir,
3367 /* File operations */
3369 .open_fn = vfswrap_open,
3370 .create_file_fn = vfswrap_create_file,
3371 .close_fn = vfswrap_close,
3372 .pread_fn = vfswrap_pread,
3373 .pread_send_fn = vfswrap_pread_send,
3374 .pread_recv_fn = vfswrap_pread_recv,
3375 .pwrite_fn = vfswrap_pwrite,
3376 .pwrite_send_fn = vfswrap_pwrite_send,
3377 .pwrite_recv_fn = vfswrap_pwrite_recv,
3378 .lseek_fn = vfswrap_lseek,
3379 .sendfile_fn = vfswrap_sendfile,
3380 .recvfile_fn = vfswrap_recvfile,
3381 .rename_fn = vfswrap_rename,
3382 .fsync_send_fn = vfswrap_fsync_send,
3383 .fsync_recv_fn = vfswrap_fsync_recv,
3384 .stat_fn = vfswrap_stat,
3385 .fstat_fn = vfswrap_fstat,
3386 .lstat_fn = vfswrap_lstat,
3387 .get_alloc_size_fn = vfswrap_get_alloc_size,
3388 .unlink_fn = vfswrap_unlink,
3389 .chmod_fn = vfswrap_chmod,
3390 .fchmod_fn = vfswrap_fchmod,
3391 .chown_fn = vfswrap_chown,
3392 .fchown_fn = vfswrap_fchown,
3393 .lchown_fn = vfswrap_lchown,
3394 .chdir_fn = vfswrap_chdir,
3395 .getwd_fn = vfswrap_getwd,
3396 .ntimes_fn = vfswrap_ntimes,
3397 .ftruncate_fn = vfswrap_ftruncate,
3398 .fallocate_fn = vfswrap_fallocate,
3399 .lock_fn = vfswrap_lock,
3400 .kernel_flock_fn = vfswrap_kernel_flock,
3401 .linux_setlease_fn = vfswrap_linux_setlease,
3402 .getlock_fn = vfswrap_getlock,
3403 .symlink_fn = vfswrap_symlink,
3404 .readlink_fn = vfswrap_readlink,
3405 .link_fn = vfswrap_link,
3406 .mknod_fn = vfswrap_mknod,
3407 .realpath_fn = vfswrap_realpath,
3408 .chflags_fn = vfswrap_chflags,
3409 .file_id_create_fn = vfswrap_file_id_create,
3410 .streaminfo_fn = vfswrap_streaminfo,
3411 .get_real_filename_fn = vfswrap_get_real_filename,
3412 .connectpath_fn = vfswrap_connectpath,
3413 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
3414 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3415 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
3416 .strict_lock_check_fn = vfswrap_strict_lock_check,
3417 .translate_name_fn = vfswrap_translate_name,
3418 .fsctl_fn = vfswrap_fsctl,
3419 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
3420 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
3421 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
3422 .get_dos_attributes_send_fn = vfswrap_get_dos_attributes_send,
3423 .get_dos_attributes_recv_fn = vfswrap_get_dos_attributes_recv,
3424 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
3425 .offload_read_send_fn = vfswrap_offload_read_send,
3426 .offload_read_recv_fn = vfswrap_offload_read_recv,
3427 .offload_write_send_fn = vfswrap_offload_write_send,
3428 .offload_write_recv_fn = vfswrap_offload_write_recv,
3429 .get_compression_fn = vfswrap_get_compression,
3430 .set_compression_fn = vfswrap_set_compression,
3432 /* NT ACL operations. */
3434 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
3435 .get_nt_acl_fn = vfswrap_get_nt_acl,
3436 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
3437 .audit_file_fn = vfswrap_audit_file,
3439 /* POSIX ACL operations. */
3441 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
3442 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3443 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
3444 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3445 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
3446 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3447 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
3449 /* EA operations. */
3450 .getxattr_fn = vfswrap_getxattr,
3451 .getxattrat_send_fn = vfswrap_getxattrat_send,
3452 .getxattrat_recv_fn = vfswrap_getxattrat_recv,
3453 .fgetxattr_fn = vfswrap_fgetxattr,
3454 .listxattr_fn = vfswrap_listxattr,
3455 .flistxattr_fn = vfswrap_flistxattr,
3456 .removexattr_fn = vfswrap_removexattr,
3457 .fremovexattr_fn = vfswrap_fremovexattr,
3458 .setxattr_fn = vfswrap_setxattr,
3459 .fsetxattr_fn = vfswrap_fsetxattr,
3461 /* aio operations */
3462 .aio_force_fn = vfswrap_aio_force,
3464 /* durable handle operations */
3465 .durable_cookie_fn = vfswrap_durable_cookie,
3466 .durable_disconnect_fn = vfswrap_durable_disconnect,
3467 .durable_reconnect_fn = vfswrap_durable_reconnect,
3471 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3474 * Here we need to implement every call!
3476 * As this is the end of the vfs module chain.
3478 smb_vfs_assert_all_fns(&vfs_default_fns, DEFAULT_VFS_MODULE_NAME);
3479 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3480 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);