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"
38 #include "util_reparse.h"
39 #include "lib/util/string_wrappers.h"
42 #define DBGC_CLASS DBGC_VFS
44 /* Check for NULL pointer parameters in vfswrap_* functions */
46 /* We don't want to have NULL function pointers lying around. Someone
47 is sure to try and execute them. These stubs are used to prevent
50 static int vfswrap_connect(vfs_handle_struct *handle, const char *service, const char *user)
52 handle->conn->have_proc_fds = sys_have_proc_fds();
53 return 0; /* Return >= 0 for success */
56 static void vfswrap_disconnect(vfs_handle_struct *handle)
62 static uint64_t vfswrap_disk_free(vfs_handle_struct *handle,
63 const struct smb_filename *smb_fname,
68 if (sys_fsusage(smb_fname->base_name, dfree, dsize) != 0) {
76 static int vfswrap_get_quota(struct vfs_handle_struct *handle,
77 const struct smb_filename *smb_fname,
78 enum SMB_QUOTA_TYPE qtype,
82 #ifdef HAVE_SYS_QUOTAS
85 START_PROFILE(syscall_get_quota);
86 result = sys_get_quota(smb_fname->base_name, qtype, id, qt);
87 END_PROFILE(syscall_get_quota);
95 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
97 #ifdef HAVE_SYS_QUOTAS
100 START_PROFILE(syscall_set_quota);
101 result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
102 END_PROFILE(syscall_set_quota);
110 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
111 struct files_struct *fsp,
112 struct shadow_copy_data *shadow_copy_data,
116 return -1; /* Not implemented. */
119 static int vfswrap_statvfs(struct vfs_handle_struct *handle,
120 const struct smb_filename *smb_fname,
121 vfs_statvfs_struct *statbuf)
123 return sys_statvfs(smb_fname->base_name, statbuf);
126 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
127 enum timestamp_set_resolution *p_ts_res)
129 const struct loadparm_substitution *lp_sub =
130 loadparm_s3_global_substitution();
131 connection_struct *conn = handle->conn;
132 uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
133 struct smb_filename *smb_fname_cpath = NULL;
134 struct vfs_statvfs_struct statbuf;
137 smb_fname_cpath = synthetic_smb_fname(talloc_tos(),
143 if (smb_fname_cpath == NULL) {
147 ZERO_STRUCT(statbuf);
148 ret = SMB_VFS_STATVFS(conn, smb_fname_cpath, &statbuf);
150 caps = statbuf.FsCapabilities;
153 *p_ts_res = TIMESTAMP_SET_SECONDS;
155 /* Work out what timestamp resolution we can
156 * use when setting a timestamp. */
158 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
160 TALLOC_FREE(smb_fname_cpath);
164 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
165 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
166 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
167 /* If any of the normal UNIX directory timestamps
168 * have a non-zero tv_nsec component assume
169 * we might be able to set sub-second timestamps.
170 * See what filetime set primitives we have.
172 #if defined(HAVE_UTIMENSAT)
173 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
174 #elif defined(HAVE_UTIMES)
175 /* utimes allows msec timestamps to be set. */
176 *p_ts_res = TIMESTAMP_SET_MSEC;
177 #elif defined(HAVE_UTIME)
178 /* utime only allows sec timestamps to be set. */
179 *p_ts_res = TIMESTAMP_SET_SECONDS;
182 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
184 "available on share %s, directory %s\n",
185 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
186 lp_servicename(talloc_tos(), lp_sub, conn->params->service),
187 conn->connectpath ));
189 TALLOC_FREE(smb_fname_cpath);
193 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
194 struct dfs_GetDFSReferral *r)
196 struct junction_map *junction = NULL;
198 bool self_referral = false;
199 char *pathnamep = NULL;
200 char *local_dfs_path = NULL;
203 uint16_t max_referral_level = r->in.req.max_referral_level;
206 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
209 /* get the junction entry */
210 if (r->in.req.servername == NULL) {
211 return NT_STATUS_NOT_FOUND;
215 * Trim pathname sent by client so it begins with only one backslash.
216 * Two backslashes confuse some dfs clients
219 local_dfs_path = talloc_strdup(r, r->in.req.servername);
220 if (local_dfs_path == NULL) {
221 return NT_STATUS_NO_MEMORY;
223 pathnamep = local_dfs_path;
224 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
225 IS_DIRECTORY_SEP(pathnamep[1])) {
229 junction = talloc_zero(r, struct junction_map);
230 if (junction == NULL) {
231 return NT_STATUS_NO_MEMORY;
234 /* The following call can change cwd. */
235 status = get_referred_path(r,
236 handle->conn->session_info,
238 handle->conn->sconn->remote_address,
239 handle->conn->sconn->local_address,
240 !handle->conn->sconn->using_smb2,
241 junction, &consumedcnt, &self_referral);
242 if (!NT_STATUS_IS_OK(status)) {
243 struct smb_filename connectpath_fname = {
244 .base_name = handle->conn->connectpath
246 vfs_ChDir(handle->conn, &connectpath_fname);
250 struct smb_filename connectpath_fname = {
251 .base_name = handle->conn->connectpath
253 vfs_ChDir(handle->conn, &connectpath_fname);
256 if (!self_referral) {
257 pathnamep[consumedcnt] = '\0';
260 dbgtext("Path %s to alternate path(s):",
262 for (i=0; i < junction->referral_count; i++) {
264 junction->referral_list[i].alternate_path);
270 if (r->in.req.max_referral_level <= 2) {
271 max_referral_level = 2;
273 if (r->in.req.max_referral_level >= 3) {
274 max_referral_level = 3;
277 r->out.resp = talloc_zero(r, struct dfs_referral_resp);
278 if (r->out.resp == NULL) {
279 return NT_STATUS_NO_MEMORY;
282 r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
283 r->out.resp->nb_referrals = junction->referral_count;
285 r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
287 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
290 r->out.resp->referral_entries = talloc_zero_array(r,
291 struct dfs_referral_type,
292 r->out.resp->nb_referrals);
293 if (r->out.resp->referral_entries == NULL) {
294 return NT_STATUS_NO_MEMORY;
297 switch (max_referral_level) {
299 for(i=0; i < junction->referral_count; i++) {
300 struct referral *ref = &junction->referral_list[i];
301 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
302 struct dfs_referral_type *t =
303 &r->out.resp->referral_entries[i];
304 struct dfs_referral_v2 *v2 = &t->referral.v2;
307 v2->size = VERSION2_REFERRAL_SIZE;
309 v2->server_type = DFS_SERVER_ROOT;
311 v2->server_type = DFS_SERVER_NON_ROOT;
314 v2->proximity = ref->proximity;
316 v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
317 if (v2->DFS_path == NULL) {
318 return NT_STATUS_NO_MEMORY;
320 v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
321 if (v2->DFS_alt_path == NULL) {
322 return NT_STATUS_NO_MEMORY;
324 v2->netw_address = talloc_strdup(mem_ctx,
325 ref->alternate_path);
326 if (v2->netw_address == NULL) {
327 return NT_STATUS_NO_MEMORY;
333 for(i=0; i < junction->referral_count; i++) {
334 struct referral *ref = &junction->referral_list[i];
335 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
336 struct dfs_referral_type *t =
337 &r->out.resp->referral_entries[i];
338 struct dfs_referral_v3 *v3 = &t->referral.v3;
339 struct dfs_normal_referral *r1 = &v3->referrals.r1;
342 v3->size = VERSION3_REFERRAL_SIZE;
344 v3->server_type = DFS_SERVER_ROOT;
346 v3->server_type = DFS_SERVER_NON_ROOT;
350 r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
351 if (r1->DFS_path == NULL) {
352 return NT_STATUS_NO_MEMORY;
354 r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
355 if (r1->DFS_alt_path == NULL) {
356 return NT_STATUS_NO_MEMORY;
358 r1->netw_address = talloc_strdup(mem_ctx,
359 ref->alternate_path);
360 if (r1->netw_address == NULL) {
361 return NT_STATUS_NO_MEMORY;
366 DEBUG(0,("Invalid dfs referral version: %d\n",
367 max_referral_level));
368 return NT_STATUS_INVALID_LEVEL;
372 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
378 static NTSTATUS vfswrap_create_dfs_pathat(struct vfs_handle_struct *handle,
379 struct files_struct *dirfsp,
380 const struct smb_filename *smb_fname,
381 const struct referral *reflist,
382 size_t referral_count)
384 TALLOC_CTX *frame = talloc_stackframe();
385 NTSTATUS status = NT_STATUS_NO_MEMORY;
387 char *msdfs_link = NULL;
389 /* Form the msdfs_link contents */
390 msdfs_link = msdfs_link_string(frame,
393 if (msdfs_link == NULL) {
397 ret = symlinkat(msdfs_link,
398 fsp_get_pathref_fd(dirfsp),
399 smb_fname->base_name);
401 status = NT_STATUS_OK;
403 status = map_nt_error_from_unix(errno);
413 * Read and return the contents of a DFS redirect given a
414 * pathname. A caller can pass in NULL for ppreflist and
415 * preferral_count but still determine if this was a
416 * DFS redirect point by getting NT_STATUS_OK back
417 * without incurring the overhead of reading and parsing
418 * the referral contents.
421 static NTSTATUS vfswrap_read_dfs_pathat(struct vfs_handle_struct *handle,
423 struct files_struct *dirfsp,
424 struct smb_filename *smb_fname,
425 struct referral **ppreflist,
426 size_t *preferral_count)
428 NTSTATUS status = NT_STATUS_NO_MEMORY;
430 char *link_target = NULL;
433 #if defined(HAVE_BROKEN_READLINK)
434 char link_target_buf[PATH_MAX];
436 char link_target_buf[7];
440 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
442 if (is_named_stream(smb_fname)) {
443 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
447 if (ppreflist == NULL && preferral_count == NULL) {
449 * We're only checking if this is a DFS
450 * redirect. We don't need to return data.
452 bufsize = sizeof(link_target_buf);
453 link_target = link_target_buf;
456 link_target = talloc_array(mem_ctx, char, bufsize);
462 referral_len = readlinkat(fsp_get_io_fd(dirfsp),
463 smb_fname->base_name,
466 if (referral_len == -1) {
467 if (errno == EINVAL) {
469 * If the path isn't a link, readlinkat
470 * returns EINVAL. Allow the caller to
473 DBG_INFO("%s is not a link.\n", smb_fname->base_name);
474 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
476 status = map_nt_error_from_unix(errno);
477 if (errno == ENOENT) {
478 DBG_NOTICE("Error reading "
479 "msdfs link %s: %s\n",
480 smb_fname->base_name,
483 DBG_ERR("Error reading "
484 "msdfs link %s: %s\n",
485 smb_fname->base_name,
491 link_target[referral_len] = '\0';
493 DBG_INFO("%s -> %s\n",
494 smb_fname->base_name,
497 if (!strnequal(link_target, "msdfs:", 6)) {
498 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
502 ret = sys_lstat(smb_fname->base_name,
504 lp_fake_directory_create_times(SNUM(handle->conn)));
506 status = map_nt_error_from_unix(errno);
510 if (ppreflist == NULL && preferral_count == NULL) {
511 /* Early return for checking if this is a DFS link. */
515 ok = parse_msdfs_symlink(mem_ctx,
516 lp_msdfs_shuffle_referrals(SNUM(handle->conn)),
522 status = NT_STATUS_OK;
524 status = NT_STATUS_NO_MEMORY;
529 if (link_target != link_target_buf) {
530 TALLOC_FREE(link_target);
535 static NTSTATUS vfswrap_snap_check_path(struct vfs_handle_struct *handle,
537 const char *service_path,
540 return NT_STATUS_NOT_SUPPORTED;
543 static NTSTATUS vfswrap_snap_create(struct vfs_handle_struct *handle,
545 const char *base_volume,
551 return NT_STATUS_NOT_SUPPORTED;
554 static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle,
559 return NT_STATUS_NOT_SUPPORTED;
562 /* Directory operations */
564 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
571 START_PROFILE(syscall_fdopendir);
572 result = sys_fdopendir(fsp_get_io_fd(fsp));
573 END_PROFILE(syscall_fdopendir);
578 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
579 struct files_struct *dirfsp,
581 SMB_STRUCT_STAT *sbuf)
583 struct dirent *result;
584 bool do_stat = false;
585 bool fake_ctime = lp_fake_directory_create_times(SNUM(handle->conn));
586 int flags = AT_SYMLINK_NOFOLLOW;
590 START_PROFILE(syscall_readdir);
592 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
596 result = readdir(dirp);
597 END_PROFILE(syscall_readdir);
602 if (result == NULL) {
607 * Default Posix readdir() does not give us stat info.
608 * Set to invalid to indicate we didn't return this info.
610 SET_STAT_INVALID(*sbuf);
612 /* See if we can efficiently return this. */
617 ret = fstatat(dirfd(dirp),
626 * As this is an optimization, ignore it if we stat'ed a
627 * symlink for non-POSIX context. Make the caller do it again
628 * as we don't know if they wanted the link info, or its
631 if (S_ISLNK(st.st_mode) &&
632 !(dirfsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH))
636 init_stat_ex_from_stat(sbuf, &st, fake_ctime);
641 static NTSTATUS vfswrap_freaddir_attr(struct vfs_handle_struct *handle,
642 struct files_struct *fsp,
644 struct readdir_attr_data **attr_data)
646 return NT_STATUS_NOT_SUPPORTED;
649 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
651 START_PROFILE(syscall_seekdir);
652 seekdir(dirp, offset);
653 END_PROFILE(syscall_seekdir);
656 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
659 START_PROFILE(syscall_telldir);
660 result = telldir(dirp);
661 END_PROFILE(syscall_telldir);
665 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
667 START_PROFILE(syscall_rewinddir);
669 END_PROFILE(syscall_rewinddir);
672 static int vfswrap_mkdirat(vfs_handle_struct *handle,
673 struct files_struct *dirfsp,
674 const struct smb_filename *smb_fname,
679 START_PROFILE(syscall_mkdirat);
681 result = mkdirat(fsp_get_pathref_fd(dirfsp), smb_fname->base_name, mode);
683 END_PROFILE(syscall_mkdirat);
687 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
691 START_PROFILE(syscall_closedir);
692 result = closedir(dirp);
693 END_PROFILE(syscall_closedir);
697 /* File operations */
699 static int vfswrap_openat(vfs_handle_struct *handle,
700 const struct files_struct *dirfsp,
701 const struct smb_filename *smb_fname,
706 bool have_opath = false;
707 bool became_root = false;
710 START_PROFILE(syscall_openat);
712 if (is_named_stream(smb_fname)) {
720 if (fsp->fsp_flags.is_pathref) {
725 if (fsp->fsp_flags.is_pathref && !have_opath) {
730 result = openat(fsp_get_pathref_fd(dirfsp),
731 smb_fname->base_name,
739 fsp->fsp_flags.have_proc_fds = fsp->conn->have_proc_fds;
742 END_PROFILE(syscall_openat);
745 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
746 struct smb_request *req,
747 struct smb_filename *smb_fname,
748 uint32_t access_mask,
749 uint32_t share_access,
750 uint32_t create_disposition,
751 uint32_t create_options,
752 uint32_t file_attributes,
753 uint32_t oplock_request,
754 const struct smb2_lease *lease,
755 uint64_t allocation_size,
756 uint32_t private_flags,
757 struct security_descriptor *sd,
758 struct ea_list *ea_list,
759 files_struct **result,
761 const struct smb2_create_blobs *in_context_blobs,
762 struct smb2_create_blobs *out_context_blobs)
764 return create_file_default(handle->conn, req, smb_fname,
765 access_mask, share_access,
766 create_disposition, create_options,
767 file_attributes, oplock_request, lease,
768 allocation_size, private_flags,
770 pinfo, in_context_blobs, out_context_blobs);
773 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
777 START_PROFILE(syscall_close);
778 result = fd_close_posix(fsp);
779 END_PROFILE(syscall_close);
783 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
784 size_t n, off_t offset)
788 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
789 START_PROFILE_BYTES(syscall_pread, n);
790 result = sys_pread_full(fsp_get_io_fd(fsp), data, n, offset);
791 END_PROFILE_BYTES(syscall_pread);
793 if (result == -1 && errno == ESPIPE) {
794 /* Maintain the fiction that pipes can be seeked (sought?) on. */
795 result = sys_read(fsp_get_io_fd(fsp), data, n);
796 fh_set_pos(fsp->fh, 0);
799 #else /* HAVE_PREAD */
802 #endif /* HAVE_PREAD */
807 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
808 size_t n, off_t offset)
812 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
813 START_PROFILE_BYTES(syscall_pwrite, n);
814 result = sys_pwrite_full(fsp_get_io_fd(fsp), data, n, offset);
815 END_PROFILE_BYTES(syscall_pwrite);
817 if (result == -1 && errno == ESPIPE) {
818 /* Maintain the fiction that pipes can be sought on. */
819 result = sys_write(fsp_get_io_fd(fsp), data, n);
822 #else /* HAVE_PWRITE */
825 #endif /* HAVE_PWRITE */
830 struct vfswrap_pread_state {
837 struct vfs_aio_state vfs_aio_state;
838 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
841 static void vfs_pread_do(void *private_data);
842 static void vfs_pread_done(struct tevent_req *subreq);
843 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state);
845 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
847 struct tevent_context *ev,
848 struct files_struct *fsp,
850 size_t n, off_t offset)
852 struct tevent_req *req, *subreq;
853 struct vfswrap_pread_state *state;
855 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
861 state->fd = fsp_get_io_fd(fsp);
864 state->offset = offset;
866 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
867 state->profile_bytes, n);
868 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
870 subreq = pthreadpool_tevent_job_send(
871 state, ev, handle->conn->sconn->pool,
872 vfs_pread_do, state);
873 if (tevent_req_nomem(subreq, req)) {
874 return tevent_req_post(req, ev);
876 tevent_req_set_callback(subreq, vfs_pread_done, req);
878 talloc_set_destructor(state, vfs_pread_state_destructor);
883 static void vfs_pread_do(void *private_data)
885 struct vfswrap_pread_state *state = talloc_get_type_abort(
886 private_data, struct vfswrap_pread_state);
887 struct timespec start_time;
888 struct timespec end_time;
890 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
892 PROFILE_TIMESTAMP(&start_time);
894 state->ret = sys_pread_full(state->fd,
899 if (state->ret == -1) {
900 state->vfs_aio_state.error = errno;
903 PROFILE_TIMESTAMP(&end_time);
905 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
907 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
910 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state)
915 static void vfs_pread_done(struct tevent_req *subreq)
917 struct tevent_req *req = tevent_req_callback_data(
918 subreq, struct tevent_req);
919 struct vfswrap_pread_state *state = tevent_req_data(
920 req, struct vfswrap_pread_state);
923 ret = pthreadpool_tevent_job_recv(subreq);
925 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
926 talloc_set_destructor(state, NULL);
929 tevent_req_error(req, ret);
933 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
934 * means the lower level pthreadpool failed to create a new
935 * thread. Fallback to sync processing in that case to allow
936 * some progress for the client.
941 tevent_req_done(req);
944 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
945 struct vfs_aio_state *vfs_aio_state)
947 struct vfswrap_pread_state *state = tevent_req_data(
948 req, struct vfswrap_pread_state);
950 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
954 *vfs_aio_state = state->vfs_aio_state;
958 struct vfswrap_pwrite_state {
965 struct vfs_aio_state vfs_aio_state;
966 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
969 static void vfs_pwrite_do(void *private_data);
970 static void vfs_pwrite_done(struct tevent_req *subreq);
971 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state);
973 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
975 struct tevent_context *ev,
976 struct files_struct *fsp,
978 size_t n, off_t offset)
980 struct tevent_req *req, *subreq;
981 struct vfswrap_pwrite_state *state;
983 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
989 state->fd = fsp_get_io_fd(fsp);
992 state->offset = offset;
994 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
995 state->profile_bytes, n);
996 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
998 subreq = pthreadpool_tevent_job_send(
999 state, ev, handle->conn->sconn->pool,
1000 vfs_pwrite_do, state);
1001 if (tevent_req_nomem(subreq, req)) {
1002 return tevent_req_post(req, ev);
1004 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
1006 talloc_set_destructor(state, vfs_pwrite_state_destructor);
1011 static void vfs_pwrite_do(void *private_data)
1013 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
1014 private_data, struct vfswrap_pwrite_state);
1015 struct timespec start_time;
1016 struct timespec end_time;
1018 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
1020 PROFILE_TIMESTAMP(&start_time);
1022 state->ret = sys_pwrite_full(state->fd,
1027 if (state->ret == -1) {
1028 state->vfs_aio_state.error = errno;
1031 PROFILE_TIMESTAMP(&end_time);
1033 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1035 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1038 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state)
1043 static void vfs_pwrite_done(struct tevent_req *subreq)
1045 struct tevent_req *req = tevent_req_callback_data(
1046 subreq, struct tevent_req);
1047 struct vfswrap_pwrite_state *state = tevent_req_data(
1048 req, struct vfswrap_pwrite_state);
1051 ret = pthreadpool_tevent_job_recv(subreq);
1052 TALLOC_FREE(subreq);
1053 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1054 talloc_set_destructor(state, NULL);
1056 if (ret != EAGAIN) {
1057 tevent_req_error(req, ret);
1061 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1062 * means the lower level pthreadpool failed to create a new
1063 * thread. Fallback to sync processing in that case to allow
1064 * some progress for the client.
1066 vfs_pwrite_do(state);
1069 tevent_req_done(req);
1072 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
1073 struct vfs_aio_state *vfs_aio_state)
1075 struct vfswrap_pwrite_state *state = tevent_req_data(
1076 req, struct vfswrap_pwrite_state);
1078 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1082 *vfs_aio_state = state->vfs_aio_state;
1086 struct vfswrap_fsync_state {
1090 struct vfs_aio_state vfs_aio_state;
1091 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
1094 static void vfs_fsync_do(void *private_data);
1095 static void vfs_fsync_done(struct tevent_req *subreq);
1096 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state);
1098 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
1099 TALLOC_CTX *mem_ctx,
1100 struct tevent_context *ev,
1101 struct files_struct *fsp)
1103 struct tevent_req *req, *subreq;
1104 struct vfswrap_fsync_state *state;
1106 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
1112 state->fd = fsp_get_io_fd(fsp);
1114 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_fsync, profile_p,
1115 state->profile_bytes, 0);
1116 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1118 subreq = pthreadpool_tevent_job_send(
1119 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
1120 if (tevent_req_nomem(subreq, req)) {
1121 return tevent_req_post(req, ev);
1123 tevent_req_set_callback(subreq, vfs_fsync_done, req);
1125 talloc_set_destructor(state, vfs_fsync_state_destructor);
1130 static void vfs_fsync_do(void *private_data)
1132 struct vfswrap_fsync_state *state = talloc_get_type_abort(
1133 private_data, struct vfswrap_fsync_state);
1134 struct timespec start_time;
1135 struct timespec end_time;
1137 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
1139 PROFILE_TIMESTAMP(&start_time);
1142 state->ret = fsync(state->fd);
1143 } while ((state->ret == -1) && (errno == EINTR));
1145 if (state->ret == -1) {
1146 state->vfs_aio_state.error = errno;
1149 PROFILE_TIMESTAMP(&end_time);
1151 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1153 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1156 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state)
1161 static void vfs_fsync_done(struct tevent_req *subreq)
1163 struct tevent_req *req = tevent_req_callback_data(
1164 subreq, struct tevent_req);
1165 struct vfswrap_fsync_state *state = tevent_req_data(
1166 req, struct vfswrap_fsync_state);
1169 ret = pthreadpool_tevent_job_recv(subreq);
1170 TALLOC_FREE(subreq);
1171 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1172 talloc_set_destructor(state, NULL);
1174 if (ret != EAGAIN) {
1175 tevent_req_error(req, ret);
1179 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1180 * means the lower level pthreadpool failed to create a new
1181 * thread. Fallback to sync processing in that case to allow
1182 * some progress for the client.
1184 vfs_fsync_do(state);
1187 tevent_req_done(req);
1190 static int vfswrap_fsync_recv(struct tevent_req *req,
1191 struct vfs_aio_state *vfs_aio_state)
1193 struct vfswrap_fsync_state *state = tevent_req_data(
1194 req, struct vfswrap_fsync_state);
1196 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1200 *vfs_aio_state = state->vfs_aio_state;
1204 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1208 START_PROFILE(syscall_lseek);
1210 result = lseek(fsp_get_io_fd(fsp), offset, whence);
1212 * We want to maintain the fiction that we can seek
1213 * on a fifo for file system purposes. This allows
1214 * people to set up UNIX fifo's that feed data to Windows
1215 * applications. JRA.
1218 if((result == -1) && (errno == ESPIPE)) {
1223 END_PROFILE(syscall_lseek);
1227 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1228 off_t offset, size_t n)
1232 START_PROFILE_BYTES(syscall_sendfile, n);
1233 result = sys_sendfile(tofd, fsp_get_io_fd(fromfsp), hdr, offset, n);
1234 END_PROFILE_BYTES(syscall_sendfile);
1238 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1240 files_struct *tofsp,
1246 START_PROFILE_BYTES(syscall_recvfile, n);
1247 result = sys_recvfile(fromfd, fsp_get_io_fd(tofsp), offset, n);
1248 END_PROFILE_BYTES(syscall_recvfile);
1252 static int vfswrap_renameat(vfs_handle_struct *handle,
1253 files_struct *srcfsp,
1254 const struct smb_filename *smb_fname_src,
1255 files_struct *dstfsp,
1256 const struct smb_filename *smb_fname_dst)
1260 START_PROFILE(syscall_renameat);
1262 if (is_named_stream(smb_fname_src) || is_named_stream(smb_fname_dst)) {
1267 result = renameat(fsp_get_pathref_fd(srcfsp),
1268 smb_fname_src->base_name,
1269 fsp_get_pathref_fd(dstfsp),
1270 smb_fname_dst->base_name);
1273 END_PROFILE(syscall_renameat);
1277 static int vfswrap_stat(vfs_handle_struct *handle,
1278 struct smb_filename *smb_fname)
1282 START_PROFILE(syscall_stat);
1284 if (is_named_stream(smb_fname)) {
1289 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1290 lp_fake_directory_create_times(SNUM(handle->conn)));
1292 END_PROFILE(syscall_stat);
1296 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1300 START_PROFILE(syscall_fstat);
1301 result = sys_fstat(fsp_get_pathref_fd(fsp),
1302 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1303 END_PROFILE(syscall_fstat);
1307 static int vfswrap_lstat(vfs_handle_struct *handle,
1308 struct smb_filename *smb_fname)
1312 START_PROFILE(syscall_lstat);
1314 if (is_named_stream(smb_fname)) {
1319 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1320 lp_fake_directory_create_times(SNUM(handle->conn)));
1322 END_PROFILE(syscall_lstat);
1326 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1328 enum vfs_translate_direction direction,
1329 TALLOC_CTX *mem_ctx,
1332 return NT_STATUS_NONE_MAPPED;
1336 * Return allocated parent directory and basename of path
1338 * Note: if requesting name, it is returned as talloc child of the
1339 * parent. Freeing the parent is thus sufficient to free both.
1341 static NTSTATUS vfswrap_parent_pathname(struct vfs_handle_struct *handle,
1342 TALLOC_CTX *mem_ctx,
1343 const struct smb_filename *smb_fname_in,
1344 struct smb_filename **parent_dir_out,
1345 struct smb_filename **atname_out)
1347 TALLOC_CTX *frame = talloc_stackframe();
1348 struct smb_filename *parent = NULL;
1349 struct smb_filename *name = NULL;
1352 parent = cp_smb_filename(frame, smb_fname_in);
1353 if (parent == NULL) {
1355 return NT_STATUS_NO_MEMORY;
1357 TALLOC_FREE(parent->stream_name);
1358 SET_STAT_INVALID(parent->st);
1360 p = strrchr_m(parent->base_name, '/'); /* Find final '/', if any */
1362 TALLOC_FREE(parent->base_name);
1363 parent->base_name = talloc_strdup(parent, ".");
1364 if (parent->base_name == NULL) {
1366 return NT_STATUS_NO_MEMORY;
1368 p = smb_fname_in->base_name;
1374 if (atname_out == NULL) {
1375 *parent_dir_out = talloc_move(mem_ctx, &parent);
1377 return NT_STATUS_OK;
1380 name = cp_smb_filename(frame, smb_fname_in);
1383 return NT_STATUS_NO_MEMORY;
1385 TALLOC_FREE(name->base_name);
1387 name->base_name = talloc_strdup(name, p);
1388 if (name->base_name == NULL) {
1390 return NT_STATUS_NO_MEMORY;
1393 *parent_dir_out = talloc_move(mem_ctx, &parent);
1394 *atname_out = talloc_move(*parent_dir_out, &name);
1396 return NT_STATUS_OK;
1400 * Implement the default fsctl operation.
1402 static bool vfswrap_logged_ioctl_message = false;
1404 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1405 struct files_struct *fsp,
1408 uint16_t req_flags, /* Needed for UNICODE ... */
1409 const uint8_t *_in_data,
1411 uint8_t **_out_data,
1412 uint32_t max_out_len,
1415 const char *in_data = (const char *)_in_data;
1416 char **out_data = (char **)_out_data;
1420 case FSCTL_SET_SPARSE:
1422 bool set_sparse = true;
1424 if (in_len >= 1 && in_data[0] == 0) {
1428 status = file_set_sparse(handle->conn, fsp, set_sparse);
1430 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1431 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1432 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1433 nt_errstr(status)));
1438 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1440 unsigned char objid[16];
1441 char *return_data = NULL;
1443 /* This should return the object-id on this file.
1444 * I think I'll make this be the inode+dev. JRA.
1447 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1448 fsp_fnum_dbg(fsp)));
1450 *out_len = MIN(max_out_len, 64);
1452 /* Hmmm, will this cause problems if less data asked for? */
1453 return_data = talloc_array(ctx, char, 64);
1454 if (return_data == NULL) {
1455 return NT_STATUS_NO_MEMORY;
1458 /* For backwards compatibility only store the dev/inode. */
1459 push_file_id_16(return_data, &fsp->file_id);
1460 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1461 push_file_id_16(return_data+32, &fsp->file_id);
1462 memset(return_data+48, 0, 16);
1463 *out_data = return_data;
1464 return NT_STATUS_OK;
1467 case FSCTL_GET_REPARSE_POINT:
1469 status = fsctl_get_reparse_point(
1470 fsp, ctx, out_data, max_out_len, out_len);
1474 case FSCTL_SET_REPARSE_POINT:
1476 status = fsctl_set_reparse_point(fsp, ctx, _in_data, in_len);
1480 case FSCTL_DELETE_REPARSE_POINT:
1482 status = fsctl_del_reparse_point(fsp, ctx, _in_data, in_len);
1486 case FSCTL_GET_SHADOW_COPY_DATA:
1489 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1490 * and return their volume names. If max_data_count is 16, then it is just
1491 * asking for the number of volumes and length of the combined names.
1493 * pdata is the data allocated by our caller, but that uses
1494 * total_data_count (which is 0 in our case) rather than max_data_count.
1495 * Allocate the correct amount and return the pointer to let
1496 * it be deallocated when we return.
1498 struct shadow_copy_data *shadow_data = NULL;
1499 bool labels = False;
1500 uint32_t labels_data_count = 0;
1502 char *cur_pdata = NULL;
1504 if (max_out_len < 16) {
1505 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1507 return NT_STATUS_INVALID_PARAMETER;
1510 if (max_out_len > 16) {
1514 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1515 if (shadow_data == NULL) {
1516 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1517 return NT_STATUS_NO_MEMORY;
1521 * Call the VFS routine to actually do the work.
1523 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1526 /* broken module didn't set errno on error */
1527 status = NT_STATUS_UNSUCCESSFUL;
1529 status = map_nt_error_from_unix(errno);
1530 if (NT_STATUS_EQUAL(status,
1531 NT_STATUS_NOT_SUPPORTED)) {
1535 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1536 "connectpath %s, failed - %s.\n",
1537 fsp->conn->connectpath,
1538 nt_errstr(status)));
1539 TALLOC_FREE(shadow_data);
1543 labels_data_count = (shadow_data->num_volumes * 2 *
1544 sizeof(SHADOW_COPY_LABEL)) + 2;
1549 *out_len = 12 + labels_data_count;
1552 if (max_out_len < *out_len) {
1553 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1554 max_out_len, *out_len));
1555 TALLOC_FREE(shadow_data);
1556 return NT_STATUS_BUFFER_TOO_SMALL;
1559 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1560 if (cur_pdata == NULL) {
1561 TALLOC_FREE(shadow_data);
1562 return NT_STATUS_NO_MEMORY;
1565 *out_data = cur_pdata;
1567 /* num_volumes 4 bytes */
1568 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1571 /* num_labels 4 bytes */
1572 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1575 /* needed_data_count 4 bytes */
1576 SIVAL(cur_pdata, 8, labels_data_count);
1580 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1581 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1582 if (labels && shadow_data->labels) {
1583 for (i=0; i<shadow_data->num_volumes; i++) {
1585 status = srvstr_push(cur_pdata, req_flags,
1586 cur_pdata, shadow_data->labels[i],
1587 2 * sizeof(SHADOW_COPY_LABEL),
1588 STR_UNICODE|STR_TERMINATE, &len);
1589 if (!NT_STATUS_IS_OK(status)) {
1590 TALLOC_FREE(*out_data);
1591 TALLOC_FREE(shadow_data);
1594 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1595 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1599 TALLOC_FREE(shadow_data);
1601 return NT_STATUS_OK;
1604 case FSCTL_FIND_FILES_BY_SID:
1606 /* pretend this succeeded -
1608 * we have to send back a list with all files owned by this SID
1610 * but I have to check that --metze
1614 struct dom_sid_buf buf;
1618 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1619 fsp_fnum_dbg(fsp)));
1622 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1623 return NT_STATUS_INVALID_PARAMETER;
1626 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1628 /* unknown 4 bytes: this is not the length of the sid :-( */
1629 /*unknown = IVAL(pdata,0);*/
1631 ret = sid_parse(_in_data + 4, sid_len, &sid);
1633 return NT_STATUS_INVALID_PARAMETER;
1635 DEBUGADD(10, ("for SID: %s\n",
1636 dom_sid_str_buf(&sid, &buf)));
1638 if (!sid_to_uid(&sid, &uid)) {
1639 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1640 dom_sid_str_buf(&sid, &buf),
1641 (unsigned long)sid_len));
1645 /* we can take a look at the find source :-)
1647 * find ./ -uid $uid -name '*' is what we need here
1650 * and send 4bytes len and then NULL terminated unicode strings
1653 * but I don't know how to deal with the paged results
1654 * (maybe we can hang the result anywhere in the fsp struct)
1656 * but I don't know how to deal with the paged results
1657 * (maybe we can hang the result anywhere in the fsp struct)
1659 * we don't send all files at once
1660 * and at the next we should *not* start from the beginning,
1661 * so we have to cache the result
1666 /* this works for now... */
1667 return NT_STATUS_OK;
1670 case FSCTL_QUERY_ALLOCATED_RANGES:
1672 /* FIXME: This is just a dummy reply, telling that all of the
1673 * file is allocated. MKS cp needs that.
1674 * Adding the real allocated ranges via FIEMAP on Linux
1675 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1676 * this FSCTL correct for sparse files.
1678 uint64_t offset, length;
1679 char *out_data_tmp = NULL;
1682 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1684 return NT_STATUS_INVALID_PARAMETER;
1687 if (max_out_len < 16) {
1688 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1690 return NT_STATUS_INVALID_PARAMETER;
1693 offset = BVAL(in_data,0);
1694 length = BVAL(in_data,8);
1696 if (offset + length < offset) {
1697 /* No 64-bit integer wrap. */
1698 return NT_STATUS_INVALID_PARAMETER;
1701 /* Shouldn't this be SMB_VFS_STAT ... ? */
1702 status = vfs_stat_fsp(fsp);
1703 if (!NT_STATUS_IS_OK(status)) {
1708 out_data_tmp = talloc_array(ctx, char, *out_len);
1709 if (out_data_tmp == NULL) {
1710 DEBUG(10, ("unable to allocate memory for response\n"));
1711 return NT_STATUS_NO_MEMORY;
1714 if (offset > fsp->fsp_name->st.st_ex_size ||
1715 fsp->fsp_name->st.st_ex_size == 0 ||
1717 memset(out_data_tmp, 0, *out_len);
1719 uint64_t end = offset + length;
1720 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1721 SBVAL(out_data_tmp, 0, 0);
1722 SBVAL(out_data_tmp, 8, end);
1725 *out_data = out_data_tmp;
1727 return NT_STATUS_OK;
1730 case FSCTL_IS_VOLUME_DIRTY:
1732 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1733 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1735 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1736 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1738 return NT_STATUS_INVALID_PARAMETER;
1743 * Only print once ... unfortunately there could be lots of
1744 * different FSCTLs that are called.
1746 if (!vfswrap_logged_ioctl_message) {
1747 vfswrap_logged_ioctl_message = true;
1748 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1749 __func__, function));
1753 return NT_STATUS_NOT_SUPPORTED;
1756 static bool vfswrap_is_offline(struct connection_struct *conn,
1757 const struct smb_filename *fname);
1759 struct vfswrap_get_dos_attributes_state {
1760 struct vfs_aio_state aio_state;
1761 connection_struct *conn;
1762 TALLOC_CTX *mem_ctx;
1763 struct tevent_context *ev;
1764 files_struct *dir_fsp;
1765 struct smb_filename *smb_fname;
1770 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq);
1772 static struct tevent_req *vfswrap_get_dos_attributes_send(
1773 TALLOC_CTX *mem_ctx,
1774 struct tevent_context *ev,
1775 struct vfs_handle_struct *handle,
1776 files_struct *dir_fsp,
1777 struct smb_filename *smb_fname)
1779 struct tevent_req *req = NULL;
1780 struct tevent_req *subreq = NULL;
1781 struct vfswrap_get_dos_attributes_state *state = NULL;
1783 req = tevent_req_create(mem_ctx, &state,
1784 struct vfswrap_get_dos_attributes_state);
1789 *state = (struct vfswrap_get_dos_attributes_state) {
1790 .conn = dir_fsp->conn,
1794 .smb_fname = smb_fname,
1797 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1801 SAMBA_XATTR_DOS_ATTRIB,
1803 if (tevent_req_nomem(subreq, req)) {
1804 return tevent_req_post(req, ev);
1806 tevent_req_set_callback(subreq,
1807 vfswrap_get_dos_attributes_getxattr_done,
1813 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq)
1815 struct tevent_req *req =
1816 tevent_req_callback_data(subreq,
1818 struct vfswrap_get_dos_attributes_state *state =
1819 tevent_req_data(req,
1820 struct vfswrap_get_dos_attributes_state);
1822 DATA_BLOB blob = {0};
1824 char *tofree = NULL;
1825 char pathbuf[PATH_MAX+1];
1827 struct smb_filename smb_fname;
1831 xattr_size = SMB_VFS_GETXATTRAT_RECV(subreq,
1835 TALLOC_FREE(subreq);
1836 if (xattr_size == -1) {
1837 status = map_nt_error_from_unix(state->aio_state.error);
1839 if (state->as_root) {
1840 tevent_req_nterror(req, status);
1843 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1844 tevent_req_nterror(req, status);
1848 state->as_root = true;
1851 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1855 SAMBA_XATTR_DOS_ATTRIB,
1858 if (tevent_req_nomem(subreq, req)) {
1861 tevent_req_set_callback(subreq,
1862 vfswrap_get_dos_attributes_getxattr_done,
1867 blob.length = xattr_size;
1869 status = parse_dos_attribute_blob(state->smb_fname,
1872 if (!NT_STATUS_IS_OK(status)) {
1873 tevent_req_nterror(req, status);
1877 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
1878 state->smb_fname->base_name,
1883 if (pathlen == -1) {
1884 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1888 smb_fname = (struct smb_filename) {
1890 .st = state->smb_fname->st,
1891 .flags = state->smb_fname->flags,
1892 .twrp = state->smb_fname->twrp,
1895 offline = vfswrap_is_offline(state->conn, &smb_fname);
1897 state->dosmode |= FILE_ATTRIBUTE_OFFLINE;
1899 TALLOC_FREE(tofree);
1901 tevent_req_done(req);
1905 static NTSTATUS vfswrap_get_dos_attributes_recv(struct tevent_req *req,
1906 struct vfs_aio_state *aio_state,
1909 struct vfswrap_get_dos_attributes_state *state =
1910 tevent_req_data(req,
1911 struct vfswrap_get_dos_attributes_state);
1914 if (tevent_req_is_nterror(req, &status)) {
1915 tevent_req_received(req);
1919 *aio_state = state->aio_state;
1920 *dosmode = state->dosmode;
1921 tevent_req_received(req);
1922 return NT_STATUS_OK;
1925 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1926 struct files_struct *fsp,
1931 offline = vfswrap_is_offline(handle->conn, fsp->fsp_name);
1933 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1936 return fget_ea_dos_attribute(fsp, dosmode);
1939 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1940 struct files_struct *fsp,
1943 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1946 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1948 struct vfswrap_offload_read_state {
1952 static struct tevent_req *vfswrap_offload_read_send(
1953 TALLOC_CTX *mem_ctx,
1954 struct tevent_context *ev,
1955 struct vfs_handle_struct *handle,
1956 struct files_struct *fsp,
1962 struct tevent_req *req = NULL;
1963 struct vfswrap_offload_read_state *state = NULL;
1966 req = tevent_req_create(mem_ctx, &state,
1967 struct vfswrap_offload_read_state);
1972 status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1973 &vfswrap_offload_ctx);
1974 if (tevent_req_nterror(req, status)) {
1975 return tevent_req_post(req, ev);
1978 if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1979 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1980 return tevent_req_post(req, ev);
1983 status = vfs_offload_token_create_blob(state, fsp, fsctl,
1985 if (tevent_req_nterror(req, status)) {
1986 return tevent_req_post(req, ev);
1989 status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1991 if (tevent_req_nterror(req, status)) {
1992 return tevent_req_post(req, ev);
1995 tevent_req_done(req);
1996 return tevent_req_post(req, ev);
1999 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
2000 struct vfs_handle_struct *handle,
2001 TALLOC_CTX *mem_ctx,
2004 struct vfswrap_offload_read_state *state = tevent_req_data(
2005 req, struct vfswrap_offload_read_state);
2008 if (tevent_req_is_nterror(req, &status)) {
2009 tevent_req_received(req);
2013 token->length = state->token.length;
2014 token->data = talloc_move(mem_ctx, &state->token.data);
2016 tevent_req_received(req);
2017 return NT_STATUS_OK;
2020 struct vfswrap_offload_write_state {
2022 bool read_lck_locked;
2023 bool write_lck_locked;
2025 struct tevent_context *src_ev;
2026 struct files_struct *src_fsp;
2028 struct tevent_context *dst_ev;
2029 struct files_struct *dst_fsp;
2033 size_t next_io_size;
2036 static void vfswrap_offload_write_cleanup(struct tevent_req *req,
2037 enum tevent_req_state req_state)
2039 struct vfswrap_offload_write_state *state = tevent_req_data(
2040 req, struct vfswrap_offload_write_state);
2043 if (state->dst_fsp == NULL) {
2047 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2049 state->dst_fsp = NULL;
2052 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
2054 static struct tevent_req *vfswrap_offload_write_send(
2055 struct vfs_handle_struct *handle,
2056 TALLOC_CTX *mem_ctx,
2057 struct tevent_context *ev,
2060 off_t transfer_offset,
2061 struct files_struct *dest_fsp,
2065 struct tevent_req *req;
2066 struct vfswrap_offload_write_state *state = NULL;
2067 /* off_t is signed! */
2068 off_t max_offset = INT64_MAX - to_copy;
2069 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
2070 files_struct *src_fsp = NULL;
2074 req = tevent_req_create(mem_ctx, &state,
2075 struct vfswrap_offload_write_state);
2080 *state = (struct vfswrap_offload_write_state) {
2082 .src_off = transfer_offset,
2084 .dst_fsp = dest_fsp,
2085 .dst_off = dest_off,
2087 .remaining = to_copy,
2090 tevent_req_set_cleanup_fn(req, vfswrap_offload_write_cleanup);
2093 case FSCTL_SRV_COPYCHUNK:
2094 case FSCTL_SRV_COPYCHUNK_WRITE:
2097 case FSCTL_OFFLOAD_WRITE:
2098 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
2099 return tevent_req_post(req, ev);
2101 case FSCTL_DUP_EXTENTS_TO_FILE:
2102 DBG_DEBUG("COW clones not supported by vfs_default\n");
2103 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2104 return tevent_req_post(req, ev);
2107 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2108 return tevent_req_post(req, ev);
2112 * From here on we assume a copy-chunk fsctl
2116 tevent_req_done(req);
2117 return tevent_req_post(req, ev);
2120 if (state->src_off > max_offset) {
2122 * Protect integer checks below.
2124 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2125 return tevent_req_post(req, ev);
2127 if (state->src_off < 0) {
2129 * Protect integer checks below.
2131 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2132 return tevent_req_post(req, ev);
2134 if (state->dst_off > max_offset) {
2136 * Protect integer checks below.
2138 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2139 return tevent_req_post(req, ev);
2141 if (state->dst_off < 0) {
2143 * Protect integer checks below.
2145 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2146 return tevent_req_post(req, ev);
2149 status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
2151 if (tevent_req_nterror(req, status)) {
2152 return tevent_req_post(req, ev);
2155 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
2157 status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
2158 if (!NT_STATUS_IS_OK(status)) {
2159 tevent_req_nterror(req, status);
2160 return tevent_req_post(req, ev);
2163 ok = change_to_user_and_service_by_fsp(src_fsp);
2165 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2166 return tevent_req_post(req, ev);
2169 state->src_ev = src_fsp->conn->sconn->ev_ctx;
2170 state->src_fsp = src_fsp;
2172 status = vfs_stat_fsp(src_fsp);
2173 if (tevent_req_nterror(req, status)) {
2174 return tevent_req_post(req, ev);
2177 if (src_fsp->fsp_name->st.st_ex_size < state->src_off + to_copy) {
2179 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
2180 * If the SourceOffset or SourceOffset + Length extends beyond
2181 * the end of file, the server SHOULD<240> treat this as a
2182 * STATUS_END_OF_FILE error.
2184 * <240> Section 3.3.5.15.6: Windows servers will return
2185 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
2187 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
2188 return tevent_req_post(req, ev);
2191 state->buf = talloc_array(state, uint8_t, num);
2192 if (tevent_req_nomem(state->buf, req)) {
2193 return tevent_req_post(req, ev);
2196 status = vfswrap_offload_write_loop(req);
2197 if (!NT_STATUS_IS_OK(status)) {
2198 tevent_req_nterror(req, status);
2199 return tevent_req_post(req, ev);
2205 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
2207 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
2209 struct vfswrap_offload_write_state *state = tevent_req_data(
2210 req, struct vfswrap_offload_write_state);
2211 struct tevent_req *subreq = NULL;
2212 struct lock_struct read_lck;
2216 * This is called under the context of state->src_fsp.
2219 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
2221 init_strict_lock_struct(state->src_fsp,
2222 state->src_fsp->op->global->open_persistent_id,
2224 state->next_io_size,
2228 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
2232 return NT_STATUS_FILE_LOCK_CONFLICT;
2235 subreq = SMB_VFS_PREAD_SEND(state,
2239 state->next_io_size,
2241 if (subreq == NULL) {
2242 return NT_STATUS_NO_MEMORY;
2244 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
2246 return NT_STATUS_OK;
2249 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
2251 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
2253 struct tevent_req *req = tevent_req_callback_data(
2254 subreq, struct tevent_req);
2255 struct vfswrap_offload_write_state *state = tevent_req_data(
2256 req, struct vfswrap_offload_write_state);
2257 struct vfs_aio_state aio_state;
2258 struct lock_struct write_lck;
2262 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
2263 TALLOC_FREE(subreq);
2265 DBG_ERR("read failed: %s\n", strerror(aio_state.error));
2266 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2269 if (nread != state->next_io_size) {
2270 DBG_ERR("Short read, only %zd of %zu\n",
2271 nread, state->next_io_size);
2272 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2276 state->src_off += nread;
2278 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2280 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2284 init_strict_lock_struct(state->dst_fsp,
2285 state->dst_fsp->op->global->open_persistent_id,
2287 state->next_io_size,
2291 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
2295 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
2299 subreq = SMB_VFS_PWRITE_SEND(state,
2303 state->next_io_size,
2305 if (subreq == NULL) {
2306 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2309 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
2312 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
2314 struct tevent_req *req = tevent_req_callback_data(
2315 subreq, struct tevent_req);
2316 struct vfswrap_offload_write_state *state = tevent_req_data(
2317 req, struct vfswrap_offload_write_state);
2318 struct vfs_aio_state aio_state;
2323 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
2324 TALLOC_FREE(subreq);
2325 if (nwritten == -1) {
2326 DBG_ERR("write failed: %s\n", strerror(aio_state.error));
2327 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2330 if (nwritten != state->next_io_size) {
2331 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
2332 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2336 state->dst_off += nwritten;
2338 if (state->remaining < nwritten) {
2339 /* Paranoia check */
2340 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2343 state->remaining -= nwritten;
2344 if (state->remaining == 0) {
2345 tevent_req_done(req);
2349 ok = change_to_user_and_service_by_fsp(state->src_fsp);
2351 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2355 status = vfswrap_offload_write_loop(req);
2356 if (!NT_STATUS_IS_OK(status)) {
2357 tevent_req_nterror(req, status);
2364 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
2365 struct tevent_req *req,
2368 struct vfswrap_offload_write_state *state = tevent_req_data(
2369 req, struct vfswrap_offload_write_state);
2372 if (tevent_req_is_nterror(req, &status)) {
2373 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
2375 tevent_req_received(req);
2379 *copied = state->to_copy;
2380 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
2381 tevent_req_received(req);
2383 return NT_STATUS_OK;
2386 static NTSTATUS vfswrap_fget_compression(struct vfs_handle_struct *handle,
2387 TALLOC_CTX *mem_ctx,
2388 struct files_struct *fsp,
2389 uint16_t *_compression_fmt)
2391 return NT_STATUS_INVALID_DEVICE_REQUEST;
2394 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
2395 TALLOC_CTX *mem_ctx,
2396 struct files_struct *fsp,
2397 uint16_t compression_fmt)
2399 return NT_STATUS_INVALID_DEVICE_REQUEST;
2402 /********************************************************************
2403 Given a stat buffer return the allocated size on disk, taking into
2404 account sparse files.
2405 ********************************************************************/
2406 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
2407 struct files_struct *fsp,
2408 const SMB_STRUCT_STAT *sbuf)
2412 START_PROFILE(syscall_get_alloc_size);
2414 if(S_ISDIR(sbuf->st_ex_mode)) {
2419 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2420 /* The type of st_blocksize is blkcnt_t which *MUST* be
2421 signed (according to POSIX) and can be less than 64-bits.
2422 Ensure when we're converting to 64 bits wide we don't
2424 #if defined(SIZEOF_BLKCNT_T_8)
2425 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2426 #elif defined(SIZEOF_BLKCNT_T_4)
2428 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2429 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2432 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2436 * Some file systems do not allocate a block for very
2437 * small files. But for non-empty file should report a
2441 uint64_t filesize = get_file_size_stat(sbuf);
2443 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2447 result = get_file_size_stat(sbuf);
2450 if (fsp && fsp->initial_allocation_size)
2451 result = MAX(result,fsp->initial_allocation_size);
2453 result = smb_roundup(handle->conn, result);
2456 END_PROFILE(syscall_get_alloc_size);
2460 static int vfswrap_unlinkat(vfs_handle_struct *handle,
2461 struct files_struct *dirfsp,
2462 const struct smb_filename *smb_fname,
2467 START_PROFILE(syscall_unlinkat);
2469 if (is_named_stream(smb_fname)) {
2473 result = unlinkat(fsp_get_pathref_fd(dirfsp),
2474 smb_fname->base_name,
2478 END_PROFILE(syscall_unlinkat);
2482 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2486 START_PROFILE(syscall_fchmod);
2488 if (!fsp->fsp_flags.is_pathref) {
2489 result = fchmod(fsp_get_io_fd(fsp), mode);
2490 END_PROFILE(syscall_fchmod);
2494 if (fsp->fsp_flags.have_proc_fds) {
2495 int fd = fsp_get_pathref_fd(fsp);
2496 const char *p = NULL;
2499 p = sys_proc_fd_path(fd, buf, sizeof(buf));
2501 result = chmod(p, mode);
2505 END_PROFILE(syscall_fchmod);
2510 * This is no longer a handle based call.
2512 result = chmod(fsp->fsp_name->base_name, mode);
2514 END_PROFILE(syscall_fchmod);
2518 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2523 START_PROFILE(syscall_fchown);
2524 if (!fsp->fsp_flags.is_pathref) {
2525 result = fchown(fsp_get_io_fd(fsp), uid, gid);
2526 END_PROFILE(syscall_fchown);
2530 if (fsp->fsp_flags.have_proc_fds) {
2531 int fd = fsp_get_pathref_fd(fsp);
2532 const char *p = NULL;
2535 p = sys_proc_fd_path(fd, buf, sizeof(buf));
2537 result = chown(p, uid, gid);
2541 END_PROFILE(syscall_fchown);
2546 * This is no longer a handle based call.
2548 result = chown(fsp->fsp_name->base_name, uid, gid);
2549 END_PROFILE(syscall_fchown);
2557 static int vfswrap_lchown(vfs_handle_struct *handle,
2558 const struct smb_filename *smb_fname,
2564 START_PROFILE(syscall_lchown);
2565 result = lchown(smb_fname->base_name, uid, gid);
2566 END_PROFILE(syscall_lchown);
2570 static int vfswrap_chdir(vfs_handle_struct *handle,
2571 const struct smb_filename *smb_fname)
2575 START_PROFILE(syscall_chdir);
2576 result = chdir(smb_fname->base_name);
2577 END_PROFILE(syscall_chdir);
2581 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2585 struct smb_filename *smb_fname = NULL;
2587 START_PROFILE(syscall_getwd);
2588 result = sys_getwd();
2589 END_PROFILE(syscall_getwd);
2591 if (result == NULL) {
2594 smb_fname = synthetic_smb_fname(ctx,
2601 * sys_getwd() *always* returns malloced memory.
2602 * We must free here to avoid leaks:
2603 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2609 /*********************************************************************
2610 nsec timestamp resolution call. Convert down to whatever the underlying
2611 system will support.
2612 **********************************************************************/
2614 static int vfswrap_fntimes(vfs_handle_struct *handle,
2616 struct smb_file_time *ft)
2619 struct timespec ts[2];
2620 struct timespec *times = NULL;
2622 START_PROFILE(syscall_fntimes);
2624 if (is_named_stream(fsp->fsp_name)) {
2630 if (is_omit_timespec(&ft->atime)) {
2631 ft->atime = fsp->fsp_name->st.st_ex_atime;
2634 if (is_omit_timespec(&ft->mtime)) {
2635 ft->mtime = fsp->fsp_name->st.st_ex_mtime;
2638 if (!is_omit_timespec(&ft->create_time)) {
2639 set_create_timespec_ea(fsp,
2643 if ((timespec_compare(&ft->atime,
2644 &fsp->fsp_name->st.st_ex_atime) == 0) &&
2645 (timespec_compare(&ft->mtime,
2646 &fsp->fsp_name->st.st_ex_mtime) == 0)) {
2658 if (!fsp->fsp_flags.is_pathref) {
2659 result = futimens(fsp_get_io_fd(fsp), times);
2663 if (fsp->fsp_flags.have_proc_fds) {
2664 int fd = fsp_get_pathref_fd(fsp);
2665 const char *p = NULL;
2668 p = sys_proc_fd_path(fd, buf, sizeof(buf));
2671 * The dirfd argument of utimensat is ignored when
2672 * pathname is an absolute path
2674 result = utimensat(AT_FDCWD, p, times, 0);
2683 * The fd is a pathref (opened with O_PATH) and there isn't fd to
2684 * path translation mechanism. Fallback to path based call.
2686 result = utimensat(AT_FDCWD, fsp->fsp_name->base_name, times, 0);
2689 END_PROFILE(syscall_fntimes);
2695 /*********************************************************************
2696 A version of ftruncate that will write the space on disk if strict
2698 **********************************************************************/
2700 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2702 off_t space_to_write;
2703 uint64_t space_avail;
2704 uint64_t bsize,dfree,dsize;
2707 SMB_STRUCT_STAT *pst;
2710 ok = vfs_valid_pwrite_range(len, 0);
2716 status = vfs_stat_fsp(fsp);
2717 if (!NT_STATUS_IS_OK(status)) {
2720 pst = &fsp->fsp_name->st;
2723 if (S_ISFIFO(pst->st_ex_mode))
2727 if (pst->st_ex_size == len)
2730 /* Shrink - just ftruncate. */
2731 if (pst->st_ex_size > len)
2732 return ftruncate(fsp_get_io_fd(fsp), len);
2734 space_to_write = len - pst->st_ex_size;
2736 /* for allocation try fallocate first. This can fail on some
2737 platforms e.g. when the filesystem doesn't support it and no
2738 emulation is being done by the libc (like on AIX with JFS1). In that
2739 case we do our own emulation. fallocate implementations can
2740 return ENOTSUP or EINVAL in cases like that. */
2741 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2742 if (ret == -1 && errno == ENOSPC) {
2748 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2749 "error %d. Falling back to slow manual allocation\n", errno));
2751 /* available disk space is enough or not? */
2753 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2754 /* space_avail is 1k blocks */
2755 if (space_avail == (uint64_t)-1 ||
2756 ((uint64_t)space_to_write/1024 > space_avail) ) {
2761 /* Write out the real space on disk. */
2762 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2770 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2773 SMB_STRUCT_STAT *pst;
2777 START_PROFILE(syscall_ftruncate);
2779 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->fsp_flags.is_sparse) {
2780 result = strict_allocate_ftruncate(handle, fsp, len);
2781 END_PROFILE(syscall_ftruncate);
2785 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2786 ftruncate if the system supports it. Then I discovered that
2787 you can have some filesystems that support ftruncate
2788 expansion and some that don't! On Linux fat can't do
2789 ftruncate extend but ext2 can. */
2791 result = ftruncate(fsp_get_io_fd(fsp), len);
2793 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2794 extend a file with ftruncate. Provide alternate implementation
2797 /* Do an fstat to see if the file is longer than the requested
2798 size in which case the ftruncate above should have
2799 succeeded or shorter, in which case seek to len - 1 and
2800 write 1 byte of zero */
2801 status = vfs_stat_fsp(fsp);
2802 if (!NT_STATUS_IS_OK(status)) {
2806 /* We need to update the files_struct after successful ftruncate */
2811 pst = &fsp->fsp_name->st;
2814 if (S_ISFIFO(pst->st_ex_mode)) {
2820 if (pst->st_ex_size == len) {
2825 if (pst->st_ex_size > len) {
2826 /* the ftruncate should have worked */
2830 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2838 END_PROFILE(syscall_ftruncate);
2842 static int vfswrap_fallocate(vfs_handle_struct *handle,
2850 START_PROFILE(syscall_fallocate);
2852 result = sys_posix_fallocate(fsp_get_io_fd(fsp), offset, len);
2854 * posix_fallocate returns 0 on success, errno on error
2855 * and doesn't set errno. Make it behave like fallocate()
2856 * which returns -1, and sets errno on failure.
2863 /* sys_fallocate handles filtering of unsupported mode flags */
2864 result = sys_fallocate(fsp_get_io_fd(fsp), mode, offset, len);
2866 END_PROFILE(syscall_fallocate);
2870 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2874 START_PROFILE(syscall_fcntl_lock);
2876 if (fsp->fsp_flags.use_ofd_locks) {
2877 op = map_process_lock_to_ofd_lock(op);
2880 result = fcntl_lock(fsp_get_io_fd(fsp), op, offset, count, type);
2881 END_PROFILE(syscall_fcntl_lock);
2885 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2886 uint32_t share_access, uint32_t access_mask)
2888 START_PROFILE(syscall_kernel_flock);
2889 kernel_flock(fsp_get_io_fd(fsp), share_access, access_mask);
2890 END_PROFILE(syscall_kernel_flock);
2894 static int vfswrap_fcntl(vfs_handle_struct *handle, files_struct *fsp, int cmd,
2898 va_list dup_cmd_arg;
2902 START_PROFILE(syscall_fcntl);
2904 va_copy(dup_cmd_arg, cmd_arg);
2910 #if defined(HAVE_OFD_LOCKS)
2915 #if defined(HAVE_F_OWNER_EX)
2919 #if defined(HAVE_RW_HINTS)
2922 case F_GET_FILE_RW_HINT:
2923 case F_SET_FILE_RW_HINT:
2925 argp = va_arg(dup_cmd_arg, void *);
2926 result = sys_fcntl_ptr(fsp_get_io_fd(fsp), cmd, argp);
2929 val = va_arg(dup_cmd_arg, int);
2930 result = sys_fcntl_int(fsp_get_io_fd(fsp), cmd, val);
2933 va_end(dup_cmd_arg);
2935 END_PROFILE(syscall_fcntl);
2939 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2944 START_PROFILE(syscall_fcntl_getlock);
2946 if (fsp->fsp_flags.use_ofd_locks) {
2947 op = map_process_lock_to_ofd_lock(op);
2950 result = fcntl_getlock(fsp_get_io_fd(fsp), op, poffset, pcount, ptype, ppid);
2951 END_PROFILE(syscall_fcntl_getlock);
2955 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2960 START_PROFILE(syscall_linux_setlease);
2962 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2963 result = linux_setlease(fsp_get_io_fd(fsp), leasetype);
2967 END_PROFILE(syscall_linux_setlease);
2971 static int vfswrap_symlinkat(vfs_handle_struct *handle,
2972 const struct smb_filename *link_target,
2973 struct files_struct *dirfsp,
2974 const struct smb_filename *new_smb_fname)
2978 START_PROFILE(syscall_symlinkat);
2980 result = symlinkat(link_target->base_name,
2981 fsp_get_pathref_fd(dirfsp),
2982 new_smb_fname->base_name);
2983 END_PROFILE(syscall_symlinkat);
2987 static int vfswrap_readlinkat(vfs_handle_struct *handle,
2988 const struct files_struct *dirfsp,
2989 const struct smb_filename *smb_fname,
2995 START_PROFILE(syscall_readlinkat);
2997 result = readlinkat(fsp_get_pathref_fd(dirfsp),
2998 smb_fname->base_name,
3002 END_PROFILE(syscall_readlinkat);
3006 static int vfswrap_linkat(vfs_handle_struct *handle,
3007 files_struct *srcfsp,
3008 const struct smb_filename *old_smb_fname,
3009 files_struct *dstfsp,
3010 const struct smb_filename *new_smb_fname,
3015 START_PROFILE(syscall_linkat);
3017 result = linkat(fsp_get_pathref_fd(srcfsp),
3018 old_smb_fname->base_name,
3019 fsp_get_pathref_fd(dstfsp),
3020 new_smb_fname->base_name,
3023 END_PROFILE(syscall_linkat);
3027 static int vfswrap_mknodat(vfs_handle_struct *handle,
3028 files_struct *dirfsp,
3029 const struct smb_filename *smb_fname,
3035 START_PROFILE(syscall_mknodat);
3037 result = sys_mknodat(fsp_get_pathref_fd(dirfsp),
3038 smb_fname->base_name,
3042 END_PROFILE(syscall_mknodat);
3046 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
3048 const struct smb_filename *smb_fname)
3051 struct smb_filename *result_fname = NULL;
3053 START_PROFILE(syscall_realpath);
3054 result = sys_realpath(smb_fname->base_name);
3055 END_PROFILE(syscall_realpath);
3057 result_fname = synthetic_smb_fname(ctx,
3065 return result_fname;
3068 static int vfswrap_chflags(vfs_handle_struct *handle,
3069 const struct smb_filename *smb_fname,
3073 return chflags(smb_fname->base_name, flags);
3080 static int vfswrap_fchflags(vfs_handle_struct *handle,
3081 struct files_struct *fsp,
3084 #ifdef HAVE_FCHFLAGS
3085 int fd = fsp_get_pathref_fd(fsp);
3087 if (!fsp->fsp_flags.is_pathref) {
3088 return fchflags(fd, flags);
3091 if (fsp->fsp_flags.have_proc_fds) {
3092 const char *p = NULL;
3095 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3100 return chflags(p, flags);
3104 * This is no longer a handle based call.
3106 return chflags(fsp->fsp_name->base_name, flags);
3113 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
3114 const SMB_STRUCT_STAT *sbuf)
3118 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
3122 key.devid = sbuf->st_ex_dev;
3123 key.inode = sbuf->st_ex_ino;
3124 /* key.extid is unused by default. */
3129 static uint64_t vfswrap_fs_file_id(struct vfs_handle_struct *handle,
3130 const SMB_STRUCT_STAT *psbuf)
3134 if (!(psbuf->st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)) {
3135 return psbuf->st_ex_file_id;
3138 if (handle->conn->base_share_dev == psbuf->st_ex_dev) {
3139 return (uint64_t)psbuf->st_ex_ino;
3143 file_id = ((psbuf->st_ex_ino) & UINT32_MAX);
3146 file_id |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32;
3151 static NTSTATUS vfswrap_fstreaminfo(vfs_handle_struct *handle,
3152 struct files_struct *fsp,
3153 TALLOC_CTX *mem_ctx,
3154 unsigned int *pnum_streams,
3155 struct stream_struct **pstreams)
3157 struct stream_struct *tmp_streams = NULL;
3158 unsigned int num_streams = *pnum_streams;
3159 struct stream_struct *streams = *pstreams;
3162 if (fsp->fsp_flags.is_directory) {
3164 * No default streams on directories
3168 status = vfs_stat_fsp(fsp);
3169 if (!NT_STATUS_IS_OK(status)) {
3173 if (num_streams + 1 < 1) {
3175 return NT_STATUS_INVALID_PARAMETER;
3178 tmp_streams = talloc_realloc(mem_ctx,
3180 struct stream_struct,
3182 if (tmp_streams == NULL) {
3183 return NT_STATUS_NO_MEMORY;
3185 tmp_streams[num_streams].name = talloc_strdup(tmp_streams, "::$DATA");
3186 if (tmp_streams[num_streams].name == NULL) {
3187 return NT_STATUS_NO_MEMORY;
3189 tmp_streams[num_streams].size = fsp->fsp_name->st.st_ex_size;
3190 tmp_streams[num_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(
3193 &fsp->fsp_name->st);
3196 *pnum_streams = num_streams;
3197 *pstreams = tmp_streams;
3199 return NT_STATUS_OK;
3202 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
3203 const struct smb_filename *path,
3205 TALLOC_CTX *mem_ctx,
3209 * Don't fall back to get_real_filename so callers can differentiate
3210 * between a full directory scan and an actual case-insensitive stat.
3216 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
3217 const struct smb_filename *smb_fname)
3219 return handle->conn->connectpath;
3222 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
3223 struct byte_range_lock *br_lck,
3224 struct lock_struct *plock)
3226 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3228 /* Note: blr is not used in the default implementation. */
3229 return brl_lock_windows_default(br_lck, plock);
3232 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
3233 struct byte_range_lock *br_lck,
3234 const struct lock_struct *plock)
3236 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3238 return brl_unlock_windows_default(br_lck, plock);
3241 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
3243 struct lock_struct *plock)
3245 SMB_ASSERT(plock->lock_type == READ_LOCK ||
3246 plock->lock_type == WRITE_LOCK);
3248 return strict_lock_check_default(fsp, plock);
3251 /* NT ACL operations. */
3253 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
3255 uint32_t security_info,
3256 TALLOC_CTX *mem_ctx,
3257 struct security_descriptor **ppdesc)
3261 START_PROFILE(fget_nt_acl);
3262 result = posix_fget_nt_acl(fsp, security_info,
3264 END_PROFILE(fget_nt_acl);
3268 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
3272 START_PROFILE(fset_nt_acl);
3273 result = set_nt_acl(fsp, security_info_sent, psd);
3274 END_PROFILE(fset_nt_acl);
3278 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
3279 struct smb_filename *file,
3280 struct security_acl *sacl,
3281 uint32_t access_requested,
3282 uint32_t access_denied)
3284 return NT_STATUS_OK; /* Nothing to do here ... */
3287 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
3289 SMB_ACL_TYPE_T type,
3290 TALLOC_CTX *mem_ctx)
3292 return sys_acl_get_fd(handle, fsp, type, mem_ctx);
3295 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle,
3297 SMB_ACL_TYPE_T type,
3300 return sys_acl_set_fd(handle, fsp, type, theacl);
3303 static int vfswrap_sys_acl_delete_def_fd(vfs_handle_struct *handle,
3306 return sys_acl_delete_def_fd(handle, fsp);
3309 /****************************************************************
3310 Extended attribute operations.
3311 *****************************************************************/
3313 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
3314 const struct smb_filename *smb_fname,
3319 return getxattr(smb_fname->base_name, name, value, size);
3322 struct vfswrap_getxattrat_state {
3323 struct tevent_context *ev;
3324 files_struct *dir_fsp;
3325 const struct smb_filename *smb_fname;
3328 * The following variables are talloced off "state" which is protected
3329 * by a destructor and thus are guaranteed to be safe to be used in the
3330 * job function in the worker thread.
3333 const char *xattr_name;
3334 uint8_t *xattr_value;
3335 struct security_unix_token *token;
3338 struct vfs_aio_state vfs_aio_state;
3339 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
3342 static int vfswrap_getxattrat_state_destructor(
3343 struct vfswrap_getxattrat_state *state)
3348 static void vfswrap_getxattrat_do_sync(struct tevent_req *req);
3349 static void vfswrap_getxattrat_do_async(void *private_data);
3350 static void vfswrap_getxattrat_done(struct tevent_req *subreq);
3352 static struct tevent_req *vfswrap_getxattrat_send(
3353 TALLOC_CTX *mem_ctx,
3354 struct tevent_context *ev,
3355 struct vfs_handle_struct *handle,
3356 files_struct *dir_fsp,
3357 const struct smb_filename *smb_fname,
3358 const char *xattr_name,
3361 struct tevent_req *req = NULL;
3362 struct tevent_req *subreq = NULL;
3363 struct vfswrap_getxattrat_state *state = NULL;
3364 size_t max_threads = 0;
3365 bool have_per_thread_cwd = false;
3366 bool have_per_thread_creds = false;
3367 bool do_async = false;
3369 req = tevent_req_create(mem_ctx, &state,
3370 struct vfswrap_getxattrat_state);
3374 *state = (struct vfswrap_getxattrat_state) {
3377 .smb_fname = smb_fname,
3380 max_threads = pthreadpool_tevent_max_threads(dir_fsp->conn->sconn->pool);
3381 if (max_threads >= 1) {
3383 * We need a non sync threadpool!
3385 have_per_thread_cwd = per_thread_cwd_supported();
3387 #ifdef HAVE_LINUX_THREAD_CREDENTIALS
3388 have_per_thread_creds = true;
3390 if (have_per_thread_cwd && have_per_thread_creds) {
3394 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat, profile_p,
3395 state->profile_bytes, 0);
3397 if (fsp_get_pathref_fd(dir_fsp) == -1) {
3398 DBG_ERR("Need a valid directory fd\n");
3399 tevent_req_error(req, EINVAL);
3400 return tevent_req_post(req, ev);
3403 if (alloc_hint > 0) {
3404 state->xattr_value = talloc_zero_array(state,
3407 if (tevent_req_nomem(state->xattr_value, req)) {
3408 return tevent_req_post(req, ev);
3413 vfswrap_getxattrat_do_sync(req);
3414 return tevent_req_post(req, ev);
3418 * Now allocate all parameters from a memory context that won't go away
3419 * no matter what. These paremeters will get used in threads and we
3420 * can't reliably cancel threads, so all buffers passed to the threads
3421 * must not be freed before all referencing threads terminate.
3424 state->name = talloc_strdup(state, smb_fname->base_name);
3425 if (tevent_req_nomem(state->name, req)) {
3426 return tevent_req_post(req, ev);
3429 state->xattr_name = talloc_strdup(state, xattr_name);
3430 if (tevent_req_nomem(state->xattr_name, req)) {
3431 return tevent_req_post(req, ev);
3435 * This is a hot codepath so at first glance one might think we should
3436 * somehow optimize away the token allocation and do a
3437 * talloc_reference() or similar black magic instead. But due to the
3438 * talloc_stackframe pool per SMB2 request this should be a simple copy
3439 * without a malloc in most cases.
3441 if (geteuid() == sec_initial_uid()) {
3442 state->token = root_unix_token(state);
3444 state->token = copy_unix_token(
3446 dir_fsp->conn->session_info->unix_token);
3448 if (tevent_req_nomem(state->token, req)) {
3449 return tevent_req_post(req, ev);
3452 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3454 subreq = pthreadpool_tevent_job_send(
3457 dir_fsp->conn->sconn->pool,
3458 vfswrap_getxattrat_do_async,
3460 if (tevent_req_nomem(subreq, req)) {
3461 return tevent_req_post(req, ev);
3463 tevent_req_set_callback(subreq, vfswrap_getxattrat_done, req);
3465 talloc_set_destructor(state, vfswrap_getxattrat_state_destructor);
3470 static void vfswrap_getxattrat_do_sync(struct tevent_req *req)
3472 struct vfswrap_getxattrat_state *state = tevent_req_data(
3473 req, struct vfswrap_getxattrat_state);
3475 char *tofree = NULL;
3476 char pathbuf[PATH_MAX+1];
3480 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
3481 state->smb_fname->base_name,
3486 if (pathlen == -1) {
3487 tevent_req_error(req, ENOMEM);
3491 state->xattr_size = getxattr(path,
3494 talloc_array_length(state->xattr_value));
3496 TALLOC_FREE(tofree);
3497 if (state->xattr_size == -1) {
3498 tevent_req_error(req, err);
3502 tevent_req_done(req);
3506 static void vfswrap_getxattrat_do_async(void *private_data)
3508 struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3509 private_data, struct vfswrap_getxattrat_state);
3510 struct timespec start_time;
3511 struct timespec end_time;
3514 PROFILE_TIMESTAMP(&start_time);
3515 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
3518 * Here we simulate a getxattrat()
3519 * call using fchdir();getxattr()
3522 per_thread_cwd_activate();
3524 /* Become the correct credential on this thread. */
3525 ret = set_thread_credentials(state->token->uid,
3527 (size_t)state->token->ngroups,
3528 state->token->groups);
3530 state->xattr_size = -1;
3531 state->vfs_aio_state.error = errno;
3535 ret = fchdir(fsp_get_pathref_fd(state->dir_fsp));
3537 state->xattr_size = -1;
3538 state->vfs_aio_state.error = errno;
3542 state->xattr_size = getxattr(state->name,
3545 talloc_array_length(state->xattr_value));
3546 if (state->xattr_size == -1) {
3547 state->vfs_aio_state.error = errno;
3551 PROFILE_TIMESTAMP(&end_time);
3552 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
3553 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3556 static void vfswrap_getxattrat_done(struct tevent_req *subreq)
3558 struct tevent_req *req = tevent_req_callback_data(
3559 subreq, struct tevent_req);
3560 struct vfswrap_getxattrat_state *state = tevent_req_data(
3561 req, struct vfswrap_getxattrat_state);
3566 * Make sure we run as the user again
3568 ok = change_to_user_and_service_by_fsp(state->dir_fsp);
3571 ret = pthreadpool_tevent_job_recv(subreq);
3572 TALLOC_FREE(subreq);
3573 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
3574 talloc_set_destructor(state, NULL);
3576 if (ret != EAGAIN) {
3577 tevent_req_error(req, ret);
3581 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
3582 * means the lower level pthreadpool failed to create a new
3583 * thread. Fallback to sync processing in that case to allow
3584 * some progress for the client.
3586 vfswrap_getxattrat_do_sync(req);
3590 if (state->xattr_size == -1) {
3591 tevent_req_error(req, state->vfs_aio_state.error);
3595 if (state->xattr_value == NULL) {
3597 * The caller only wanted the size.
3599 tevent_req_done(req);
3604 * shrink the buffer to the returned size.
3605 * (can't fail). It means NULL if size is 0.
3607 state->xattr_value = talloc_realloc(state,
3612 tevent_req_done(req);
3615 static ssize_t vfswrap_getxattrat_recv(struct tevent_req *req,
3616 struct vfs_aio_state *aio_state,
3617 TALLOC_CTX *mem_ctx,
3618 uint8_t **xattr_value)
3620 struct vfswrap_getxattrat_state *state = tevent_req_data(
3621 req, struct vfswrap_getxattrat_state);
3624 if (tevent_req_is_unix_error(req, &aio_state->error)) {
3625 tevent_req_received(req);
3629 *aio_state = state->vfs_aio_state;
3630 xattr_size = state->xattr_size;
3631 if (xattr_value != NULL) {
3632 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
3635 tevent_req_received(req);
3639 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle,
3640 struct files_struct *fsp,
3645 int fd = fsp_get_pathref_fd(fsp);
3647 if (!fsp->fsp_flags.is_pathref) {
3648 return fgetxattr(fd, name, value, size);
3651 if (fsp->fsp_flags.have_proc_fds) {
3652 const char *p = NULL;
3655 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3660 return getxattr(p, name, value, size);
3664 * This is no longer a handle based call.
3666 return getxattr(fsp->fsp_name->base_name, name, value, size);
3669 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
3671 int fd = fsp_get_pathref_fd(fsp);
3673 if (!fsp->fsp_flags.is_pathref) {
3674 return flistxattr(fd, list, size);
3677 if (fsp->fsp_flags.have_proc_fds) {
3678 const char *p = NULL;
3681 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3686 return listxattr(p, list, size);
3690 * This is no longer a handle based call.
3692 return listxattr(fsp->fsp_name->base_name, list, size);
3695 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
3697 int fd = fsp_get_pathref_fd(fsp);
3699 if (!fsp->fsp_flags.is_pathref) {
3700 return fremovexattr(fd, name);
3703 if (fsp->fsp_flags.have_proc_fds) {
3704 const char *p = NULL;
3707 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3712 return removexattr(p, name);
3716 * This is no longer a handle based call.
3718 return removexattr(fsp->fsp_name->base_name, name);
3721 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
3723 int fd = fsp_get_pathref_fd(fsp);
3725 if (!fsp->fsp_flags.is_pathref) {
3726 return fsetxattr(fd, name, value, size, flags);
3729 if (fsp->fsp_flags.have_proc_fds) {
3730 const char *p = NULL;
3733 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3738 return setxattr(p, name, value, size, flags);
3742 * This is no longer a handle based call.
3744 return setxattr(fsp->fsp_name->base_name, name, value, size, flags);
3747 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
3752 static bool vfswrap_is_offline(struct connection_struct *conn,
3753 const struct smb_filename *fname)
3757 bool offline = false;
3759 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
3763 if (!lp_dmapi_support(SNUM(conn)) || !dmapi_have_session()) {
3764 #if defined(ENOTSUP)
3770 status = get_full_smb_filename(talloc_tos(), fname, &path);
3771 if (!NT_STATUS_IS_OK(status)) {
3772 errno = map_errno_from_nt_status(status);
3776 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
3783 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
3784 struct files_struct *fsp,
3785 TALLOC_CTX *mem_ctx,
3788 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
3791 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
3792 struct files_struct *fsp,
3793 const DATA_BLOB old_cookie,
3794 TALLOC_CTX *mem_ctx,
3795 DATA_BLOB *new_cookie)
3797 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
3801 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
3802 struct smb_request *smb1req,
3803 struct smbXsrv_open *op,
3804 const DATA_BLOB old_cookie,
3805 TALLOC_CTX *mem_ctx,
3806 struct files_struct **fsp,
3807 DATA_BLOB *new_cookie)
3809 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
3810 old_cookie, mem_ctx,
3814 static struct vfs_fn_pointers vfs_default_fns = {
3815 /* Disk operations */
3817 .connect_fn = vfswrap_connect,
3818 .disconnect_fn = vfswrap_disconnect,
3819 .disk_free_fn = vfswrap_disk_free,
3820 .get_quota_fn = vfswrap_get_quota,
3821 .set_quota_fn = vfswrap_set_quota,
3822 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3823 .statvfs_fn = vfswrap_statvfs,
3824 .fs_capabilities_fn = vfswrap_fs_capabilities,
3825 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3826 .create_dfs_pathat_fn = vfswrap_create_dfs_pathat,
3827 .read_dfs_pathat_fn = vfswrap_read_dfs_pathat,
3828 .snap_check_path_fn = vfswrap_snap_check_path,
3829 .snap_create_fn = vfswrap_snap_create,
3830 .snap_delete_fn = vfswrap_snap_delete,
3832 /* Directory operations */
3834 .fdopendir_fn = vfswrap_fdopendir,
3835 .readdir_fn = vfswrap_readdir,
3836 .freaddir_attr_fn = vfswrap_freaddir_attr,
3837 .seekdir_fn = vfswrap_seekdir,
3838 .telldir_fn = vfswrap_telldir,
3839 .rewind_dir_fn = vfswrap_rewinddir,
3840 .mkdirat_fn = vfswrap_mkdirat,
3841 .closedir_fn = vfswrap_closedir,
3843 /* File operations */
3845 .openat_fn = vfswrap_openat,
3846 .create_file_fn = vfswrap_create_file,
3847 .close_fn = vfswrap_close,
3848 .pread_fn = vfswrap_pread,
3849 .pread_send_fn = vfswrap_pread_send,
3850 .pread_recv_fn = vfswrap_pread_recv,
3851 .pwrite_fn = vfswrap_pwrite,
3852 .pwrite_send_fn = vfswrap_pwrite_send,
3853 .pwrite_recv_fn = vfswrap_pwrite_recv,
3854 .lseek_fn = vfswrap_lseek,
3855 .sendfile_fn = vfswrap_sendfile,
3856 .recvfile_fn = vfswrap_recvfile,
3857 .renameat_fn = vfswrap_renameat,
3858 .fsync_send_fn = vfswrap_fsync_send,
3859 .fsync_recv_fn = vfswrap_fsync_recv,
3860 .stat_fn = vfswrap_stat,
3861 .fstat_fn = vfswrap_fstat,
3862 .lstat_fn = vfswrap_lstat,
3863 .get_alloc_size_fn = vfswrap_get_alloc_size,
3864 .unlinkat_fn = vfswrap_unlinkat,
3865 .fchmod_fn = vfswrap_fchmod,
3866 .fchown_fn = vfswrap_fchown,
3867 .lchown_fn = vfswrap_lchown,
3868 .chdir_fn = vfswrap_chdir,
3869 .getwd_fn = vfswrap_getwd,
3870 .fntimes_fn = vfswrap_fntimes,
3871 .ftruncate_fn = vfswrap_ftruncate,
3872 .fallocate_fn = vfswrap_fallocate,
3873 .lock_fn = vfswrap_lock,
3874 .kernel_flock_fn = vfswrap_kernel_flock,
3875 .fcntl_fn = vfswrap_fcntl,
3876 .linux_setlease_fn = vfswrap_linux_setlease,
3877 .getlock_fn = vfswrap_getlock,
3878 .symlinkat_fn = vfswrap_symlinkat,
3879 .readlinkat_fn = vfswrap_readlinkat,
3880 .linkat_fn = vfswrap_linkat,
3881 .mknodat_fn = vfswrap_mknodat,
3882 .realpath_fn = vfswrap_realpath,
3883 .chflags_fn = vfswrap_chflags,
3884 .fchflags_fn = vfswrap_fchflags,
3885 .file_id_create_fn = vfswrap_file_id_create,
3886 .fs_file_id_fn = vfswrap_fs_file_id,
3887 .fstreaminfo_fn = vfswrap_fstreaminfo,
3888 .get_real_filename_fn = vfswrap_get_real_filename,
3889 .connectpath_fn = vfswrap_connectpath,
3890 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
3891 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3892 .strict_lock_check_fn = vfswrap_strict_lock_check,
3893 .translate_name_fn = vfswrap_translate_name,
3894 .parent_pathname_fn = vfswrap_parent_pathname,
3895 .fsctl_fn = vfswrap_fsctl,
3896 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
3897 .get_dos_attributes_send_fn = vfswrap_get_dos_attributes_send,
3898 .get_dos_attributes_recv_fn = vfswrap_get_dos_attributes_recv,
3899 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
3900 .offload_read_send_fn = vfswrap_offload_read_send,
3901 .offload_read_recv_fn = vfswrap_offload_read_recv,
3902 .offload_write_send_fn = vfswrap_offload_write_send,
3903 .offload_write_recv_fn = vfswrap_offload_write_recv,
3904 .fget_compression_fn = vfswrap_fget_compression,
3905 .set_compression_fn = vfswrap_set_compression,
3907 /* NT ACL operations. */
3909 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
3910 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
3911 .audit_file_fn = vfswrap_audit_file,
3913 /* POSIX ACL operations. */
3915 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3916 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3917 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3918 .sys_acl_delete_def_fd_fn = vfswrap_sys_acl_delete_def_fd,
3920 /* EA operations. */
3921 .getxattr_fn = vfswrap_getxattr,
3922 .getxattrat_send_fn = vfswrap_getxattrat_send,
3923 .getxattrat_recv_fn = vfswrap_getxattrat_recv,
3924 .fgetxattr_fn = vfswrap_fgetxattr,
3925 .flistxattr_fn = vfswrap_flistxattr,
3926 .fremovexattr_fn = vfswrap_fremovexattr,
3927 .fsetxattr_fn = vfswrap_fsetxattr,
3929 /* aio operations */
3930 .aio_force_fn = vfswrap_aio_force,
3932 /* durable handle operations */
3933 .durable_cookie_fn = vfswrap_durable_cookie,
3934 .durable_disconnect_fn = vfswrap_durable_disconnect,
3935 .durable_reconnect_fn = vfswrap_durable_reconnect,
3939 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3942 * Here we need to implement every call!
3944 * As this is the end of the vfs module chain.
3946 smb_vfs_assert_all_fns(&vfs_default_fns, DEFAULT_VFS_MODULE_NAME);
3947 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3948 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);