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;
2034 size_t next_io_size;
2037 static void vfswrap_offload_write_cleanup(struct tevent_req *req,
2038 enum tevent_req_state req_state)
2040 struct vfswrap_offload_write_state *state = tevent_req_data(
2041 req, struct vfswrap_offload_write_state);
2044 if (state->dst_fsp == NULL) {
2048 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2050 state->dst_fsp = NULL;
2053 static NTSTATUS vfswrap_offload_copy_file_range(struct tevent_req *req);
2054 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
2056 static struct tevent_req *vfswrap_offload_write_send(
2057 struct vfs_handle_struct *handle,
2058 TALLOC_CTX *mem_ctx,
2059 struct tevent_context *ev,
2062 off_t transfer_offset,
2063 struct files_struct *dest_fsp,
2067 struct tevent_req *req;
2068 struct vfswrap_offload_write_state *state = NULL;
2069 /* off_t is signed! */
2070 off_t max_offset = INT64_MAX - to_copy;
2071 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
2072 files_struct *src_fsp = NULL;
2076 req = tevent_req_create(mem_ctx, &state,
2077 struct vfswrap_offload_write_state);
2082 *state = (struct vfswrap_offload_write_state) {
2084 .src_off = transfer_offset,
2086 .dst_fsp = dest_fsp,
2087 .dst_off = dest_off,
2089 .remaining = to_copy,
2092 tevent_req_set_cleanup_fn(req, vfswrap_offload_write_cleanup);
2095 case FSCTL_SRV_COPYCHUNK:
2096 case FSCTL_SRV_COPYCHUNK_WRITE:
2099 case FSCTL_OFFLOAD_WRITE:
2100 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
2101 return tevent_req_post(req, ev);
2103 case FSCTL_DUP_EXTENTS_TO_FILE:
2104 DBG_DEBUG("COW clones not supported by vfs_default\n");
2105 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2106 return tevent_req_post(req, ev);
2109 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2110 return tevent_req_post(req, ev);
2114 * From here on we assume a copy-chunk fsctl
2118 tevent_req_done(req);
2119 return tevent_req_post(req, ev);
2122 if (state->src_off > max_offset) {
2124 * Protect integer checks below.
2126 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2127 return tevent_req_post(req, ev);
2129 if (state->src_off < 0) {
2131 * Protect integer checks below.
2133 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2134 return tevent_req_post(req, ev);
2136 if (state->dst_off > max_offset) {
2138 * Protect integer checks below.
2140 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2141 return tevent_req_post(req, ev);
2143 if (state->dst_off < 0) {
2145 * Protect integer checks below.
2147 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2148 return tevent_req_post(req, ev);
2151 status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
2153 if (tevent_req_nterror(req, status)) {
2154 return tevent_req_post(req, ev);
2157 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
2159 status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
2160 if (!NT_STATUS_IS_OK(status)) {
2161 tevent_req_nterror(req, status);
2162 return tevent_req_post(req, ev);
2165 ok = change_to_user_and_service_by_fsp(src_fsp);
2167 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2168 return tevent_req_post(req, ev);
2171 state->src_ev = src_fsp->conn->sconn->ev_ctx;
2172 state->src_fsp = src_fsp;
2174 status = vfs_stat_fsp(src_fsp);
2175 if (tevent_req_nterror(req, status)) {
2176 return tevent_req_post(req, ev);
2179 if (src_fsp->fsp_name->st.st_ex_size < state->src_off + to_copy) {
2181 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
2182 * If the SourceOffset or SourceOffset + Length extends beyond
2183 * the end of file, the server SHOULD<240> treat this as a
2184 * STATUS_END_OF_FILE error.
2186 * <240> Section 3.3.5.15.6: Windows servers will return
2187 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
2189 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
2190 return tevent_req_post(req, ev);
2193 status = vfswrap_offload_copy_file_range(req);
2194 if (NT_STATUS_IS_OK(status)) {
2195 tevent_req_done(req);
2196 return tevent_req_post(req, ev);
2198 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2199 tevent_req_nterror(req, status);
2200 return tevent_req_post(req, ev);
2203 state->buf = talloc_array(state, uint8_t, num);
2204 if (tevent_req_nomem(state->buf, req)) {
2205 return tevent_req_post(req, ev);
2208 status = vfswrap_offload_write_loop(req);
2209 if (!NT_STATUS_IS_OK(status)) {
2210 tevent_req_nterror(req, status);
2211 return tevent_req_post(req, ev);
2217 static NTSTATUS vfswrap_offload_copy_file_range(struct tevent_req *req)
2219 struct vfswrap_offload_write_state *state = tevent_req_data(
2220 req, struct vfswrap_offload_write_state);
2221 struct lock_struct lck;
2227 #ifndef USE_COPY_FILE_RANGE
2228 return NT_STATUS_MORE_PROCESSING_REQUIRED;
2231 same_file = file_id_equal(&state->src_fsp->file_id,
2232 &state->dst_fsp->file_id);
2234 sys_io_ranges_overlap(state->remaining,
2239 return NT_STATUS_MORE_PROCESSING_REQUIRED;
2242 if (is_named_stream(state->src_fsp->fsp_name) ||
2243 is_named_stream(state->dst_fsp->fsp_name))
2245 return NT_STATUS_MORE_PROCESSING_REQUIRED;
2248 init_strict_lock_struct(state->src_fsp,
2249 state->src_fsp->op->global->open_persistent_id,
2255 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
2259 return NT_STATUS_FILE_LOCK_CONFLICT;
2262 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2264 return NT_STATUS_INTERNAL_ERROR;
2267 init_strict_lock_struct(state->dst_fsp,
2268 state->dst_fsp->op->global->open_persistent_id,
2274 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
2278 return NT_STATUS_FILE_LOCK_CONFLICT;
2281 while (state->remaining > 0) {
2282 nwritten = copy_file_range(fsp_get_io_fd(state->src_fsp),
2284 fsp_get_io_fd(state->dst_fsp),
2288 if (nwritten == -1) {
2289 DBG_DEBUG("copy_file_range src [%s]:[%jd] dst [%s]:[%jd] "
2290 "n [%jd] failed: %s\n",
2291 fsp_str_dbg(state->src_fsp),
2292 (intmax_t)state->src_off,
2293 fsp_str_dbg(state->dst_fsp),
2294 (intmax_t)state->dst_off,
2295 (intmax_t)state->remaining,
2299 status = NT_STATUS_MORE_PROCESSING_REQUIRED;
2302 status = map_nt_error_from_unix(errno);
2303 if (NT_STATUS_EQUAL(
2305 NT_STATUS_MORE_PROCESSING_REQUIRED))
2307 /* Avoid triggering the fallback */
2308 status = NT_STATUS_INTERNAL_ERROR;
2315 if (state->remaining < nwritten) {
2316 DBG_DEBUG("copy_file_range src [%s] dst [%s] "
2317 "n [%jd] remaining [%jd]\n",
2318 fsp_str_dbg(state->src_fsp),
2319 fsp_str_dbg(state->dst_fsp),
2321 (intmax_t)state->remaining);
2322 return NT_STATUS_INTERNAL_ERROR;
2325 if (nwritten == 0) {
2328 state->copied += nwritten;
2329 state->remaining -= nwritten;
2333 * Tell the req cleanup function there's no need to call
2334 * change_to_user_and_service_by_fsp() on the dst handle.
2336 state->dst_fsp = NULL;
2337 return NT_STATUS_OK;
2340 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
2342 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
2344 struct vfswrap_offload_write_state *state = tevent_req_data(
2345 req, struct vfswrap_offload_write_state);
2346 struct tevent_req *subreq = NULL;
2347 struct lock_struct read_lck;
2351 * This is called under the context of state->src_fsp.
2354 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
2356 init_strict_lock_struct(state->src_fsp,
2357 state->src_fsp->op->global->open_persistent_id,
2359 state->next_io_size,
2363 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
2367 return NT_STATUS_FILE_LOCK_CONFLICT;
2370 subreq = SMB_VFS_PREAD_SEND(state,
2374 state->next_io_size,
2376 if (subreq == NULL) {
2377 return NT_STATUS_NO_MEMORY;
2379 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
2381 return NT_STATUS_OK;
2384 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
2386 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
2388 struct tevent_req *req = tevent_req_callback_data(
2389 subreq, struct tevent_req);
2390 struct vfswrap_offload_write_state *state = tevent_req_data(
2391 req, struct vfswrap_offload_write_state);
2392 struct vfs_aio_state aio_state;
2393 struct lock_struct write_lck;
2397 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
2398 TALLOC_FREE(subreq);
2400 DBG_ERR("read failed: %s\n", strerror(aio_state.error));
2401 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2404 if (nread != state->next_io_size) {
2405 DBG_ERR("Short read, only %zd of %zu\n",
2406 nread, state->next_io_size);
2407 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2411 state->src_off += nread;
2413 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2415 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2419 init_strict_lock_struct(state->dst_fsp,
2420 state->dst_fsp->op->global->open_persistent_id,
2422 state->next_io_size,
2426 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
2430 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
2434 subreq = SMB_VFS_PWRITE_SEND(state,
2438 state->next_io_size,
2440 if (subreq == NULL) {
2441 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2444 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
2447 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
2449 struct tevent_req *req = tevent_req_callback_data(
2450 subreq, struct tevent_req);
2451 struct vfswrap_offload_write_state *state = tevent_req_data(
2452 req, struct vfswrap_offload_write_state);
2453 struct vfs_aio_state aio_state;
2458 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
2459 TALLOC_FREE(subreq);
2460 if (nwritten == -1) {
2461 DBG_ERR("write failed: %s\n", strerror(aio_state.error));
2462 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2465 if (nwritten != state->next_io_size) {
2466 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
2467 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2471 state->dst_off += nwritten;
2473 if (state->remaining < nwritten) {
2474 /* Paranoia check */
2475 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2478 state->copied += nwritten;
2479 state->remaining -= nwritten;
2480 if (state->remaining == 0) {
2481 tevent_req_done(req);
2485 ok = change_to_user_and_service_by_fsp(state->src_fsp);
2487 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2491 status = vfswrap_offload_write_loop(req);
2492 if (!NT_STATUS_IS_OK(status)) {
2493 tevent_req_nterror(req, status);
2500 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
2501 struct tevent_req *req,
2504 struct vfswrap_offload_write_state *state = tevent_req_data(
2505 req, struct vfswrap_offload_write_state);
2508 if (tevent_req_is_nterror(req, &status)) {
2509 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
2511 tevent_req_received(req);
2515 *copied = state->copied;
2516 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
2517 tevent_req_received(req);
2519 return NT_STATUS_OK;
2522 static NTSTATUS vfswrap_fget_compression(struct vfs_handle_struct *handle,
2523 TALLOC_CTX *mem_ctx,
2524 struct files_struct *fsp,
2525 uint16_t *_compression_fmt)
2527 return NT_STATUS_INVALID_DEVICE_REQUEST;
2530 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
2531 TALLOC_CTX *mem_ctx,
2532 struct files_struct *fsp,
2533 uint16_t compression_fmt)
2535 return NT_STATUS_INVALID_DEVICE_REQUEST;
2538 /********************************************************************
2539 Given a stat buffer return the allocated size on disk, taking into
2540 account sparse files.
2541 ********************************************************************/
2542 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
2543 struct files_struct *fsp,
2544 const SMB_STRUCT_STAT *sbuf)
2548 START_PROFILE(syscall_get_alloc_size);
2550 if(S_ISDIR(sbuf->st_ex_mode)) {
2555 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2556 /* The type of st_blocksize is blkcnt_t which *MUST* be
2557 signed (according to POSIX) and can be less than 64-bits.
2558 Ensure when we're converting to 64 bits wide we don't
2560 #if defined(SIZEOF_BLKCNT_T_8)
2561 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2562 #elif defined(SIZEOF_BLKCNT_T_4)
2564 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2565 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2568 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2572 * Some file systems do not allocate a block for very
2573 * small files. But for non-empty file should report a
2577 uint64_t filesize = get_file_size_stat(sbuf);
2579 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2583 result = get_file_size_stat(sbuf);
2586 if (fsp && fsp->initial_allocation_size)
2587 result = MAX(result,fsp->initial_allocation_size);
2589 result = smb_roundup(handle->conn, result);
2592 END_PROFILE(syscall_get_alloc_size);
2596 static int vfswrap_unlinkat(vfs_handle_struct *handle,
2597 struct files_struct *dirfsp,
2598 const struct smb_filename *smb_fname,
2603 START_PROFILE(syscall_unlinkat);
2605 if (is_named_stream(smb_fname)) {
2609 result = unlinkat(fsp_get_pathref_fd(dirfsp),
2610 smb_fname->base_name,
2614 END_PROFILE(syscall_unlinkat);
2618 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2622 START_PROFILE(syscall_fchmod);
2624 if (!fsp->fsp_flags.is_pathref) {
2625 result = fchmod(fsp_get_io_fd(fsp), mode);
2626 END_PROFILE(syscall_fchmod);
2630 if (fsp->fsp_flags.have_proc_fds) {
2631 int fd = fsp_get_pathref_fd(fsp);
2632 const char *p = NULL;
2635 p = sys_proc_fd_path(fd, buf, sizeof(buf));
2637 result = chmod(p, mode);
2641 END_PROFILE(syscall_fchmod);
2646 * This is no longer a handle based call.
2648 result = chmod(fsp->fsp_name->base_name, mode);
2650 END_PROFILE(syscall_fchmod);
2654 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2659 START_PROFILE(syscall_fchown);
2660 if (!fsp->fsp_flags.is_pathref) {
2661 result = fchown(fsp_get_io_fd(fsp), uid, gid);
2662 END_PROFILE(syscall_fchown);
2666 if (fsp->fsp_flags.have_proc_fds) {
2667 int fd = fsp_get_pathref_fd(fsp);
2668 const char *p = NULL;
2671 p = sys_proc_fd_path(fd, buf, sizeof(buf));
2673 result = chown(p, uid, gid);
2677 END_PROFILE(syscall_fchown);
2682 * This is no longer a handle based call.
2684 result = chown(fsp->fsp_name->base_name, uid, gid);
2685 END_PROFILE(syscall_fchown);
2693 static int vfswrap_lchown(vfs_handle_struct *handle,
2694 const struct smb_filename *smb_fname,
2700 START_PROFILE(syscall_lchown);
2701 result = lchown(smb_fname->base_name, uid, gid);
2702 END_PROFILE(syscall_lchown);
2706 static int vfswrap_chdir(vfs_handle_struct *handle,
2707 const struct smb_filename *smb_fname)
2711 START_PROFILE(syscall_chdir);
2712 result = chdir(smb_fname->base_name);
2713 END_PROFILE(syscall_chdir);
2717 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2721 struct smb_filename *smb_fname = NULL;
2723 START_PROFILE(syscall_getwd);
2724 result = sys_getwd();
2725 END_PROFILE(syscall_getwd);
2727 if (result == NULL) {
2730 smb_fname = synthetic_smb_fname(ctx,
2737 * sys_getwd() *always* returns malloced memory.
2738 * We must free here to avoid leaks:
2739 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2745 /*********************************************************************
2746 nsec timestamp resolution call. Convert down to whatever the underlying
2747 system will support.
2748 **********************************************************************/
2750 static int vfswrap_fntimes(vfs_handle_struct *handle,
2752 struct smb_file_time *ft)
2755 struct timespec ts[2];
2756 struct timespec *times = NULL;
2758 START_PROFILE(syscall_fntimes);
2760 if (is_named_stream(fsp->fsp_name)) {
2766 if (is_omit_timespec(&ft->atime)) {
2767 ft->atime = fsp->fsp_name->st.st_ex_atime;
2770 if (is_omit_timespec(&ft->mtime)) {
2771 ft->mtime = fsp->fsp_name->st.st_ex_mtime;
2774 if (!is_omit_timespec(&ft->create_time)) {
2775 set_create_timespec_ea(fsp,
2779 if ((timespec_compare(&ft->atime,
2780 &fsp->fsp_name->st.st_ex_atime) == 0) &&
2781 (timespec_compare(&ft->mtime,
2782 &fsp->fsp_name->st.st_ex_mtime) == 0)) {
2794 if (!fsp->fsp_flags.is_pathref) {
2795 result = futimens(fsp_get_io_fd(fsp), times);
2799 if (fsp->fsp_flags.have_proc_fds) {
2800 int fd = fsp_get_pathref_fd(fsp);
2801 const char *p = NULL;
2804 p = sys_proc_fd_path(fd, buf, sizeof(buf));
2807 * The dirfd argument of utimensat is ignored when
2808 * pathname is an absolute path
2810 result = utimensat(AT_FDCWD, p, times, 0);
2819 * The fd is a pathref (opened with O_PATH) and there isn't fd to
2820 * path translation mechanism. Fallback to path based call.
2822 result = utimensat(AT_FDCWD, fsp->fsp_name->base_name, times, 0);
2825 END_PROFILE(syscall_fntimes);
2831 /*********************************************************************
2832 A version of ftruncate that will write the space on disk if strict
2834 **********************************************************************/
2836 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2838 off_t space_to_write;
2839 uint64_t space_avail;
2840 uint64_t bsize,dfree,dsize;
2843 SMB_STRUCT_STAT *pst;
2846 ok = vfs_valid_pwrite_range(len, 0);
2852 status = vfs_stat_fsp(fsp);
2853 if (!NT_STATUS_IS_OK(status)) {
2856 pst = &fsp->fsp_name->st;
2859 if (S_ISFIFO(pst->st_ex_mode))
2863 if (pst->st_ex_size == len)
2866 /* Shrink - just ftruncate. */
2867 if (pst->st_ex_size > len)
2868 return ftruncate(fsp_get_io_fd(fsp), len);
2870 space_to_write = len - pst->st_ex_size;
2872 /* for allocation try fallocate first. This can fail on some
2873 platforms e.g. when the filesystem doesn't support it and no
2874 emulation is being done by the libc (like on AIX with JFS1). In that
2875 case we do our own emulation. fallocate implementations can
2876 return ENOTSUP or EINVAL in cases like that. */
2877 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2878 if (ret == -1 && errno == ENOSPC) {
2884 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2885 "error %d. Falling back to slow manual allocation\n", errno));
2887 /* available disk space is enough or not? */
2889 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2890 /* space_avail is 1k blocks */
2891 if (space_avail == (uint64_t)-1 ||
2892 ((uint64_t)space_to_write/1024 > space_avail) ) {
2897 /* Write out the real space on disk. */
2898 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2906 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2909 SMB_STRUCT_STAT *pst;
2913 START_PROFILE(syscall_ftruncate);
2915 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->fsp_flags.is_sparse) {
2916 result = strict_allocate_ftruncate(handle, fsp, len);
2917 END_PROFILE(syscall_ftruncate);
2921 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2922 ftruncate if the system supports it. Then I discovered that
2923 you can have some filesystems that support ftruncate
2924 expansion and some that don't! On Linux fat can't do
2925 ftruncate extend but ext2 can. */
2927 result = ftruncate(fsp_get_io_fd(fsp), len);
2929 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2930 extend a file with ftruncate. Provide alternate implementation
2933 /* Do an fstat to see if the file is longer than the requested
2934 size in which case the ftruncate above should have
2935 succeeded or shorter, in which case seek to len - 1 and
2936 write 1 byte of zero */
2937 status = vfs_stat_fsp(fsp);
2938 if (!NT_STATUS_IS_OK(status)) {
2942 /* We need to update the files_struct after successful ftruncate */
2947 pst = &fsp->fsp_name->st;
2950 if (S_ISFIFO(pst->st_ex_mode)) {
2956 if (pst->st_ex_size == len) {
2961 if (pst->st_ex_size > len) {
2962 /* the ftruncate should have worked */
2966 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2974 END_PROFILE(syscall_ftruncate);
2978 static int vfswrap_fallocate(vfs_handle_struct *handle,
2986 START_PROFILE(syscall_fallocate);
2988 result = sys_posix_fallocate(fsp_get_io_fd(fsp), offset, len);
2990 * posix_fallocate returns 0 on success, errno on error
2991 * and doesn't set errno. Make it behave like fallocate()
2992 * which returns -1, and sets errno on failure.
2999 /* sys_fallocate handles filtering of unsupported mode flags */
3000 result = sys_fallocate(fsp_get_io_fd(fsp), mode, offset, len);
3002 END_PROFILE(syscall_fallocate);
3006 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
3010 START_PROFILE(syscall_fcntl_lock);
3012 if (fsp->fsp_flags.use_ofd_locks) {
3013 op = map_process_lock_to_ofd_lock(op);
3016 result = fcntl_lock(fsp_get_io_fd(fsp), op, offset, count, type);
3017 END_PROFILE(syscall_fcntl_lock);
3021 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
3022 uint32_t share_access, uint32_t access_mask)
3024 START_PROFILE(syscall_kernel_flock);
3025 kernel_flock(fsp_get_io_fd(fsp), share_access, access_mask);
3026 END_PROFILE(syscall_kernel_flock);
3030 static int vfswrap_fcntl(vfs_handle_struct *handle, files_struct *fsp, int cmd,
3034 va_list dup_cmd_arg;
3038 START_PROFILE(syscall_fcntl);
3040 va_copy(dup_cmd_arg, cmd_arg);
3046 #if defined(HAVE_OFD_LOCKS)
3051 #if defined(HAVE_F_OWNER_EX)
3055 #if defined(HAVE_RW_HINTS)
3058 case F_GET_FILE_RW_HINT:
3059 case F_SET_FILE_RW_HINT:
3061 argp = va_arg(dup_cmd_arg, void *);
3062 result = sys_fcntl_ptr(fsp_get_io_fd(fsp), cmd, argp);
3065 val = va_arg(dup_cmd_arg, int);
3066 result = sys_fcntl_int(fsp_get_io_fd(fsp), cmd, val);
3069 va_end(dup_cmd_arg);
3071 END_PROFILE(syscall_fcntl);
3075 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
3080 START_PROFILE(syscall_fcntl_getlock);
3082 if (fsp->fsp_flags.use_ofd_locks) {
3083 op = map_process_lock_to_ofd_lock(op);
3086 result = fcntl_getlock(fsp_get_io_fd(fsp), op, poffset, pcount, ptype, ppid);
3087 END_PROFILE(syscall_fcntl_getlock);
3091 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
3096 START_PROFILE(syscall_linux_setlease);
3098 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
3099 result = linux_setlease(fsp_get_io_fd(fsp), leasetype);
3103 END_PROFILE(syscall_linux_setlease);
3107 static int vfswrap_symlinkat(vfs_handle_struct *handle,
3108 const struct smb_filename *link_target,
3109 struct files_struct *dirfsp,
3110 const struct smb_filename *new_smb_fname)
3114 START_PROFILE(syscall_symlinkat);
3116 result = symlinkat(link_target->base_name,
3117 fsp_get_pathref_fd(dirfsp),
3118 new_smb_fname->base_name);
3119 END_PROFILE(syscall_symlinkat);
3123 static int vfswrap_readlinkat(vfs_handle_struct *handle,
3124 const struct files_struct *dirfsp,
3125 const struct smb_filename *smb_fname,
3131 START_PROFILE(syscall_readlinkat);
3133 result = readlinkat(fsp_get_pathref_fd(dirfsp),
3134 smb_fname->base_name,
3138 END_PROFILE(syscall_readlinkat);
3142 static int vfswrap_linkat(vfs_handle_struct *handle,
3143 files_struct *srcfsp,
3144 const struct smb_filename *old_smb_fname,
3145 files_struct *dstfsp,
3146 const struct smb_filename *new_smb_fname,
3151 START_PROFILE(syscall_linkat);
3153 result = linkat(fsp_get_pathref_fd(srcfsp),
3154 old_smb_fname->base_name,
3155 fsp_get_pathref_fd(dstfsp),
3156 new_smb_fname->base_name,
3159 END_PROFILE(syscall_linkat);
3163 static int vfswrap_mknodat(vfs_handle_struct *handle,
3164 files_struct *dirfsp,
3165 const struct smb_filename *smb_fname,
3171 START_PROFILE(syscall_mknodat);
3173 result = sys_mknodat(fsp_get_pathref_fd(dirfsp),
3174 smb_fname->base_name,
3178 END_PROFILE(syscall_mknodat);
3182 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
3184 const struct smb_filename *smb_fname)
3187 struct smb_filename *result_fname = NULL;
3189 START_PROFILE(syscall_realpath);
3190 result = sys_realpath(smb_fname->base_name);
3191 END_PROFILE(syscall_realpath);
3193 result_fname = synthetic_smb_fname(ctx,
3201 return result_fname;
3204 static int vfswrap_fchflags(vfs_handle_struct *handle,
3205 struct files_struct *fsp,
3208 #ifdef HAVE_FCHFLAGS
3209 int fd = fsp_get_pathref_fd(fsp);
3211 if (!fsp->fsp_flags.is_pathref) {
3212 return fchflags(fd, flags);
3215 if (fsp->fsp_flags.have_proc_fds) {
3216 const char *p = NULL;
3219 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3224 return chflags(p, flags);
3228 * This is no longer a handle based call.
3230 return chflags(fsp->fsp_name->base_name, flags);
3237 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
3238 const SMB_STRUCT_STAT *sbuf)
3242 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
3246 key.devid = sbuf->st_ex_dev;
3247 key.inode = sbuf->st_ex_ino;
3248 /* key.extid is unused by default. */
3253 static uint64_t vfswrap_fs_file_id(struct vfs_handle_struct *handle,
3254 const SMB_STRUCT_STAT *psbuf)
3258 if (!(psbuf->st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)) {
3259 return psbuf->st_ex_file_id;
3262 if (handle->conn->base_share_dev == psbuf->st_ex_dev) {
3263 return (uint64_t)psbuf->st_ex_ino;
3267 file_id = ((psbuf->st_ex_ino) & UINT32_MAX);
3270 file_id |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32;
3275 static NTSTATUS vfswrap_fstreaminfo(vfs_handle_struct *handle,
3276 struct files_struct *fsp,
3277 TALLOC_CTX *mem_ctx,
3278 unsigned int *pnum_streams,
3279 struct stream_struct **pstreams)
3281 struct stream_struct *tmp_streams = NULL;
3282 unsigned int num_streams = *pnum_streams;
3283 struct stream_struct *streams = *pstreams;
3286 if (fsp->fsp_flags.is_directory) {
3288 * No default streams on directories
3292 status = vfs_stat_fsp(fsp);
3293 if (!NT_STATUS_IS_OK(status)) {
3297 if (num_streams + 1 < 1) {
3299 return NT_STATUS_INVALID_PARAMETER;
3302 tmp_streams = talloc_realloc(mem_ctx,
3304 struct stream_struct,
3306 if (tmp_streams == NULL) {
3307 return NT_STATUS_NO_MEMORY;
3309 tmp_streams[num_streams].name = talloc_strdup(tmp_streams, "::$DATA");
3310 if (tmp_streams[num_streams].name == NULL) {
3311 return NT_STATUS_NO_MEMORY;
3313 tmp_streams[num_streams].size = fsp->fsp_name->st.st_ex_size;
3314 tmp_streams[num_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(
3317 &fsp->fsp_name->st);
3320 *pnum_streams = num_streams;
3321 *pstreams = tmp_streams;
3323 return NT_STATUS_OK;
3326 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
3327 const struct smb_filename *path,
3329 TALLOC_CTX *mem_ctx,
3333 * Don't fall back to get_real_filename so callers can differentiate
3334 * between a full directory scan and an actual case-insensitive stat.
3340 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
3341 const struct smb_filename *smb_fname)
3343 return handle->conn->connectpath;
3346 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
3347 struct byte_range_lock *br_lck,
3348 struct lock_struct *plock)
3350 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3352 /* Note: blr is not used in the default implementation. */
3353 return brl_lock_windows_default(br_lck, plock);
3356 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
3357 struct byte_range_lock *br_lck,
3358 const struct lock_struct *plock)
3360 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3362 return brl_unlock_windows_default(br_lck, plock);
3365 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
3367 struct lock_struct *plock)
3369 SMB_ASSERT(plock->lock_type == READ_LOCK ||
3370 plock->lock_type == WRITE_LOCK);
3372 return strict_lock_check_default(fsp, plock);
3375 /* NT ACL operations. */
3377 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
3379 uint32_t security_info,
3380 TALLOC_CTX *mem_ctx,
3381 struct security_descriptor **ppdesc)
3385 START_PROFILE(fget_nt_acl);
3386 result = posix_fget_nt_acl(fsp, security_info,
3388 END_PROFILE(fget_nt_acl);
3392 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
3396 START_PROFILE(fset_nt_acl);
3397 result = set_nt_acl(fsp, security_info_sent, psd);
3398 END_PROFILE(fset_nt_acl);
3402 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
3403 struct smb_filename *file,
3404 struct security_acl *sacl,
3405 uint32_t access_requested,
3406 uint32_t access_denied)
3408 return NT_STATUS_OK; /* Nothing to do here ... */
3411 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
3413 SMB_ACL_TYPE_T type,
3414 TALLOC_CTX *mem_ctx)
3416 return sys_acl_get_fd(handle, fsp, type, mem_ctx);
3419 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle,
3421 SMB_ACL_TYPE_T type,
3424 return sys_acl_set_fd(handle, fsp, type, theacl);
3427 static int vfswrap_sys_acl_delete_def_fd(vfs_handle_struct *handle,
3430 return sys_acl_delete_def_fd(handle, fsp);
3433 /****************************************************************
3434 Extended attribute operations.
3435 *****************************************************************/
3437 struct vfswrap_getxattrat_state {
3438 struct tevent_context *ev;
3439 files_struct *dir_fsp;
3440 const struct smb_filename *smb_fname;
3443 * The following variables are talloced off "state" which is protected
3444 * by a destructor and thus are guaranteed to be safe to be used in the
3445 * job function in the worker thread.
3448 const char *xattr_name;
3449 uint8_t *xattr_value;
3450 struct security_unix_token *token;
3453 struct vfs_aio_state vfs_aio_state;
3454 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
3457 static int vfswrap_getxattrat_state_destructor(
3458 struct vfswrap_getxattrat_state *state)
3463 static void vfswrap_getxattrat_do_sync(struct tevent_req *req);
3464 static void vfswrap_getxattrat_do_async(void *private_data);
3465 static void vfswrap_getxattrat_done(struct tevent_req *subreq);
3467 static struct tevent_req *vfswrap_getxattrat_send(
3468 TALLOC_CTX *mem_ctx,
3469 struct tevent_context *ev,
3470 struct vfs_handle_struct *handle,
3471 files_struct *dir_fsp,
3472 const struct smb_filename *smb_fname,
3473 const char *xattr_name,
3476 struct tevent_req *req = NULL;
3477 struct tevent_req *subreq = NULL;
3478 struct vfswrap_getxattrat_state *state = NULL;
3479 size_t max_threads = 0;
3480 bool have_per_thread_cwd = false;
3481 bool have_per_thread_creds = false;
3482 bool do_async = false;
3484 req = tevent_req_create(mem_ctx, &state,
3485 struct vfswrap_getxattrat_state);
3489 *state = (struct vfswrap_getxattrat_state) {
3492 .smb_fname = smb_fname,
3495 max_threads = pthreadpool_tevent_max_threads(dir_fsp->conn->sconn->pool);
3496 if (max_threads >= 1) {
3498 * We need a non sync threadpool!
3500 have_per_thread_cwd = per_thread_cwd_supported();
3502 #ifdef HAVE_LINUX_THREAD_CREDENTIALS
3503 have_per_thread_creds = true;
3505 if (have_per_thread_cwd && have_per_thread_creds) {
3509 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat, profile_p,
3510 state->profile_bytes, 0);
3512 if (fsp_get_pathref_fd(dir_fsp) == -1) {
3513 DBG_ERR("Need a valid directory fd\n");
3514 tevent_req_error(req, EINVAL);
3515 return tevent_req_post(req, ev);
3518 if (alloc_hint > 0) {
3519 state->xattr_value = talloc_zero_array(state,
3522 if (tevent_req_nomem(state->xattr_value, req)) {
3523 return tevent_req_post(req, ev);
3528 vfswrap_getxattrat_do_sync(req);
3529 return tevent_req_post(req, ev);
3533 * Now allocate all parameters from a memory context that won't go away
3534 * no matter what. These paremeters will get used in threads and we
3535 * can't reliably cancel threads, so all buffers passed to the threads
3536 * must not be freed before all referencing threads terminate.
3539 state->name = talloc_strdup(state, smb_fname->base_name);
3540 if (tevent_req_nomem(state->name, req)) {
3541 return tevent_req_post(req, ev);
3544 state->xattr_name = talloc_strdup(state, xattr_name);
3545 if (tevent_req_nomem(state->xattr_name, req)) {
3546 return tevent_req_post(req, ev);
3550 * This is a hot codepath so at first glance one might think we should
3551 * somehow optimize away the token allocation and do a
3552 * talloc_reference() or similar black magic instead. But due to the
3553 * talloc_stackframe pool per SMB2 request this should be a simple copy
3554 * without a malloc in most cases.
3556 if (geteuid() == sec_initial_uid()) {
3557 state->token = root_unix_token(state);
3559 state->token = copy_unix_token(
3561 dir_fsp->conn->session_info->unix_token);
3563 if (tevent_req_nomem(state->token, req)) {
3564 return tevent_req_post(req, ev);
3567 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3569 subreq = pthreadpool_tevent_job_send(
3572 dir_fsp->conn->sconn->pool,
3573 vfswrap_getxattrat_do_async,
3575 if (tevent_req_nomem(subreq, req)) {
3576 return tevent_req_post(req, ev);
3578 tevent_req_set_callback(subreq, vfswrap_getxattrat_done, req);
3580 talloc_set_destructor(state, vfswrap_getxattrat_state_destructor);
3585 static void vfswrap_getxattrat_do_sync(struct tevent_req *req)
3587 struct vfswrap_getxattrat_state *state = tevent_req_data(
3588 req, struct vfswrap_getxattrat_state);
3590 char *tofree = NULL;
3591 char pathbuf[PATH_MAX+1];
3595 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
3596 state->smb_fname->base_name,
3601 if (pathlen == -1) {
3602 tevent_req_error(req, ENOMEM);
3606 state->xattr_size = getxattr(path,
3609 talloc_array_length(state->xattr_value));
3611 TALLOC_FREE(tofree);
3612 if (state->xattr_size == -1) {
3613 tevent_req_error(req, err);
3617 tevent_req_done(req);
3621 static void vfswrap_getxattrat_do_async(void *private_data)
3623 struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3624 private_data, struct vfswrap_getxattrat_state);
3625 struct timespec start_time;
3626 struct timespec end_time;
3629 PROFILE_TIMESTAMP(&start_time);
3630 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
3633 * Here we simulate a getxattrat()
3634 * call using fchdir();getxattr()
3637 per_thread_cwd_activate();
3639 /* Become the correct credential on this thread. */
3640 ret = set_thread_credentials(state->token->uid,
3642 (size_t)state->token->ngroups,
3643 state->token->groups);
3645 state->xattr_size = -1;
3646 state->vfs_aio_state.error = errno;
3650 ret = fchdir(fsp_get_pathref_fd(state->dir_fsp));
3652 state->xattr_size = -1;
3653 state->vfs_aio_state.error = errno;
3657 state->xattr_size = getxattr(state->name,
3660 talloc_array_length(state->xattr_value));
3661 if (state->xattr_size == -1) {
3662 state->vfs_aio_state.error = errno;
3666 PROFILE_TIMESTAMP(&end_time);
3667 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
3668 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3671 static void vfswrap_getxattrat_done(struct tevent_req *subreq)
3673 struct tevent_req *req = tevent_req_callback_data(
3674 subreq, struct tevent_req);
3675 struct vfswrap_getxattrat_state *state = tevent_req_data(
3676 req, struct vfswrap_getxattrat_state);
3681 * Make sure we run as the user again
3683 ok = change_to_user_and_service_by_fsp(state->dir_fsp);
3686 ret = pthreadpool_tevent_job_recv(subreq);
3687 TALLOC_FREE(subreq);
3688 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
3689 talloc_set_destructor(state, NULL);
3691 if (ret != EAGAIN) {
3692 tevent_req_error(req, ret);
3696 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
3697 * means the lower level pthreadpool failed to create a new
3698 * thread. Fallback to sync processing in that case to allow
3699 * some progress for the client.
3701 vfswrap_getxattrat_do_sync(req);
3705 if (state->xattr_size == -1) {
3706 tevent_req_error(req, state->vfs_aio_state.error);
3710 if (state->xattr_value == NULL) {
3712 * The caller only wanted the size.
3714 tevent_req_done(req);
3719 * shrink the buffer to the returned size.
3720 * (can't fail). It means NULL if size is 0.
3722 state->xattr_value = talloc_realloc(state,
3727 tevent_req_done(req);
3730 static ssize_t vfswrap_getxattrat_recv(struct tevent_req *req,
3731 struct vfs_aio_state *aio_state,
3732 TALLOC_CTX *mem_ctx,
3733 uint8_t **xattr_value)
3735 struct vfswrap_getxattrat_state *state = tevent_req_data(
3736 req, struct vfswrap_getxattrat_state);
3739 if (tevent_req_is_unix_error(req, &aio_state->error)) {
3740 tevent_req_received(req);
3744 *aio_state = state->vfs_aio_state;
3745 xattr_size = state->xattr_size;
3746 if (xattr_value != NULL) {
3747 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
3750 tevent_req_received(req);
3754 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle,
3755 struct files_struct *fsp,
3760 int fd = fsp_get_pathref_fd(fsp);
3762 if (!fsp->fsp_flags.is_pathref) {
3763 return fgetxattr(fd, name, value, size);
3766 if (fsp->fsp_flags.have_proc_fds) {
3767 const char *p = NULL;
3770 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3775 return getxattr(p, name, value, size);
3779 * This is no longer a handle based call.
3781 return getxattr(fsp->fsp_name->base_name, name, value, size);
3784 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
3786 int fd = fsp_get_pathref_fd(fsp);
3788 if (!fsp->fsp_flags.is_pathref) {
3789 return flistxattr(fd, list, size);
3792 if (fsp->fsp_flags.have_proc_fds) {
3793 const char *p = NULL;
3796 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3801 return listxattr(p, list, size);
3805 * This is no longer a handle based call.
3807 return listxattr(fsp->fsp_name->base_name, list, size);
3810 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
3812 int fd = fsp_get_pathref_fd(fsp);
3814 if (!fsp->fsp_flags.is_pathref) {
3815 return fremovexattr(fd, name);
3818 if (fsp->fsp_flags.have_proc_fds) {
3819 const char *p = NULL;
3822 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3827 return removexattr(p, name);
3831 * This is no longer a handle based call.
3833 return removexattr(fsp->fsp_name->base_name, name);
3836 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
3838 int fd = fsp_get_pathref_fd(fsp);
3840 if (!fsp->fsp_flags.is_pathref) {
3841 return fsetxattr(fd, name, value, size, flags);
3844 if (fsp->fsp_flags.have_proc_fds) {
3845 const char *p = NULL;
3848 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3853 return setxattr(p, name, value, size, flags);
3857 * This is no longer a handle based call.
3859 return setxattr(fsp->fsp_name->base_name, name, value, size, flags);
3862 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
3867 static bool vfswrap_is_offline(struct connection_struct *conn,
3868 const struct smb_filename *fname)
3872 bool offline = false;
3874 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
3878 if (!lp_dmapi_support(SNUM(conn)) || !dmapi_have_session()) {
3879 #if defined(ENOTSUP)
3885 status = get_full_smb_filename(talloc_tos(), fname, &path);
3886 if (!NT_STATUS_IS_OK(status)) {
3887 errno = map_errno_from_nt_status(status);
3891 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
3898 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
3899 struct files_struct *fsp,
3900 TALLOC_CTX *mem_ctx,
3903 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
3906 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
3907 struct files_struct *fsp,
3908 const DATA_BLOB old_cookie,
3909 TALLOC_CTX *mem_ctx,
3910 DATA_BLOB *new_cookie)
3912 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
3916 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
3917 struct smb_request *smb1req,
3918 struct smbXsrv_open *op,
3919 const DATA_BLOB old_cookie,
3920 TALLOC_CTX *mem_ctx,
3921 struct files_struct **fsp,
3922 DATA_BLOB *new_cookie)
3924 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
3925 old_cookie, mem_ctx,
3929 static struct vfs_fn_pointers vfs_default_fns = {
3930 /* Disk operations */
3932 .connect_fn = vfswrap_connect,
3933 .disconnect_fn = vfswrap_disconnect,
3934 .disk_free_fn = vfswrap_disk_free,
3935 .get_quota_fn = vfswrap_get_quota,
3936 .set_quota_fn = vfswrap_set_quota,
3937 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3938 .statvfs_fn = vfswrap_statvfs,
3939 .fs_capabilities_fn = vfswrap_fs_capabilities,
3940 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3941 .create_dfs_pathat_fn = vfswrap_create_dfs_pathat,
3942 .read_dfs_pathat_fn = vfswrap_read_dfs_pathat,
3943 .snap_check_path_fn = vfswrap_snap_check_path,
3944 .snap_create_fn = vfswrap_snap_create,
3945 .snap_delete_fn = vfswrap_snap_delete,
3947 /* Directory operations */
3949 .fdopendir_fn = vfswrap_fdopendir,
3950 .readdir_fn = vfswrap_readdir,
3951 .freaddir_attr_fn = vfswrap_freaddir_attr,
3952 .seekdir_fn = vfswrap_seekdir,
3953 .telldir_fn = vfswrap_telldir,
3954 .rewind_dir_fn = vfswrap_rewinddir,
3955 .mkdirat_fn = vfswrap_mkdirat,
3956 .closedir_fn = vfswrap_closedir,
3958 /* File operations */
3960 .openat_fn = vfswrap_openat,
3961 .create_file_fn = vfswrap_create_file,
3962 .close_fn = vfswrap_close,
3963 .pread_fn = vfswrap_pread,
3964 .pread_send_fn = vfswrap_pread_send,
3965 .pread_recv_fn = vfswrap_pread_recv,
3966 .pwrite_fn = vfswrap_pwrite,
3967 .pwrite_send_fn = vfswrap_pwrite_send,
3968 .pwrite_recv_fn = vfswrap_pwrite_recv,
3969 .lseek_fn = vfswrap_lseek,
3970 .sendfile_fn = vfswrap_sendfile,
3971 .recvfile_fn = vfswrap_recvfile,
3972 .renameat_fn = vfswrap_renameat,
3973 .fsync_send_fn = vfswrap_fsync_send,
3974 .fsync_recv_fn = vfswrap_fsync_recv,
3975 .stat_fn = vfswrap_stat,
3976 .fstat_fn = vfswrap_fstat,
3977 .lstat_fn = vfswrap_lstat,
3978 .get_alloc_size_fn = vfswrap_get_alloc_size,
3979 .unlinkat_fn = vfswrap_unlinkat,
3980 .fchmod_fn = vfswrap_fchmod,
3981 .fchown_fn = vfswrap_fchown,
3982 .lchown_fn = vfswrap_lchown,
3983 .chdir_fn = vfswrap_chdir,
3984 .getwd_fn = vfswrap_getwd,
3985 .fntimes_fn = vfswrap_fntimes,
3986 .ftruncate_fn = vfswrap_ftruncate,
3987 .fallocate_fn = vfswrap_fallocate,
3988 .lock_fn = vfswrap_lock,
3989 .kernel_flock_fn = vfswrap_kernel_flock,
3990 .fcntl_fn = vfswrap_fcntl,
3991 .linux_setlease_fn = vfswrap_linux_setlease,
3992 .getlock_fn = vfswrap_getlock,
3993 .symlinkat_fn = vfswrap_symlinkat,
3994 .readlinkat_fn = vfswrap_readlinkat,
3995 .linkat_fn = vfswrap_linkat,
3996 .mknodat_fn = vfswrap_mknodat,
3997 .realpath_fn = vfswrap_realpath,
3998 .fchflags_fn = vfswrap_fchflags,
3999 .file_id_create_fn = vfswrap_file_id_create,
4000 .fs_file_id_fn = vfswrap_fs_file_id,
4001 .fstreaminfo_fn = vfswrap_fstreaminfo,
4002 .get_real_filename_fn = vfswrap_get_real_filename,
4003 .connectpath_fn = vfswrap_connectpath,
4004 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
4005 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
4006 .strict_lock_check_fn = vfswrap_strict_lock_check,
4007 .translate_name_fn = vfswrap_translate_name,
4008 .parent_pathname_fn = vfswrap_parent_pathname,
4009 .fsctl_fn = vfswrap_fsctl,
4010 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
4011 .get_dos_attributes_send_fn = vfswrap_get_dos_attributes_send,
4012 .get_dos_attributes_recv_fn = vfswrap_get_dos_attributes_recv,
4013 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
4014 .offload_read_send_fn = vfswrap_offload_read_send,
4015 .offload_read_recv_fn = vfswrap_offload_read_recv,
4016 .offload_write_send_fn = vfswrap_offload_write_send,
4017 .offload_write_recv_fn = vfswrap_offload_write_recv,
4018 .fget_compression_fn = vfswrap_fget_compression,
4019 .set_compression_fn = vfswrap_set_compression,
4021 /* NT ACL operations. */
4023 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
4024 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
4025 .audit_file_fn = vfswrap_audit_file,
4027 /* POSIX ACL operations. */
4029 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
4030 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
4031 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
4032 .sys_acl_delete_def_fd_fn = vfswrap_sys_acl_delete_def_fd,
4034 /* EA operations. */
4035 .getxattrat_send_fn = vfswrap_getxattrat_send,
4036 .getxattrat_recv_fn = vfswrap_getxattrat_recv,
4037 .fgetxattr_fn = vfswrap_fgetxattr,
4038 .flistxattr_fn = vfswrap_flistxattr,
4039 .fremovexattr_fn = vfswrap_fremovexattr,
4040 .fsetxattr_fn = vfswrap_fsetxattr,
4042 /* aio operations */
4043 .aio_force_fn = vfswrap_aio_force,
4045 /* durable handle operations */
4046 .durable_cookie_fn = vfswrap_durable_cookie,
4047 .durable_disconnect_fn = vfswrap_durable_disconnect,
4048 .durable_reconnect_fn = vfswrap_durable_reconnect,
4052 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
4055 * Here we need to implement every call!
4057 * As this is the end of the vfs module chain.
4059 smb_vfs_assert_all_fns(&vfs_default_fns, DEFAULT_VFS_MODULE_NAME);
4060 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
4061 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);