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 struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
3081 const SMB_STRUCT_STAT *sbuf)
3085 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
3089 key.devid = sbuf->st_ex_dev;
3090 key.inode = sbuf->st_ex_ino;
3091 /* key.extid is unused by default. */
3096 static uint64_t vfswrap_fs_file_id(struct vfs_handle_struct *handle,
3097 const SMB_STRUCT_STAT *psbuf)
3101 if (!(psbuf->st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)) {
3102 return psbuf->st_ex_file_id;
3105 if (handle->conn->base_share_dev == psbuf->st_ex_dev) {
3106 return (uint64_t)psbuf->st_ex_ino;
3110 file_id = ((psbuf->st_ex_ino) & UINT32_MAX);
3113 file_id |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32;
3118 static NTSTATUS vfswrap_fstreaminfo(vfs_handle_struct *handle,
3119 struct files_struct *fsp,
3120 TALLOC_CTX *mem_ctx,
3121 unsigned int *pnum_streams,
3122 struct stream_struct **pstreams)
3124 struct stream_struct *tmp_streams = NULL;
3125 unsigned int num_streams = *pnum_streams;
3126 struct stream_struct *streams = *pstreams;
3129 if (fsp->fsp_flags.is_directory) {
3131 * No default streams on directories
3135 status = vfs_stat_fsp(fsp);
3136 if (!NT_STATUS_IS_OK(status)) {
3140 if (num_streams + 1 < 1) {
3142 return NT_STATUS_INVALID_PARAMETER;
3145 tmp_streams = talloc_realloc(mem_ctx,
3147 struct stream_struct,
3149 if (tmp_streams == NULL) {
3150 return NT_STATUS_NO_MEMORY;
3152 tmp_streams[num_streams].name = talloc_strdup(tmp_streams, "::$DATA");
3153 if (tmp_streams[num_streams].name == NULL) {
3154 return NT_STATUS_NO_MEMORY;
3156 tmp_streams[num_streams].size = fsp->fsp_name->st.st_ex_size;
3157 tmp_streams[num_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(
3160 &fsp->fsp_name->st);
3163 *pnum_streams = num_streams;
3164 *pstreams = tmp_streams;
3166 return NT_STATUS_OK;
3169 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
3170 const struct smb_filename *path,
3172 TALLOC_CTX *mem_ctx,
3176 * Don't fall back to get_real_filename so callers can differentiate
3177 * between a full directory scan and an actual case-insensitive stat.
3183 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
3184 const struct smb_filename *smb_fname)
3186 return handle->conn->connectpath;
3189 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
3190 struct byte_range_lock *br_lck,
3191 struct lock_struct *plock)
3193 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3195 /* Note: blr is not used in the default implementation. */
3196 return brl_lock_windows_default(br_lck, plock);
3199 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
3200 struct byte_range_lock *br_lck,
3201 const struct lock_struct *plock)
3203 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3205 return brl_unlock_windows_default(br_lck, plock);
3208 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
3210 struct lock_struct *plock)
3212 SMB_ASSERT(plock->lock_type == READ_LOCK ||
3213 plock->lock_type == WRITE_LOCK);
3215 return strict_lock_check_default(fsp, plock);
3218 /* NT ACL operations. */
3220 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
3222 uint32_t security_info,
3223 TALLOC_CTX *mem_ctx,
3224 struct security_descriptor **ppdesc)
3228 START_PROFILE(fget_nt_acl);
3229 result = posix_fget_nt_acl(fsp, security_info,
3231 END_PROFILE(fget_nt_acl);
3235 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
3239 START_PROFILE(fset_nt_acl);
3240 result = set_nt_acl(fsp, security_info_sent, psd);
3241 END_PROFILE(fset_nt_acl);
3245 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
3246 struct smb_filename *file,
3247 struct security_acl *sacl,
3248 uint32_t access_requested,
3249 uint32_t access_denied)
3251 return NT_STATUS_OK; /* Nothing to do here ... */
3254 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
3256 SMB_ACL_TYPE_T type,
3257 TALLOC_CTX *mem_ctx)
3259 return sys_acl_get_fd(handle, fsp, type, mem_ctx);
3262 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle,
3264 SMB_ACL_TYPE_T type,
3267 return sys_acl_set_fd(handle, fsp, type, theacl);
3270 static int vfswrap_sys_acl_delete_def_fd(vfs_handle_struct *handle,
3273 return sys_acl_delete_def_fd(handle, fsp);
3276 /****************************************************************
3277 Extended attribute operations.
3278 *****************************************************************/
3280 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
3281 const struct smb_filename *smb_fname,
3286 return getxattr(smb_fname->base_name, name, value, size);
3289 struct vfswrap_getxattrat_state {
3290 struct tevent_context *ev;
3291 files_struct *dir_fsp;
3292 const struct smb_filename *smb_fname;
3295 * The following variables are talloced off "state" which is protected
3296 * by a destructor and thus are guaranteed to be safe to be used in the
3297 * job function in the worker thread.
3300 const char *xattr_name;
3301 uint8_t *xattr_value;
3302 struct security_unix_token *token;
3305 struct vfs_aio_state vfs_aio_state;
3306 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
3309 static int vfswrap_getxattrat_state_destructor(
3310 struct vfswrap_getxattrat_state *state)
3315 static void vfswrap_getxattrat_do_sync(struct tevent_req *req);
3316 static void vfswrap_getxattrat_do_async(void *private_data);
3317 static void vfswrap_getxattrat_done(struct tevent_req *subreq);
3319 static struct tevent_req *vfswrap_getxattrat_send(
3320 TALLOC_CTX *mem_ctx,
3321 struct tevent_context *ev,
3322 struct vfs_handle_struct *handle,
3323 files_struct *dir_fsp,
3324 const struct smb_filename *smb_fname,
3325 const char *xattr_name,
3328 struct tevent_req *req = NULL;
3329 struct tevent_req *subreq = NULL;
3330 struct vfswrap_getxattrat_state *state = NULL;
3331 size_t max_threads = 0;
3332 bool have_per_thread_cwd = false;
3333 bool have_per_thread_creds = false;
3334 bool do_async = false;
3336 req = tevent_req_create(mem_ctx, &state,
3337 struct vfswrap_getxattrat_state);
3341 *state = (struct vfswrap_getxattrat_state) {
3344 .smb_fname = smb_fname,
3347 max_threads = pthreadpool_tevent_max_threads(dir_fsp->conn->sconn->pool);
3348 if (max_threads >= 1) {
3350 * We need a non sync threadpool!
3352 have_per_thread_cwd = per_thread_cwd_supported();
3354 #ifdef HAVE_LINUX_THREAD_CREDENTIALS
3355 have_per_thread_creds = true;
3357 if (have_per_thread_cwd && have_per_thread_creds) {
3361 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat, profile_p,
3362 state->profile_bytes, 0);
3364 if (fsp_get_pathref_fd(dir_fsp) == -1) {
3365 DBG_ERR("Need a valid directory fd\n");
3366 tevent_req_error(req, EINVAL);
3367 return tevent_req_post(req, ev);
3370 if (alloc_hint > 0) {
3371 state->xattr_value = talloc_zero_array(state,
3374 if (tevent_req_nomem(state->xattr_value, req)) {
3375 return tevent_req_post(req, ev);
3380 vfswrap_getxattrat_do_sync(req);
3381 return tevent_req_post(req, ev);
3385 * Now allocate all parameters from a memory context that won't go away
3386 * no matter what. These paremeters will get used in threads and we
3387 * can't reliably cancel threads, so all buffers passed to the threads
3388 * must not be freed before all referencing threads terminate.
3391 state->name = talloc_strdup(state, smb_fname->base_name);
3392 if (tevent_req_nomem(state->name, req)) {
3393 return tevent_req_post(req, ev);
3396 state->xattr_name = talloc_strdup(state, xattr_name);
3397 if (tevent_req_nomem(state->xattr_name, req)) {
3398 return tevent_req_post(req, ev);
3402 * This is a hot codepath so at first glance one might think we should
3403 * somehow optimize away the token allocation and do a
3404 * talloc_reference() or similar black magic instead. But due to the
3405 * talloc_stackframe pool per SMB2 request this should be a simple copy
3406 * without a malloc in most cases.
3408 if (geteuid() == sec_initial_uid()) {
3409 state->token = root_unix_token(state);
3411 state->token = copy_unix_token(
3413 dir_fsp->conn->session_info->unix_token);
3415 if (tevent_req_nomem(state->token, req)) {
3416 return tevent_req_post(req, ev);
3419 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3421 subreq = pthreadpool_tevent_job_send(
3424 dir_fsp->conn->sconn->pool,
3425 vfswrap_getxattrat_do_async,
3427 if (tevent_req_nomem(subreq, req)) {
3428 return tevent_req_post(req, ev);
3430 tevent_req_set_callback(subreq, vfswrap_getxattrat_done, req);
3432 talloc_set_destructor(state, vfswrap_getxattrat_state_destructor);
3437 static void vfswrap_getxattrat_do_sync(struct tevent_req *req)
3439 struct vfswrap_getxattrat_state *state = tevent_req_data(
3440 req, struct vfswrap_getxattrat_state);
3442 char *tofree = NULL;
3443 char pathbuf[PATH_MAX+1];
3447 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
3448 state->smb_fname->base_name,
3453 if (pathlen == -1) {
3454 tevent_req_error(req, ENOMEM);
3458 state->xattr_size = getxattr(path,
3461 talloc_array_length(state->xattr_value));
3463 TALLOC_FREE(tofree);
3464 if (state->xattr_size == -1) {
3465 tevent_req_error(req, err);
3469 tevent_req_done(req);
3473 static void vfswrap_getxattrat_do_async(void *private_data)
3475 struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3476 private_data, struct vfswrap_getxattrat_state);
3477 struct timespec start_time;
3478 struct timespec end_time;
3481 PROFILE_TIMESTAMP(&start_time);
3482 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
3485 * Here we simulate a getxattrat()
3486 * call using fchdir();getxattr()
3489 per_thread_cwd_activate();
3491 /* Become the correct credential on this thread. */
3492 ret = set_thread_credentials(state->token->uid,
3494 (size_t)state->token->ngroups,
3495 state->token->groups);
3497 state->xattr_size = -1;
3498 state->vfs_aio_state.error = errno;
3502 ret = fchdir(fsp_get_pathref_fd(state->dir_fsp));
3504 state->xattr_size = -1;
3505 state->vfs_aio_state.error = errno;
3509 state->xattr_size = getxattr(state->name,
3512 talloc_array_length(state->xattr_value));
3513 if (state->xattr_size == -1) {
3514 state->vfs_aio_state.error = errno;
3518 PROFILE_TIMESTAMP(&end_time);
3519 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
3520 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3523 static void vfswrap_getxattrat_done(struct tevent_req *subreq)
3525 struct tevent_req *req = tevent_req_callback_data(
3526 subreq, struct tevent_req);
3527 struct vfswrap_getxattrat_state *state = tevent_req_data(
3528 req, struct vfswrap_getxattrat_state);
3533 * Make sure we run as the user again
3535 ok = change_to_user_and_service_by_fsp(state->dir_fsp);
3538 ret = pthreadpool_tevent_job_recv(subreq);
3539 TALLOC_FREE(subreq);
3540 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
3541 talloc_set_destructor(state, NULL);
3543 if (ret != EAGAIN) {
3544 tevent_req_error(req, ret);
3548 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
3549 * means the lower level pthreadpool failed to create a new
3550 * thread. Fallback to sync processing in that case to allow
3551 * some progress for the client.
3553 vfswrap_getxattrat_do_sync(req);
3557 if (state->xattr_size == -1) {
3558 tevent_req_error(req, state->vfs_aio_state.error);
3562 if (state->xattr_value == NULL) {
3564 * The caller only wanted the size.
3566 tevent_req_done(req);
3571 * shrink the buffer to the returned size.
3572 * (can't fail). It means NULL if size is 0.
3574 state->xattr_value = talloc_realloc(state,
3579 tevent_req_done(req);
3582 static ssize_t vfswrap_getxattrat_recv(struct tevent_req *req,
3583 struct vfs_aio_state *aio_state,
3584 TALLOC_CTX *mem_ctx,
3585 uint8_t **xattr_value)
3587 struct vfswrap_getxattrat_state *state = tevent_req_data(
3588 req, struct vfswrap_getxattrat_state);
3591 if (tevent_req_is_unix_error(req, &aio_state->error)) {
3592 tevent_req_received(req);
3596 *aio_state = state->vfs_aio_state;
3597 xattr_size = state->xattr_size;
3598 if (xattr_value != NULL) {
3599 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
3602 tevent_req_received(req);
3606 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle,
3607 struct files_struct *fsp,
3612 int fd = fsp_get_pathref_fd(fsp);
3614 if (!fsp->fsp_flags.is_pathref) {
3615 return fgetxattr(fd, name, value, size);
3618 if (fsp->fsp_flags.have_proc_fds) {
3619 const char *p = NULL;
3622 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3627 return getxattr(p, name, value, size);
3631 * This is no longer a handle based call.
3633 return getxattr(fsp->fsp_name->base_name, name, value, size);
3636 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
3638 int fd = fsp_get_pathref_fd(fsp);
3640 if (!fsp->fsp_flags.is_pathref) {
3641 return flistxattr(fd, list, size);
3644 if (fsp->fsp_flags.have_proc_fds) {
3645 const char *p = NULL;
3648 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3653 return listxattr(p, list, size);
3657 * This is no longer a handle based call.
3659 return listxattr(fsp->fsp_name->base_name, list, size);
3662 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
3664 int fd = fsp_get_pathref_fd(fsp);
3666 if (!fsp->fsp_flags.is_pathref) {
3667 return fremovexattr(fd, name);
3670 if (fsp->fsp_flags.have_proc_fds) {
3671 const char *p = NULL;
3674 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3679 return removexattr(p, name);
3683 * This is no longer a handle based call.
3685 return removexattr(fsp->fsp_name->base_name, name);
3688 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
3690 int fd = fsp_get_pathref_fd(fsp);
3692 if (!fsp->fsp_flags.is_pathref) {
3693 return fsetxattr(fd, name, value, size, flags);
3696 if (fsp->fsp_flags.have_proc_fds) {
3697 const char *p = NULL;
3700 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3705 return setxattr(p, name, value, size, flags);
3709 * This is no longer a handle based call.
3711 return setxattr(fsp->fsp_name->base_name, name, value, size, flags);
3714 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
3719 static bool vfswrap_is_offline(struct connection_struct *conn,
3720 const struct smb_filename *fname)
3724 bool offline = false;
3726 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
3730 if (!lp_dmapi_support(SNUM(conn)) || !dmapi_have_session()) {
3731 #if defined(ENOTSUP)
3737 status = get_full_smb_filename(talloc_tos(), fname, &path);
3738 if (!NT_STATUS_IS_OK(status)) {
3739 errno = map_errno_from_nt_status(status);
3743 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
3750 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
3751 struct files_struct *fsp,
3752 TALLOC_CTX *mem_ctx,
3755 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
3758 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
3759 struct files_struct *fsp,
3760 const DATA_BLOB old_cookie,
3761 TALLOC_CTX *mem_ctx,
3762 DATA_BLOB *new_cookie)
3764 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
3768 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
3769 struct smb_request *smb1req,
3770 struct smbXsrv_open *op,
3771 const DATA_BLOB old_cookie,
3772 TALLOC_CTX *mem_ctx,
3773 struct files_struct **fsp,
3774 DATA_BLOB *new_cookie)
3776 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
3777 old_cookie, mem_ctx,
3781 static struct vfs_fn_pointers vfs_default_fns = {
3782 /* Disk operations */
3784 .connect_fn = vfswrap_connect,
3785 .disconnect_fn = vfswrap_disconnect,
3786 .disk_free_fn = vfswrap_disk_free,
3787 .get_quota_fn = vfswrap_get_quota,
3788 .set_quota_fn = vfswrap_set_quota,
3789 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3790 .statvfs_fn = vfswrap_statvfs,
3791 .fs_capabilities_fn = vfswrap_fs_capabilities,
3792 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3793 .create_dfs_pathat_fn = vfswrap_create_dfs_pathat,
3794 .read_dfs_pathat_fn = vfswrap_read_dfs_pathat,
3795 .snap_check_path_fn = vfswrap_snap_check_path,
3796 .snap_create_fn = vfswrap_snap_create,
3797 .snap_delete_fn = vfswrap_snap_delete,
3799 /* Directory operations */
3801 .fdopendir_fn = vfswrap_fdopendir,
3802 .readdir_fn = vfswrap_readdir,
3803 .freaddir_attr_fn = vfswrap_freaddir_attr,
3804 .seekdir_fn = vfswrap_seekdir,
3805 .telldir_fn = vfswrap_telldir,
3806 .rewind_dir_fn = vfswrap_rewinddir,
3807 .mkdirat_fn = vfswrap_mkdirat,
3808 .closedir_fn = vfswrap_closedir,
3810 /* File operations */
3812 .openat_fn = vfswrap_openat,
3813 .create_file_fn = vfswrap_create_file,
3814 .close_fn = vfswrap_close,
3815 .pread_fn = vfswrap_pread,
3816 .pread_send_fn = vfswrap_pread_send,
3817 .pread_recv_fn = vfswrap_pread_recv,
3818 .pwrite_fn = vfswrap_pwrite,
3819 .pwrite_send_fn = vfswrap_pwrite_send,
3820 .pwrite_recv_fn = vfswrap_pwrite_recv,
3821 .lseek_fn = vfswrap_lseek,
3822 .sendfile_fn = vfswrap_sendfile,
3823 .recvfile_fn = vfswrap_recvfile,
3824 .renameat_fn = vfswrap_renameat,
3825 .fsync_send_fn = vfswrap_fsync_send,
3826 .fsync_recv_fn = vfswrap_fsync_recv,
3827 .stat_fn = vfswrap_stat,
3828 .fstat_fn = vfswrap_fstat,
3829 .lstat_fn = vfswrap_lstat,
3830 .get_alloc_size_fn = vfswrap_get_alloc_size,
3831 .unlinkat_fn = vfswrap_unlinkat,
3832 .fchmod_fn = vfswrap_fchmod,
3833 .fchown_fn = vfswrap_fchown,
3834 .lchown_fn = vfswrap_lchown,
3835 .chdir_fn = vfswrap_chdir,
3836 .getwd_fn = vfswrap_getwd,
3837 .fntimes_fn = vfswrap_fntimes,
3838 .ftruncate_fn = vfswrap_ftruncate,
3839 .fallocate_fn = vfswrap_fallocate,
3840 .lock_fn = vfswrap_lock,
3841 .kernel_flock_fn = vfswrap_kernel_flock,
3842 .fcntl_fn = vfswrap_fcntl,
3843 .linux_setlease_fn = vfswrap_linux_setlease,
3844 .getlock_fn = vfswrap_getlock,
3845 .symlinkat_fn = vfswrap_symlinkat,
3846 .readlinkat_fn = vfswrap_readlinkat,
3847 .linkat_fn = vfswrap_linkat,
3848 .mknodat_fn = vfswrap_mknodat,
3849 .realpath_fn = vfswrap_realpath,
3850 .chflags_fn = vfswrap_chflags,
3851 .file_id_create_fn = vfswrap_file_id_create,
3852 .fs_file_id_fn = vfswrap_fs_file_id,
3853 .fstreaminfo_fn = vfswrap_fstreaminfo,
3854 .get_real_filename_fn = vfswrap_get_real_filename,
3855 .connectpath_fn = vfswrap_connectpath,
3856 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
3857 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3858 .strict_lock_check_fn = vfswrap_strict_lock_check,
3859 .translate_name_fn = vfswrap_translate_name,
3860 .parent_pathname_fn = vfswrap_parent_pathname,
3861 .fsctl_fn = vfswrap_fsctl,
3862 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
3863 .get_dos_attributes_send_fn = vfswrap_get_dos_attributes_send,
3864 .get_dos_attributes_recv_fn = vfswrap_get_dos_attributes_recv,
3865 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
3866 .offload_read_send_fn = vfswrap_offload_read_send,
3867 .offload_read_recv_fn = vfswrap_offload_read_recv,
3868 .offload_write_send_fn = vfswrap_offload_write_send,
3869 .offload_write_recv_fn = vfswrap_offload_write_recv,
3870 .fget_compression_fn = vfswrap_fget_compression,
3871 .set_compression_fn = vfswrap_set_compression,
3873 /* NT ACL operations. */
3875 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
3876 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
3877 .audit_file_fn = vfswrap_audit_file,
3879 /* POSIX ACL operations. */
3881 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3882 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3883 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3884 .sys_acl_delete_def_fd_fn = vfswrap_sys_acl_delete_def_fd,
3886 /* EA operations. */
3887 .getxattr_fn = vfswrap_getxattr,
3888 .getxattrat_send_fn = vfswrap_getxattrat_send,
3889 .getxattrat_recv_fn = vfswrap_getxattrat_recv,
3890 .fgetxattr_fn = vfswrap_fgetxattr,
3891 .flistxattr_fn = vfswrap_flistxattr,
3892 .fremovexattr_fn = vfswrap_fremovexattr,
3893 .fsetxattr_fn = vfswrap_fsetxattr,
3895 /* aio operations */
3896 .aio_force_fn = vfswrap_aio_force,
3898 /* durable handle operations */
3899 .durable_cookie_fn = vfswrap_durable_cookie,
3900 .durable_disconnect_fn = vfswrap_durable_disconnect,
3901 .durable_reconnect_fn = vfswrap_durable_reconnect,
3905 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3908 * Here we need to implement every call!
3910 * As this is the end of the vfs module chain.
3912 smb_vfs_assert_all_fns(&vfs_default_fns, DEFAULT_VFS_MODULE_NAME);
3913 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3914 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);