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);
747 tevent_req_error(req, ret);
751 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
752 * means the lower level pthreadpool failed to create a new
753 * thread. Fallback to sync processing in that case to allow
754 * some progress for the client.
759 tevent_req_done(req);
762 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
763 struct vfs_aio_state *vfs_aio_state)
765 struct vfswrap_pread_state *state = tevent_req_data(
766 req, struct vfswrap_pread_state);
768 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
772 *vfs_aio_state = state->vfs_aio_state;
776 struct vfswrap_pwrite_state {
783 struct vfs_aio_state vfs_aio_state;
784 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
787 static void vfs_pwrite_do(void *private_data);
788 static void vfs_pwrite_done(struct tevent_req *subreq);
789 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state);
791 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
793 struct tevent_context *ev,
794 struct files_struct *fsp,
796 size_t n, off_t offset)
798 struct tevent_req *req, *subreq;
799 struct vfswrap_pwrite_state *state;
801 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
807 state->fd = fsp->fh->fd;
810 state->offset = offset;
812 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
813 state->profile_bytes, n);
814 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
816 subreq = pthreadpool_tevent_job_send(
817 state, ev, handle->conn->sconn->pool,
818 vfs_pwrite_do, state);
819 if (tevent_req_nomem(subreq, req)) {
820 return tevent_req_post(req, ev);
822 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
824 talloc_set_destructor(state, vfs_pwrite_state_destructor);
829 static void vfs_pwrite_do(void *private_data)
831 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
832 private_data, struct vfswrap_pwrite_state);
833 struct timespec start_time;
834 struct timespec end_time;
836 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
838 PROFILE_TIMESTAMP(&start_time);
841 state->ret = pwrite(state->fd, state->buf, state->count,
843 } while ((state->ret == -1) && (errno == EINTR));
845 if (state->ret == -1) {
846 state->vfs_aio_state.error = errno;
849 PROFILE_TIMESTAMP(&end_time);
851 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
853 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
856 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state)
861 static void vfs_pwrite_done(struct tevent_req *subreq)
863 struct tevent_req *req = tevent_req_callback_data(
864 subreq, struct tevent_req);
865 struct vfswrap_pwrite_state *state = tevent_req_data(
866 req, struct vfswrap_pwrite_state);
869 ret = pthreadpool_tevent_job_recv(subreq);
871 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
872 talloc_set_destructor(state, NULL);
875 tevent_req_error(req, ret);
879 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
880 * means the lower level pthreadpool failed to create a new
881 * thread. Fallback to sync processing in that case to allow
882 * some progress for the client.
884 vfs_pwrite_do(state);
887 tevent_req_done(req);
890 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
891 struct vfs_aio_state *vfs_aio_state)
893 struct vfswrap_pwrite_state *state = tevent_req_data(
894 req, struct vfswrap_pwrite_state);
896 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
900 *vfs_aio_state = state->vfs_aio_state;
904 struct vfswrap_fsync_state {
908 struct vfs_aio_state vfs_aio_state;
909 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
912 static void vfs_fsync_do(void *private_data);
913 static void vfs_fsync_done(struct tevent_req *subreq);
914 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state);
916 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
918 struct tevent_context *ev,
919 struct files_struct *fsp)
921 struct tevent_req *req, *subreq;
922 struct vfswrap_fsync_state *state;
924 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
930 state->fd = fsp->fh->fd;
932 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_fsync, profile_p,
933 state->profile_bytes, 0);
934 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
936 subreq = pthreadpool_tevent_job_send(
937 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
938 if (tevent_req_nomem(subreq, req)) {
939 return tevent_req_post(req, ev);
941 tevent_req_set_callback(subreq, vfs_fsync_done, req);
943 talloc_set_destructor(state, vfs_fsync_state_destructor);
948 static void vfs_fsync_do(void *private_data)
950 struct vfswrap_fsync_state *state = talloc_get_type_abort(
951 private_data, struct vfswrap_fsync_state);
952 struct timespec start_time;
953 struct timespec end_time;
955 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
957 PROFILE_TIMESTAMP(&start_time);
960 state->ret = fsync(state->fd);
961 } while ((state->ret == -1) && (errno == EINTR));
963 if (state->ret == -1) {
964 state->vfs_aio_state.error = errno;
967 PROFILE_TIMESTAMP(&end_time);
969 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
971 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
974 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state)
979 static void vfs_fsync_done(struct tevent_req *subreq)
981 struct tevent_req *req = tevent_req_callback_data(
982 subreq, struct tevent_req);
983 struct vfswrap_fsync_state *state = tevent_req_data(
984 req, struct vfswrap_fsync_state);
987 ret = pthreadpool_tevent_job_recv(subreq);
989 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
990 talloc_set_destructor(state, NULL);
993 tevent_req_error(req, ret);
997 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
998 * means the lower level pthreadpool failed to create a new
999 * thread. Fallback to sync processing in that case to allow
1000 * some progress for the client.
1002 vfs_fsync_do(state);
1005 tevent_req_done(req);
1008 static int vfswrap_fsync_recv(struct tevent_req *req,
1009 struct vfs_aio_state *vfs_aio_state)
1011 struct vfswrap_fsync_state *state = tevent_req_data(
1012 req, struct vfswrap_fsync_state);
1014 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1018 *vfs_aio_state = state->vfs_aio_state;
1022 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1026 START_PROFILE(syscall_lseek);
1028 result = lseek(fsp->fh->fd, offset, whence);
1030 * We want to maintain the fiction that we can seek
1031 * on a fifo for file system purposes. This allows
1032 * people to set up UNIX fifo's that feed data to Windows
1033 * applications. JRA.
1036 if((result == -1) && (errno == ESPIPE)) {
1041 END_PROFILE(syscall_lseek);
1045 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1046 off_t offset, size_t n)
1050 START_PROFILE_BYTES(syscall_sendfile, n);
1051 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
1052 END_PROFILE_BYTES(syscall_sendfile);
1056 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1058 files_struct *tofsp,
1064 START_PROFILE_BYTES(syscall_recvfile, n);
1065 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
1066 END_PROFILE_BYTES(syscall_recvfile);
1070 static int vfswrap_rename(vfs_handle_struct *handle,
1071 const struct smb_filename *smb_fname_src,
1072 const struct smb_filename *smb_fname_dst)
1076 START_PROFILE(syscall_rename);
1078 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
1083 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
1086 END_PROFILE(syscall_rename);
1090 static int vfswrap_stat(vfs_handle_struct *handle,
1091 struct smb_filename *smb_fname)
1095 START_PROFILE(syscall_stat);
1097 if (smb_fname->stream_name) {
1102 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1103 lp_fake_directory_create_times(SNUM(handle->conn)));
1105 END_PROFILE(syscall_stat);
1109 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1113 START_PROFILE(syscall_fstat);
1114 result = sys_fstat(fsp->fh->fd,
1115 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1116 END_PROFILE(syscall_fstat);
1120 static int vfswrap_lstat(vfs_handle_struct *handle,
1121 struct smb_filename *smb_fname)
1125 START_PROFILE(syscall_lstat);
1127 if (smb_fname->stream_name) {
1132 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1133 lp_fake_directory_create_times(SNUM(handle->conn)));
1135 END_PROFILE(syscall_lstat);
1139 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1141 enum vfs_translate_direction direction,
1142 TALLOC_CTX *mem_ctx,
1145 return NT_STATUS_NONE_MAPPED;
1149 * Implement the default fsctl operation.
1151 static bool vfswrap_logged_ioctl_message = false;
1153 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1154 struct files_struct *fsp,
1157 uint16_t req_flags, /* Needed for UNICODE ... */
1158 const uint8_t *_in_data,
1160 uint8_t **_out_data,
1161 uint32_t max_out_len,
1164 const char *in_data = (const char *)_in_data;
1165 char **out_data = (char **)_out_data;
1169 case FSCTL_SET_SPARSE:
1171 bool set_sparse = true;
1173 if (in_len >= 1 && in_data[0] == 0) {
1177 status = file_set_sparse(handle->conn, fsp, set_sparse);
1179 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1180 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1181 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1182 nt_errstr(status)));
1187 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1189 unsigned char objid[16];
1190 char *return_data = NULL;
1192 /* This should return the object-id on this file.
1193 * I think I'll make this be the inode+dev. JRA.
1196 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1197 fsp_fnum_dbg(fsp)));
1199 *out_len = MIN(max_out_len, 64);
1201 /* Hmmm, will this cause problems if less data asked for? */
1202 return_data = talloc_array(ctx, char, 64);
1203 if (return_data == NULL) {
1204 return NT_STATUS_NO_MEMORY;
1207 /* For backwards compatibility only store the dev/inode. */
1208 push_file_id_16(return_data, &fsp->file_id);
1209 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1210 push_file_id_16(return_data+32, &fsp->file_id);
1211 memset(return_data+48, 0, 16);
1212 *out_data = return_data;
1213 return NT_STATUS_OK;
1216 case FSCTL_GET_REPARSE_POINT:
1218 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1219 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1220 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1221 return NT_STATUS_NOT_A_REPARSE_POINT;
1224 case FSCTL_SET_REPARSE_POINT:
1226 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1227 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1228 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1229 return NT_STATUS_NOT_A_REPARSE_POINT;
1232 case FSCTL_GET_SHADOW_COPY_DATA:
1235 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1236 * and return their volume names. If max_data_count is 16, then it is just
1237 * asking for the number of volumes and length of the combined names.
1239 * pdata is the data allocated by our caller, but that uses
1240 * total_data_count (which is 0 in our case) rather than max_data_count.
1241 * Allocate the correct amount and return the pointer to let
1242 * it be deallocated when we return.
1244 struct shadow_copy_data *shadow_data = NULL;
1245 bool labels = False;
1246 uint32_t labels_data_count = 0;
1248 char *cur_pdata = NULL;
1250 if (max_out_len < 16) {
1251 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1253 return NT_STATUS_INVALID_PARAMETER;
1256 if (max_out_len > 16) {
1260 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1261 if (shadow_data == NULL) {
1262 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1263 return NT_STATUS_NO_MEMORY;
1267 * Call the VFS routine to actually do the work.
1269 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1272 /* broken module didn't set errno on error */
1273 status = NT_STATUS_UNSUCCESSFUL;
1275 status = map_nt_error_from_unix(errno);
1276 if (NT_STATUS_EQUAL(status,
1277 NT_STATUS_NOT_SUPPORTED)) {
1281 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1282 "connectpath %s, failed - %s.\n",
1283 fsp->conn->connectpath,
1284 nt_errstr(status)));
1285 TALLOC_FREE(shadow_data);
1289 labels_data_count = (shadow_data->num_volumes * 2 *
1290 sizeof(SHADOW_COPY_LABEL)) + 2;
1295 *out_len = 12 + labels_data_count;
1298 if (max_out_len < *out_len) {
1299 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1300 max_out_len, *out_len));
1301 TALLOC_FREE(shadow_data);
1302 return NT_STATUS_BUFFER_TOO_SMALL;
1305 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1306 if (cur_pdata == NULL) {
1307 TALLOC_FREE(shadow_data);
1308 return NT_STATUS_NO_MEMORY;
1311 *out_data = cur_pdata;
1313 /* num_volumes 4 bytes */
1314 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1317 /* num_labels 4 bytes */
1318 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1321 /* needed_data_count 4 bytes */
1322 SIVAL(cur_pdata, 8, labels_data_count);
1326 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1327 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1328 if (labels && shadow_data->labels) {
1329 for (i=0; i<shadow_data->num_volumes; i++) {
1331 status = srvstr_push(cur_pdata, req_flags,
1332 cur_pdata, shadow_data->labels[i],
1333 2 * sizeof(SHADOW_COPY_LABEL),
1334 STR_UNICODE|STR_TERMINATE, &len);
1335 if (!NT_STATUS_IS_OK(status)) {
1336 TALLOC_FREE(*out_data);
1337 TALLOC_FREE(shadow_data);
1340 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1341 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1345 TALLOC_FREE(shadow_data);
1347 return NT_STATUS_OK;
1350 case FSCTL_FIND_FILES_BY_SID:
1352 /* pretend this succeeded -
1354 * we have to send back a list with all files owned by this SID
1356 * but I have to check that --metze
1359 struct dom_sid_buf buf;
1363 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1364 fsp_fnum_dbg(fsp)));
1367 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1368 return NT_STATUS_INVALID_PARAMETER;
1371 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1373 /* unknown 4 bytes: this is not the length of the sid :-( */
1374 /*unknown = IVAL(pdata,0);*/
1376 if (!sid_parse(_in_data + 4, sid_len, &sid)) {
1377 return NT_STATUS_INVALID_PARAMETER;
1379 DEBUGADD(10, ("for SID: %s\n",
1380 dom_sid_str_buf(&sid, &buf)));
1382 if (!sid_to_uid(&sid, &uid)) {
1383 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1384 dom_sid_str_buf(&sid, &buf),
1385 (unsigned long)sid_len));
1389 /* we can take a look at the find source :-)
1391 * find ./ -uid $uid -name '*' is what we need here
1394 * and send 4bytes len and then NULL terminated unicode strings
1397 * but I don't know how to deal with the paged results
1398 * (maybe we can hang the result anywhere in the fsp struct)
1400 * but I don't know how to deal with the paged results
1401 * (maybe we can hang the result anywhere in the fsp struct)
1403 * we don't send all files at once
1404 * and at the next we should *not* start from the beginning,
1405 * so we have to cache the result
1410 /* this works for now... */
1411 return NT_STATUS_OK;
1414 case FSCTL_QUERY_ALLOCATED_RANGES:
1416 /* FIXME: This is just a dummy reply, telling that all of the
1417 * file is allocated. MKS cp needs that.
1418 * Adding the real allocated ranges via FIEMAP on Linux
1419 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1420 * this FSCTL correct for sparse files.
1422 uint64_t offset, length;
1423 char *out_data_tmp = NULL;
1426 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1428 return NT_STATUS_INVALID_PARAMETER;
1431 if (max_out_len < 16) {
1432 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1434 return NT_STATUS_INVALID_PARAMETER;
1437 offset = BVAL(in_data,0);
1438 length = BVAL(in_data,8);
1440 if (offset + length < offset) {
1441 /* No 64-bit integer wrap. */
1442 return NT_STATUS_INVALID_PARAMETER;
1445 /* Shouldn't this be SMB_VFS_STAT ... ? */
1446 status = vfs_stat_fsp(fsp);
1447 if (!NT_STATUS_IS_OK(status)) {
1452 out_data_tmp = talloc_array(ctx, char, *out_len);
1453 if (out_data_tmp == NULL) {
1454 DEBUG(10, ("unable to allocate memory for response\n"));
1455 return NT_STATUS_NO_MEMORY;
1458 if (offset > fsp->fsp_name->st.st_ex_size ||
1459 fsp->fsp_name->st.st_ex_size == 0 ||
1461 memset(out_data_tmp, 0, *out_len);
1463 uint64_t end = offset + length;
1464 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1465 SBVAL(out_data_tmp, 0, 0);
1466 SBVAL(out_data_tmp, 8, end);
1469 *out_data = out_data_tmp;
1471 return NT_STATUS_OK;
1474 case FSCTL_IS_VOLUME_DIRTY:
1476 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1477 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1479 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1480 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1482 return NT_STATUS_INVALID_PARAMETER;
1487 * Only print once ... unfortunately there could be lots of
1488 * different FSCTLs that are called.
1490 if (!vfswrap_logged_ioctl_message) {
1491 vfswrap_logged_ioctl_message = true;
1492 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1493 __func__, function));
1497 return NT_STATUS_NOT_SUPPORTED;
1500 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
1501 const struct smb_filename *fname,
1502 SMB_STRUCT_STAT *sbuf);
1504 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1505 struct smb_filename *smb_fname,
1510 offline = vfswrap_is_offline(handle, smb_fname, &smb_fname->st);
1512 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1515 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1518 struct vfswrap_get_dos_attributes_state {
1519 struct vfs_aio_state aio_state;
1520 connection_struct *conn;
1521 TALLOC_CTX *mem_ctx;
1522 struct tevent_context *ev;
1523 files_struct *dir_fsp;
1524 struct smb_filename *smb_fname;
1529 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq);
1531 static struct tevent_req *vfswrap_get_dos_attributes_send(
1532 TALLOC_CTX *mem_ctx,
1533 struct tevent_context *ev,
1534 struct vfs_handle_struct *handle,
1535 files_struct *dir_fsp,
1536 struct smb_filename *smb_fname)
1538 struct tevent_req *req = NULL;
1539 struct tevent_req *subreq = NULL;
1540 struct vfswrap_get_dos_attributes_state *state = NULL;
1542 req = tevent_req_create(mem_ctx, &state,
1543 struct vfswrap_get_dos_attributes_state);
1548 *state = (struct vfswrap_get_dos_attributes_state) {
1549 .conn = dir_fsp->conn,
1553 .smb_fname = smb_fname,
1556 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1560 SAMBA_XATTR_DOS_ATTRIB,
1562 if (tevent_req_nomem(subreq, req)) {
1563 return tevent_req_post(req, ev);
1565 tevent_req_set_callback(subreq,
1566 vfswrap_get_dos_attributes_getxattr_done,
1572 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq)
1574 struct tevent_req *req =
1575 tevent_req_callback_data(subreq,
1577 struct vfswrap_get_dos_attributes_state *state =
1578 tevent_req_data(req,
1579 struct vfswrap_get_dos_attributes_state);
1581 DATA_BLOB blob = {0};
1584 xattr_size = SMB_VFS_GETXATTRAT_RECV(subreq,
1588 TALLOC_FREE(subreq);
1589 if (xattr_size == -1) {
1590 status = map_nt_error_from_unix(state->aio_state.error);
1592 if (state->as_root) {
1593 tevent_req_nterror(req, status);
1596 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1597 tevent_req_nterror(req, status);
1601 state->as_root = true;
1604 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1608 SAMBA_XATTR_DOS_ATTRIB,
1611 if (tevent_req_nomem(subreq, req)) {
1614 tevent_req_set_callback(subreq,
1615 vfswrap_get_dos_attributes_getxattr_done,
1620 blob.length = xattr_size;
1622 status = parse_dos_attribute_blob(state->smb_fname,
1625 if (!NT_STATUS_IS_OK(status)) {
1626 tevent_req_nterror(req, status);
1630 tevent_req_done(req);
1634 static NTSTATUS vfswrap_get_dos_attributes_recv(struct tevent_req *req,
1635 struct vfs_aio_state *aio_state,
1638 struct vfswrap_get_dos_attributes_state *state =
1639 tevent_req_data(req,
1640 struct vfswrap_get_dos_attributes_state);
1643 if (tevent_req_is_nterror(req, &status)) {
1644 tevent_req_received(req);
1648 *aio_state = state->aio_state;
1649 *dosmode = state->dosmode;
1650 tevent_req_received(req);
1651 return NT_STATUS_OK;
1654 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1655 struct files_struct *fsp,
1660 offline = vfswrap_is_offline(handle, fsp->fsp_name, &fsp->fsp_name->st);
1662 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1665 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1668 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1669 const struct smb_filename *smb_fname,
1672 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1675 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1676 struct files_struct *fsp,
1679 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1682 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1684 struct vfswrap_offload_read_state {
1688 static struct tevent_req *vfswrap_offload_read_send(
1689 TALLOC_CTX *mem_ctx,
1690 struct tevent_context *ev,
1691 struct vfs_handle_struct *handle,
1692 struct files_struct *fsp,
1698 struct tevent_req *req = NULL;
1699 struct vfswrap_offload_read_state *state = NULL;
1702 req = tevent_req_create(mem_ctx, &state,
1703 struct vfswrap_offload_read_state);
1708 status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1709 &vfswrap_offload_ctx);
1710 if (tevent_req_nterror(req, status)) {
1711 return tevent_req_post(req, ev);
1714 if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1715 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1716 return tevent_req_post(req, ev);
1719 status = vfs_offload_token_create_blob(state, fsp, fsctl,
1721 if (tevent_req_nterror(req, status)) {
1722 return tevent_req_post(req, ev);
1725 status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1727 if (tevent_req_nterror(req, status)) {
1728 return tevent_req_post(req, ev);
1731 tevent_req_done(req);
1732 return tevent_req_post(req, ev);
1735 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
1736 struct vfs_handle_struct *handle,
1737 TALLOC_CTX *mem_ctx,
1740 struct vfswrap_offload_read_state *state = tevent_req_data(
1741 req, struct vfswrap_offload_read_state);
1744 if (tevent_req_is_nterror(req, &status)) {
1745 tevent_req_received(req);
1749 token->length = state->token.length;
1750 token->data = talloc_move(mem_ctx, &state->token.data);
1752 tevent_req_received(req);
1753 return NT_STATUS_OK;
1756 struct vfswrap_offload_write_state {
1758 bool read_lck_locked;
1759 bool write_lck_locked;
1761 struct tevent_context *src_ev;
1762 struct files_struct *src_fsp;
1764 struct tevent_context *dst_ev;
1765 struct files_struct *dst_fsp;
1769 size_t next_io_size;
1772 static void vfswrap_offload_write_cleanup(struct tevent_req *req,
1773 enum tevent_req_state req_state)
1775 struct vfswrap_offload_write_state *state = tevent_req_data(
1776 req, struct vfswrap_offload_write_state);
1779 if (state->dst_fsp == NULL) {
1783 ok = change_to_user_by_fsp(state->dst_fsp);
1785 state->dst_fsp = NULL;
1788 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
1790 static struct tevent_req *vfswrap_offload_write_send(
1791 struct vfs_handle_struct *handle,
1792 TALLOC_CTX *mem_ctx,
1793 struct tevent_context *ev,
1796 off_t transfer_offset,
1797 struct files_struct *dest_fsp,
1801 struct tevent_req *req;
1802 struct vfswrap_offload_write_state *state = NULL;
1803 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
1804 files_struct *src_fsp = NULL;
1808 req = tevent_req_create(mem_ctx, &state,
1809 struct vfswrap_offload_write_state);
1814 *state = (struct vfswrap_offload_write_state) {
1816 .src_off = transfer_offset,
1818 .dst_fsp = dest_fsp,
1819 .dst_off = dest_off,
1821 .remaining = to_copy,
1824 tevent_req_set_cleanup_fn(req, vfswrap_offload_write_cleanup);
1827 case FSCTL_SRV_COPYCHUNK:
1828 case FSCTL_SRV_COPYCHUNK_WRITE:
1831 case FSCTL_OFFLOAD_WRITE:
1832 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
1833 return tevent_req_post(req, ev);
1835 case FSCTL_DUP_EXTENTS_TO_FILE:
1836 DBG_DEBUG("COW clones not supported by vfs_default\n");
1837 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1838 return tevent_req_post(req, ev);
1841 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1842 return tevent_req_post(req, ev);
1846 * From here on we assume a copy-chunk fsctl
1850 tevent_req_done(req);
1851 return tevent_req_post(req, ev);
1854 status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
1856 if (tevent_req_nterror(req, status)) {
1857 return tevent_req_post(req, ev);
1860 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
1862 status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
1863 if (!NT_STATUS_IS_OK(status)) {
1864 tevent_req_nterror(req, status);
1865 return tevent_req_post(req, ev);
1868 ok = change_to_user_by_fsp(src_fsp);
1870 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1871 return tevent_req_post(req, ev);
1874 state->src_ev = src_fsp->conn->sconn->ev_ctx;
1875 state->src_fsp = src_fsp;
1877 state->buf = talloc_array(state, uint8_t, num);
1878 if (tevent_req_nomem(state->buf, req)) {
1879 return tevent_req_post(req, ev);
1882 status = vfs_stat_fsp(src_fsp);
1883 if (tevent_req_nterror(req, status)) {
1884 return tevent_req_post(req, ev);
1887 if (src_fsp->fsp_name->st.st_ex_size < state->src_off + num) {
1889 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1890 * If the SourceOffset or SourceOffset + Length extends beyond
1891 * the end of file, the server SHOULD<240> treat this as a
1892 * STATUS_END_OF_FILE error.
1894 * <240> Section 3.3.5.15.6: Windows servers will return
1895 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1897 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1898 return tevent_req_post(req, ev);
1901 status = vfswrap_offload_write_loop(req);
1902 if (!NT_STATUS_IS_OK(status)) {
1903 tevent_req_nterror(req, status);
1904 return tevent_req_post(req, ev);
1910 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
1912 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
1914 struct vfswrap_offload_write_state *state = tevent_req_data(
1915 req, struct vfswrap_offload_write_state);
1916 struct tevent_req *subreq = NULL;
1917 struct lock_struct read_lck;
1921 * This is called under the context of state->src_fsp.
1924 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
1926 init_strict_lock_struct(state->src_fsp,
1927 state->src_fsp->op->global->open_persistent_id,
1929 state->next_io_size,
1933 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
1937 return NT_STATUS_FILE_LOCK_CONFLICT;
1940 subreq = SMB_VFS_PREAD_SEND(state,
1944 state->next_io_size,
1946 if (subreq == NULL) {
1947 return NT_STATUS_NO_MEMORY;
1949 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
1951 return NT_STATUS_OK;
1954 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
1956 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
1958 struct tevent_req *req = tevent_req_callback_data(
1959 subreq, struct tevent_req);
1960 struct vfswrap_offload_write_state *state = tevent_req_data(
1961 req, struct vfswrap_offload_write_state);
1962 struct vfs_aio_state aio_state;
1963 struct lock_struct write_lck;
1967 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
1968 TALLOC_FREE(subreq);
1970 DBG_ERR("read failed: %s\n", strerror(errno));
1971 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1974 if (nread != state->next_io_size) {
1975 DBG_ERR("Short read, only %zd of %zu\n",
1976 nread, state->next_io_size);
1977 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1981 state->src_off += nread;
1983 ok = change_to_user_by_fsp(state->dst_fsp);
1985 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1989 init_strict_lock_struct(state->dst_fsp,
1990 state->dst_fsp->op->global->open_persistent_id,
1992 state->next_io_size,
1996 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
2000 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
2004 subreq = SMB_VFS_PWRITE_SEND(state,
2008 state->next_io_size,
2010 if (subreq == NULL) {
2011 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2014 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
2017 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
2019 struct tevent_req *req = tevent_req_callback_data(
2020 subreq, struct tevent_req);
2021 struct vfswrap_offload_write_state *state = tevent_req_data(
2022 req, struct vfswrap_offload_write_state);
2023 struct vfs_aio_state aio_state;
2028 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
2029 TALLOC_FREE(subreq);
2030 if (nwritten == -1) {
2031 DBG_ERR("write failed: %s\n", strerror(errno));
2032 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2035 if (nwritten != state->next_io_size) {
2036 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
2037 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2041 state->dst_off += nwritten;
2043 if (state->remaining < nwritten) {
2044 /* Paranoia check */
2045 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2048 state->remaining -= nwritten;
2049 if (state->remaining == 0) {
2050 tevent_req_done(req);
2054 ok = change_to_user_by_fsp(state->src_fsp);
2056 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2060 status = vfswrap_offload_write_loop(req);
2061 if (!NT_STATUS_IS_OK(status)) {
2062 tevent_req_nterror(req, status);
2069 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
2070 struct tevent_req *req,
2073 struct vfswrap_offload_write_state *state = tevent_req_data(
2074 req, struct vfswrap_offload_write_state);
2077 if (tevent_req_is_nterror(req, &status)) {
2078 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
2080 tevent_req_received(req);
2084 *copied = state->to_copy;
2085 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
2086 tevent_req_received(req);
2088 return NT_STATUS_OK;
2091 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
2092 TALLOC_CTX *mem_ctx,
2093 struct files_struct *fsp,
2094 struct smb_filename *smb_fname,
2095 uint16_t *_compression_fmt)
2097 return NT_STATUS_INVALID_DEVICE_REQUEST;
2100 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
2101 TALLOC_CTX *mem_ctx,
2102 struct files_struct *fsp,
2103 uint16_t compression_fmt)
2105 return NT_STATUS_INVALID_DEVICE_REQUEST;
2108 /********************************************************************
2109 Given a stat buffer return the allocated size on disk, taking into
2110 account sparse files.
2111 ********************************************************************/
2112 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
2113 struct files_struct *fsp,
2114 const SMB_STRUCT_STAT *sbuf)
2118 START_PROFILE(syscall_get_alloc_size);
2120 if(S_ISDIR(sbuf->st_ex_mode)) {
2125 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2126 /* The type of st_blocksize is blkcnt_t which *MUST* be
2127 signed (according to POSIX) and can be less than 64-bits.
2128 Ensure when we're converting to 64 bits wide we don't
2130 #if defined(SIZEOF_BLKCNT_T_8)
2131 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2132 #elif defined(SIZEOF_BLKCNT_T_4)
2134 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2135 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2138 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2142 * Some file systems do not allocate a block for very
2143 * small files. But for non-empty file should report a
2147 uint64_t filesize = get_file_size_stat(sbuf);
2149 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2153 result = get_file_size_stat(sbuf);
2156 if (fsp && fsp->initial_allocation_size)
2157 result = MAX(result,fsp->initial_allocation_size);
2159 result = smb_roundup(handle->conn, result);
2162 END_PROFILE(syscall_get_alloc_size);
2166 static int vfswrap_unlink(vfs_handle_struct *handle,
2167 const struct smb_filename *smb_fname)
2171 START_PROFILE(syscall_unlink);
2173 if (smb_fname->stream_name) {
2177 result = unlink(smb_fname->base_name);
2180 END_PROFILE(syscall_unlink);
2184 static int vfswrap_chmod(vfs_handle_struct *handle,
2185 const struct smb_filename *smb_fname,
2190 START_PROFILE(syscall_chmod);
2191 result = chmod(smb_fname->base_name, mode);
2192 END_PROFILE(syscall_chmod);
2196 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2200 START_PROFILE(syscall_fchmod);
2201 #if defined(HAVE_FCHMOD)
2202 result = fchmod(fsp->fh->fd, mode);
2208 END_PROFILE(syscall_fchmod);
2212 static int vfswrap_chown(vfs_handle_struct *handle,
2213 const struct smb_filename *smb_fname,
2219 START_PROFILE(syscall_chown);
2220 result = chown(smb_fname->base_name, uid, gid);
2221 END_PROFILE(syscall_chown);
2225 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2230 START_PROFILE(syscall_fchown);
2231 result = fchown(fsp->fh->fd, uid, gid);
2232 END_PROFILE(syscall_fchown);
2240 static int vfswrap_lchown(vfs_handle_struct *handle,
2241 const struct smb_filename *smb_fname,
2247 START_PROFILE(syscall_lchown);
2248 result = lchown(smb_fname->base_name, uid, gid);
2249 END_PROFILE(syscall_lchown);
2253 static int vfswrap_chdir(vfs_handle_struct *handle,
2254 const struct smb_filename *smb_fname)
2258 START_PROFILE(syscall_chdir);
2259 result = chdir(smb_fname->base_name);
2260 END_PROFILE(syscall_chdir);
2264 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2268 struct smb_filename *smb_fname = NULL;
2270 START_PROFILE(syscall_getwd);
2271 result = sys_getwd();
2272 END_PROFILE(syscall_getwd);
2274 if (result == NULL) {
2277 smb_fname = synthetic_smb_fname(ctx,
2283 * sys_getwd() *always* returns malloced memory.
2284 * We must free here to avoid leaks:
2285 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2291 /*********************************************************************
2292 nsec timestamp resolution call. Convert down to whatever the underlying
2293 system will support.
2294 **********************************************************************/
2296 static int vfswrap_ntimes(vfs_handle_struct *handle,
2297 const struct smb_filename *smb_fname,
2298 struct smb_file_time *ft)
2302 START_PROFILE(syscall_ntimes);
2304 if (smb_fname->stream_name) {
2310 if (null_timespec(ft->atime)) {
2311 ft->atime= smb_fname->st.st_ex_atime;
2314 if (null_timespec(ft->mtime)) {
2315 ft->mtime = smb_fname->st.st_ex_mtime;
2318 if (!null_timespec(ft->create_time)) {
2319 set_create_timespec_ea(handle->conn,
2324 if ((timespec_compare(&ft->atime,
2325 &smb_fname->st.st_ex_atime) == 0) &&
2326 (timespec_compare(&ft->mtime,
2327 &smb_fname->st.st_ex_mtime) == 0)) {
2332 #if defined(HAVE_UTIMENSAT)
2334 struct timespec ts[2];
2337 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2339 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2341 if (!((result == -1) && (errno == ENOSYS))) {
2345 #if defined(HAVE_UTIMES)
2347 struct timeval tv[2];
2348 tv[0] = convert_timespec_to_timeval(ft->atime);
2349 tv[1] = convert_timespec_to_timeval(ft->mtime);
2350 result = utimes(smb_fname->base_name, tv);
2352 result = utimes(smb_fname->base_name, NULL);
2354 if (!((result == -1) && (errno == ENOSYS))) {
2358 #if defined(HAVE_UTIME)
2360 struct utimbuf times;
2361 times.actime = convert_timespec_to_time_t(ft->atime);
2362 times.modtime = convert_timespec_to_time_t(ft->mtime);
2363 result = utime(smb_fname->base_name, ×);
2365 result = utime(smb_fname->base_name, NULL);
2367 if (!((result == -1) && (errno == ENOSYS))) {
2375 END_PROFILE(syscall_ntimes);
2379 /*********************************************************************
2380 A version of ftruncate that will write the space on disk if strict
2382 **********************************************************************/
2384 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2386 off_t space_to_write;
2387 uint64_t space_avail;
2388 uint64_t bsize,dfree,dsize;
2391 SMB_STRUCT_STAT *pst;
2393 status = vfs_stat_fsp(fsp);
2394 if (!NT_STATUS_IS_OK(status)) {
2397 pst = &fsp->fsp_name->st;
2400 if (S_ISFIFO(pst->st_ex_mode))
2404 if (pst->st_ex_size == len)
2407 /* Shrink - just ftruncate. */
2408 if (pst->st_ex_size > len)
2409 return ftruncate(fsp->fh->fd, len);
2411 space_to_write = len - pst->st_ex_size;
2413 /* for allocation try fallocate first. This can fail on some
2414 platforms e.g. when the filesystem doesn't support it and no
2415 emulation is being done by the libc (like on AIX with JFS1). In that
2416 case we do our own emulation. fallocate implementations can
2417 return ENOTSUP or EINVAL in cases like that. */
2418 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2419 if (ret == -1 && errno == ENOSPC) {
2425 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2426 "error %d. Falling back to slow manual allocation\n", errno));
2428 /* available disk space is enough or not? */
2430 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2431 /* space_avail is 1k blocks */
2432 if (space_avail == (uint64_t)-1 ||
2433 ((uint64_t)space_to_write/1024 > space_avail) ) {
2438 /* Write out the real space on disk. */
2439 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2447 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2450 SMB_STRUCT_STAT *pst;
2454 START_PROFILE(syscall_ftruncate);
2456 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2457 result = strict_allocate_ftruncate(handle, fsp, len);
2458 END_PROFILE(syscall_ftruncate);
2462 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2463 ftruncate if the system supports it. Then I discovered that
2464 you can have some filesystems that support ftruncate
2465 expansion and some that don't! On Linux fat can't do
2466 ftruncate extend but ext2 can. */
2468 result = ftruncate(fsp->fh->fd, len);
2470 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2471 extend a file with ftruncate. Provide alternate implementation
2474 /* Do an fstat to see if the file is longer than the requested
2475 size in which case the ftruncate above should have
2476 succeeded or shorter, in which case seek to len - 1 and
2477 write 1 byte of zero */
2478 status = vfs_stat_fsp(fsp);
2479 if (!NT_STATUS_IS_OK(status)) {
2483 /* We need to update the files_struct after successful ftruncate */
2488 pst = &fsp->fsp_name->st;
2491 if (S_ISFIFO(pst->st_ex_mode)) {
2497 if (pst->st_ex_size == len) {
2502 if (pst->st_ex_size > len) {
2503 /* the ftruncate should have worked */
2507 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2515 END_PROFILE(syscall_ftruncate);
2519 static int vfswrap_fallocate(vfs_handle_struct *handle,
2527 START_PROFILE(syscall_fallocate);
2529 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2531 * posix_fallocate returns 0 on success, errno on error
2532 * and doesn't set errno. Make it behave like fallocate()
2533 * which returns -1, and sets errno on failure.
2540 /* sys_fallocate handles filtering of unsupported mode flags */
2541 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2543 END_PROFILE(syscall_fallocate);
2547 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2551 START_PROFILE(syscall_fcntl_lock);
2553 if (fsp->use_ofd_locks) {
2554 op = map_process_lock_to_ofd_lock(op);
2557 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2558 END_PROFILE(syscall_fcntl_lock);
2562 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2563 uint32_t share_mode, uint32_t access_mask)
2565 START_PROFILE(syscall_kernel_flock);
2566 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2567 END_PROFILE(syscall_kernel_flock);
2571 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2576 START_PROFILE(syscall_fcntl_getlock);
2578 if (fsp->use_ofd_locks) {
2579 op = map_process_lock_to_ofd_lock(op);
2582 result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2583 END_PROFILE(syscall_fcntl_getlock);
2587 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2592 START_PROFILE(syscall_linux_setlease);
2594 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2595 result = linux_setlease(fsp->fh->fd, leasetype);
2599 END_PROFILE(syscall_linux_setlease);
2603 static int vfswrap_symlink(vfs_handle_struct *handle,
2604 const char *link_target,
2605 const struct smb_filename *new_smb_fname)
2609 START_PROFILE(syscall_symlink);
2610 result = symlink(link_target, new_smb_fname->base_name);
2611 END_PROFILE(syscall_symlink);
2615 static int vfswrap_readlink(vfs_handle_struct *handle,
2616 const struct smb_filename *smb_fname,
2622 START_PROFILE(syscall_readlink);
2623 result = readlink(smb_fname->base_name, buf, bufsiz);
2624 END_PROFILE(syscall_readlink);
2628 static int vfswrap_link(vfs_handle_struct *handle,
2629 const struct smb_filename *old_smb_fname,
2630 const struct smb_filename *new_smb_fname)
2634 START_PROFILE(syscall_link);
2635 result = link(old_smb_fname->base_name, new_smb_fname->base_name);
2636 END_PROFILE(syscall_link);
2640 static int vfswrap_mknod(vfs_handle_struct *handle,
2641 const struct smb_filename *smb_fname,
2647 START_PROFILE(syscall_mknod);
2648 result = sys_mknod(smb_fname->base_name, mode, dev);
2649 END_PROFILE(syscall_mknod);
2653 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2655 const struct smb_filename *smb_fname)
2658 struct smb_filename *result_fname = NULL;
2660 START_PROFILE(syscall_realpath);
2661 result = sys_realpath(smb_fname->base_name);
2662 END_PROFILE(syscall_realpath);
2664 result_fname = synthetic_smb_fname(ctx, result, NULL, NULL, 0);
2667 return result_fname;
2670 static int vfswrap_chflags(vfs_handle_struct *handle,
2671 const struct smb_filename *smb_fname,
2675 return chflags(smb_fname->base_name, flags);
2682 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2683 const SMB_STRUCT_STAT *sbuf)
2687 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2691 key.devid = sbuf->st_ex_dev;
2692 key.inode = sbuf->st_ex_ino;
2693 /* key.extid is unused by default. */
2698 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2699 struct files_struct *fsp,
2700 const struct smb_filename *smb_fname,
2701 TALLOC_CTX *mem_ctx,
2702 unsigned int *pnum_streams,
2703 struct stream_struct **pstreams)
2705 SMB_STRUCT_STAT sbuf;
2706 struct stream_struct *tmp_streams = NULL;
2709 if ((fsp != NULL) && (fsp->is_directory)) {
2711 * No default streams on directories
2716 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2717 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2720 struct smb_filename smb_fname_cp;
2722 ZERO_STRUCT(smb_fname_cp);
2723 smb_fname_cp.base_name = discard_const_p(char,
2724 smb_fname->base_name);
2725 smb_fname_cp.flags = smb_fname->flags;
2727 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
2728 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2730 ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2732 sbuf = smb_fname_cp.st;
2736 return map_nt_error_from_unix(errno);
2739 if (S_ISDIR(sbuf.st_ex_mode)) {
2743 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2744 (*pnum_streams) + 1);
2745 if (tmp_streams == NULL) {
2746 return NT_STATUS_NO_MEMORY;
2748 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2749 if (tmp_streams[*pnum_streams].name == NULL) {
2750 return NT_STATUS_NO_MEMORY;
2752 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2753 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2756 *pstreams = tmp_streams;
2758 return NT_STATUS_OK;
2761 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2764 TALLOC_CTX *mem_ctx,
2768 * Don't fall back to get_real_filename so callers can differentiate
2769 * between a full directory scan and an actual case-insensitive stat.
2775 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2776 const struct smb_filename *smb_fname)
2778 return handle->conn->connectpath;
2781 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2782 struct byte_range_lock *br_lck,
2783 struct lock_struct *plock,
2786 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2788 /* Note: blr is not used in the default implementation. */
2789 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2792 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2793 struct messaging_context *msg_ctx,
2794 struct byte_range_lock *br_lck,
2795 const struct lock_struct *plock)
2797 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2799 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2802 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2803 struct byte_range_lock *br_lck,
2804 struct lock_struct *plock)
2806 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2808 /* Note: blr is not used in the default implementation. */
2809 return brl_lock_cancel_default(br_lck, plock);
2812 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
2814 struct lock_struct *plock)
2816 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2817 plock->lock_type == WRITE_LOCK);
2819 return strict_lock_check_default(fsp, plock);
2822 /* NT ACL operations. */
2824 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2826 uint32_t security_info,
2827 TALLOC_CTX *mem_ctx,
2828 struct security_descriptor **ppdesc)
2832 START_PROFILE(fget_nt_acl);
2833 result = posix_fget_nt_acl(fsp, security_info,
2835 END_PROFILE(fget_nt_acl);
2839 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2840 const struct smb_filename *smb_fname,
2841 uint32_t security_info,
2842 TALLOC_CTX *mem_ctx,
2843 struct security_descriptor **ppdesc)
2847 START_PROFILE(get_nt_acl);
2848 result = posix_get_nt_acl(handle->conn,
2853 END_PROFILE(get_nt_acl);
2857 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2861 START_PROFILE(fset_nt_acl);
2862 result = set_nt_acl(fsp, security_info_sent, psd);
2863 END_PROFILE(fset_nt_acl);
2867 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2868 struct smb_filename *file,
2869 struct security_acl *sacl,
2870 uint32_t access_requested,
2871 uint32_t access_denied)
2873 return NT_STATUS_OK; /* Nothing to do here ... */
2876 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2877 const struct smb_filename *smb_fname,
2878 SMB_ACL_TYPE_T type,
2879 TALLOC_CTX *mem_ctx)
2881 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
2884 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2886 TALLOC_CTX *mem_ctx)
2888 return sys_acl_get_fd(handle, fsp, mem_ctx);
2891 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
2892 const struct smb_filename *smb_fname,
2893 SMB_ACL_TYPE_T acltype,
2896 return sys_acl_set_file(handle, smb_fname, acltype, theacl);
2899 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2901 return sys_acl_set_fd(handle, fsp, theacl);
2904 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
2905 const struct smb_filename *smb_fname)
2907 return sys_acl_delete_def_file(handle, smb_fname);
2910 /****************************************************************
2911 Extended attribute operations.
2912 *****************************************************************/
2914 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
2915 const struct smb_filename *smb_fname,
2920 return getxattr(smb_fname->base_name, name, value, size);
2923 struct vfswrap_getxattrat_state {
2924 struct tevent_context *ev;
2925 files_struct *dir_fsp;
2926 const struct smb_filename *smb_fname;
2927 struct tevent_req *req;
2930 * The following variables are talloced off "state" which is protected
2931 * by a destructor and thus are guaranteed to be safe to be used in the
2932 * job function in the worker thread.
2935 const char *xattr_name;
2936 uint8_t *xattr_value;
2937 struct security_unix_token *token;
2940 struct vfs_aio_state vfs_aio_state;
2941 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
2944 static int vfswrap_getxattrat_state_destructor(
2945 struct vfswrap_getxattrat_state *state)
2950 static void vfswrap_getxattrat_do_sync(struct tevent_req *req);
2951 static void vfswrap_getxattrat_do_async(void *private_data);
2952 static void vfswrap_getxattrat_done(struct tevent_req *subreq);
2954 static struct tevent_req *vfswrap_getxattrat_send(
2955 TALLOC_CTX *mem_ctx,
2956 struct tevent_context *ev,
2957 struct vfs_handle_struct *handle,
2958 files_struct *dir_fsp,
2959 const struct smb_filename *smb_fname,
2960 const char *xattr_name,
2963 struct tevent_req *req = NULL;
2964 struct tevent_req *subreq = NULL;
2965 struct vfswrap_getxattrat_state *state = NULL;
2966 size_t max_threads = 0;
2967 bool have_per_thread_cwd = false;
2968 bool have_per_thread_creds = false;
2969 bool do_async = false;
2971 req = tevent_req_create(mem_ctx, &state,
2972 struct vfswrap_getxattrat_state);
2976 *state = (struct vfswrap_getxattrat_state) {
2979 .smb_fname = smb_fname,
2983 max_threads = pthreadpool_tevent_max_threads(dir_fsp->conn->sconn->pool);
2984 if (max_threads >= 1) {
2986 * We need a non sync threadpool!
2988 have_per_thread_cwd = per_thread_cwd_supported();
2990 #ifdef HAVE_LINUX_THREAD_CREDENTIALS
2991 have_per_thread_creds = true;
2993 if (have_per_thread_cwd && have_per_thread_creds) {
2997 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat, profile_p,
2998 state->profile_bytes, 0);
3000 if (dir_fsp->fh->fd == -1) {
3001 DBG_ERR("Need a valid directory fd\n");
3002 tevent_req_error(req, EINVAL);
3003 return tevent_req_post(req, ev);
3006 if (alloc_hint > 0) {
3007 state->xattr_value = talloc_zero_array(state,
3010 if (tevent_req_nomem(state->xattr_value, req)) {
3011 return tevent_req_post(req, ev);
3016 vfswrap_getxattrat_do_sync(req);
3017 return tevent_req_post(req, ev);
3021 * Now allocate all parameters from a memory context that won't go away
3022 * no matter what. These paremeters will get used in threads and we
3023 * can't reliably cancel threads, so all buffers passed to the threads
3024 * must not be freed before all referencing threads terminate.
3027 state->name = talloc_strdup(state, smb_fname->base_name);
3028 if (tevent_req_nomem(state->name, req)) {
3029 return tevent_req_post(req, ev);
3032 state->xattr_name = talloc_strdup(state, xattr_name);
3033 if (tevent_req_nomem(state->xattr_name, req)) {
3034 return tevent_req_post(req, ev);
3038 * This is a hot codepath so at first glance one might think we should
3039 * somehow optimize away the token allocation and do a
3040 * talloc_reference() or similar black magic instead. But due to the
3041 * talloc_stackframe pool per SMB2 request this should be a simple copy
3042 * without a malloc in most cases.
3044 if (geteuid() == sec_initial_uid()) {
3045 state->token = root_unix_token(state);
3047 state->token = copy_unix_token(
3049 dir_fsp->conn->session_info->unix_token);
3051 if (tevent_req_nomem(state->token, req)) {
3052 return tevent_req_post(req, ev);
3055 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3057 subreq = pthreadpool_tevent_job_send(
3060 dir_fsp->conn->sconn->pool,
3061 vfswrap_getxattrat_do_async,
3063 if (tevent_req_nomem(subreq, req)) {
3064 return tevent_req_post(req, ev);
3066 tevent_req_set_callback(subreq, vfswrap_getxattrat_done, req);
3068 talloc_set_destructor(state, vfswrap_getxattrat_state_destructor);
3073 static void vfswrap_getxattrat_do_sync(struct tevent_req *req)
3075 struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3076 req, struct vfswrap_getxattrat_state);
3078 char *tofree = NULL;
3079 char pathbuf[PATH_MAX+1];
3083 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
3084 state->smb_fname->base_name,
3089 if (pathlen == -1) {
3090 tevent_req_error(req, ENOMEM);
3094 state->xattr_size = getxattr(path,
3097 talloc_array_length(state->xattr_value));
3099 TALLOC_FREE(tofree);
3100 if (state->xattr_size == -1) {
3101 tevent_req_error(req, err);
3105 tevent_req_done(req);
3109 static void vfswrap_getxattrat_do_async(void *private_data)
3111 struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3112 private_data, struct vfswrap_getxattrat_state);
3113 struct timespec start_time;
3114 struct timespec end_time;
3117 PROFILE_TIMESTAMP(&start_time);
3118 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
3121 * Here we simulate a getxattrat()
3122 * call using fchdir();getxattr()
3125 per_thread_cwd_activate();
3127 /* Become the correct credential on this thread. */
3128 ret = set_thread_credentials(state->token->uid,
3130 (size_t)state->token->ngroups,
3131 state->token->groups);
3133 state->xattr_size = -1;
3134 state->vfs_aio_state.error = errno;
3138 ret = fchdir(state->dir_fsp->fh->fd);
3140 state->xattr_size = -1;
3141 state->vfs_aio_state.error = errno;
3145 state->xattr_size = getxattr(state->name,
3148 talloc_array_length(state->xattr_value));
3149 if (state->xattr_size == -1) {
3150 state->vfs_aio_state.error = errno;
3154 PROFILE_TIMESTAMP(&end_time);
3155 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
3156 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3159 static void vfswrap_getxattrat_done(struct tevent_req *subreq)
3161 struct tevent_req *req = tevent_req_callback_data(
3162 subreq, struct tevent_req);
3163 struct vfswrap_getxattrat_state *state = tevent_req_data(
3164 req, struct vfswrap_getxattrat_state);
3169 * Make sure we run as the user again
3171 ok = change_to_user_by_fsp(state->dir_fsp);
3174 ret = pthreadpool_tevent_job_recv(subreq);
3175 TALLOC_FREE(subreq);
3176 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
3177 talloc_set_destructor(state, NULL);
3179 if (ret != EAGAIN) {
3180 tevent_req_error(req, ret);
3184 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
3185 * means the lower level pthreadpool failed to create a new
3186 * thread. Fallback to sync processing in that case to allow
3187 * some progress for the client.
3189 vfswrap_getxattrat_do_sync(req);
3193 if (state->xattr_size == -1) {
3194 tevent_req_error(req, state->vfs_aio_state.error);
3198 if (state->xattr_value == NULL) {
3200 * The caller only wanted the size.
3202 tevent_req_done(req);
3207 * shrink the buffer to the returned size.
3208 * (can't fail). It means NULL if size is 0.
3210 state->xattr_value = talloc_realloc(state,
3215 tevent_req_done(req);
3218 static ssize_t vfswrap_getxattrat_recv(struct tevent_req *req,
3219 struct vfs_aio_state *aio_state,
3220 TALLOC_CTX *mem_ctx,
3221 uint8_t **xattr_value)
3223 struct vfswrap_getxattrat_state *state = tevent_req_data(
3224 req, struct vfswrap_getxattrat_state);
3227 if (tevent_req_is_unix_error(req, &aio_state->error)) {
3228 tevent_req_received(req);
3232 *aio_state = state->vfs_aio_state;
3233 xattr_size = state->xattr_size;
3234 if (xattr_value != NULL) {
3235 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
3238 tevent_req_received(req);
3242 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
3244 return fgetxattr(fsp->fh->fd, name, value, size);
3247 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
3248 const struct smb_filename *smb_fname,
3252 return listxattr(smb_fname->base_name, list, size);
3255 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
3257 return flistxattr(fsp->fh->fd, list, size);
3260 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
3261 const struct smb_filename *smb_fname,
3264 return removexattr(smb_fname->base_name, name);
3267 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
3269 return fremovexattr(fsp->fh->fd, name);
3272 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
3273 const struct smb_filename *smb_fname,
3279 return setxattr(smb_fname->base_name, name, value, size, flags);
3282 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
3284 return fsetxattr(fsp->fh->fd, name, value, size, flags);
3287 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
3292 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
3293 const struct smb_filename *fname,
3294 SMB_STRUCT_STAT *sbuf)
3298 bool offline = false;
3300 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
3304 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
3305 #if defined(ENOTSUP)
3311 status = get_full_smb_filename(talloc_tos(), fname, &path);
3312 if (!NT_STATUS_IS_OK(status)) {
3313 errno = map_errno_from_nt_status(status);
3317 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
3324 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
3325 struct files_struct *fsp,
3326 TALLOC_CTX *mem_ctx,
3329 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
3332 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
3333 struct files_struct *fsp,
3334 const DATA_BLOB old_cookie,
3335 TALLOC_CTX *mem_ctx,
3336 DATA_BLOB *new_cookie)
3338 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
3342 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
3343 struct smb_request *smb1req,
3344 struct smbXsrv_open *op,
3345 const DATA_BLOB old_cookie,
3346 TALLOC_CTX *mem_ctx,
3347 struct files_struct **fsp,
3348 DATA_BLOB *new_cookie)
3350 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
3351 old_cookie, mem_ctx,
3355 static struct vfs_fn_pointers vfs_default_fns = {
3356 /* Disk operations */
3358 .connect_fn = vfswrap_connect,
3359 .disconnect_fn = vfswrap_disconnect,
3360 .disk_free_fn = vfswrap_disk_free,
3361 .get_quota_fn = vfswrap_get_quota,
3362 .set_quota_fn = vfswrap_set_quota,
3363 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3364 .statvfs_fn = vfswrap_statvfs,
3365 .fs_capabilities_fn = vfswrap_fs_capabilities,
3366 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3367 .snap_check_path_fn = vfswrap_snap_check_path,
3368 .snap_create_fn = vfswrap_snap_create,
3369 .snap_delete_fn = vfswrap_snap_delete,
3371 /* Directory operations */
3373 .opendir_fn = vfswrap_opendir,
3374 .fdopendir_fn = vfswrap_fdopendir,
3375 .readdir_fn = vfswrap_readdir,
3376 .readdir_attr_fn = vfswrap_readdir_attr,
3377 .seekdir_fn = vfswrap_seekdir,
3378 .telldir_fn = vfswrap_telldir,
3379 .rewind_dir_fn = vfswrap_rewinddir,
3380 .mkdir_fn = vfswrap_mkdir,
3381 .rmdir_fn = vfswrap_rmdir,
3382 .closedir_fn = vfswrap_closedir,
3384 /* File operations */
3386 .open_fn = vfswrap_open,
3387 .create_file_fn = vfswrap_create_file,
3388 .close_fn = vfswrap_close,
3389 .pread_fn = vfswrap_pread,
3390 .pread_send_fn = vfswrap_pread_send,
3391 .pread_recv_fn = vfswrap_pread_recv,
3392 .pwrite_fn = vfswrap_pwrite,
3393 .pwrite_send_fn = vfswrap_pwrite_send,
3394 .pwrite_recv_fn = vfswrap_pwrite_recv,
3395 .lseek_fn = vfswrap_lseek,
3396 .sendfile_fn = vfswrap_sendfile,
3397 .recvfile_fn = vfswrap_recvfile,
3398 .rename_fn = vfswrap_rename,
3399 .fsync_send_fn = vfswrap_fsync_send,
3400 .fsync_recv_fn = vfswrap_fsync_recv,
3401 .stat_fn = vfswrap_stat,
3402 .fstat_fn = vfswrap_fstat,
3403 .lstat_fn = vfswrap_lstat,
3404 .get_alloc_size_fn = vfswrap_get_alloc_size,
3405 .unlink_fn = vfswrap_unlink,
3406 .chmod_fn = vfswrap_chmod,
3407 .fchmod_fn = vfswrap_fchmod,
3408 .chown_fn = vfswrap_chown,
3409 .fchown_fn = vfswrap_fchown,
3410 .lchown_fn = vfswrap_lchown,
3411 .chdir_fn = vfswrap_chdir,
3412 .getwd_fn = vfswrap_getwd,
3413 .ntimes_fn = vfswrap_ntimes,
3414 .ftruncate_fn = vfswrap_ftruncate,
3415 .fallocate_fn = vfswrap_fallocate,
3416 .lock_fn = vfswrap_lock,
3417 .kernel_flock_fn = vfswrap_kernel_flock,
3418 .linux_setlease_fn = vfswrap_linux_setlease,
3419 .getlock_fn = vfswrap_getlock,
3420 .symlink_fn = vfswrap_symlink,
3421 .readlink_fn = vfswrap_readlink,
3422 .link_fn = vfswrap_link,
3423 .mknod_fn = vfswrap_mknod,
3424 .realpath_fn = vfswrap_realpath,
3425 .chflags_fn = vfswrap_chflags,
3426 .file_id_create_fn = vfswrap_file_id_create,
3427 .streaminfo_fn = vfswrap_streaminfo,
3428 .get_real_filename_fn = vfswrap_get_real_filename,
3429 .connectpath_fn = vfswrap_connectpath,
3430 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
3431 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3432 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
3433 .strict_lock_check_fn = vfswrap_strict_lock_check,
3434 .translate_name_fn = vfswrap_translate_name,
3435 .fsctl_fn = vfswrap_fsctl,
3436 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
3437 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
3438 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
3439 .get_dos_attributes_send_fn = vfswrap_get_dos_attributes_send,
3440 .get_dos_attributes_recv_fn = vfswrap_get_dos_attributes_recv,
3441 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
3442 .offload_read_send_fn = vfswrap_offload_read_send,
3443 .offload_read_recv_fn = vfswrap_offload_read_recv,
3444 .offload_write_send_fn = vfswrap_offload_write_send,
3445 .offload_write_recv_fn = vfswrap_offload_write_recv,
3446 .get_compression_fn = vfswrap_get_compression,
3447 .set_compression_fn = vfswrap_set_compression,
3449 /* NT ACL operations. */
3451 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
3452 .get_nt_acl_fn = vfswrap_get_nt_acl,
3453 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
3454 .audit_file_fn = vfswrap_audit_file,
3456 /* POSIX ACL operations. */
3458 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
3459 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3460 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
3461 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3462 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
3463 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3464 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
3466 /* EA operations. */
3467 .getxattr_fn = vfswrap_getxattr,
3468 .getxattrat_send_fn = vfswrap_getxattrat_send,
3469 .getxattrat_recv_fn = vfswrap_getxattrat_recv,
3470 .fgetxattr_fn = vfswrap_fgetxattr,
3471 .listxattr_fn = vfswrap_listxattr,
3472 .flistxattr_fn = vfswrap_flistxattr,
3473 .removexattr_fn = vfswrap_removexattr,
3474 .fremovexattr_fn = vfswrap_fremovexattr,
3475 .setxattr_fn = vfswrap_setxattr,
3476 .fsetxattr_fn = vfswrap_fsetxattr,
3478 /* aio operations */
3479 .aio_force_fn = vfswrap_aio_force,
3481 /* durable handle operations */
3482 .durable_cookie_fn = vfswrap_durable_cookie,
3483 .durable_disconnect_fn = vfswrap_durable_disconnect,
3484 .durable_reconnect_fn = vfswrap_durable_reconnect,
3488 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3491 * Here we need to implement every call!
3493 * As this is the end of the vfs module chain.
3495 smb_vfs_assert_all_fns(&vfs_default_fns, DEFAULT_VFS_MODULE_NAME);
3496 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3497 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);