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 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
391 /* Form the msdfs_link contents */
392 msdfs_link = msdfs_link_string(frame,
395 if (msdfs_link == NULL) {
399 ret = symlinkat(msdfs_link,
400 fsp_get_io_fd(dirfsp),
401 smb_fname->base_name);
403 status = NT_STATUS_OK;
405 status = map_nt_error_from_unix(errno);
415 * Read and return the contents of a DFS redirect given a
416 * pathname. A caller can pass in NULL for ppreflist and
417 * preferral_count but still determine if this was a
418 * DFS redirect point by getting NT_STATUS_OK back
419 * without incurring the overhead of reading and parsing
420 * the referral contents.
423 static NTSTATUS vfswrap_read_dfs_pathat(struct vfs_handle_struct *handle,
425 struct files_struct *dirfsp,
426 struct smb_filename *smb_fname,
427 struct referral **ppreflist,
428 size_t *preferral_count)
430 NTSTATUS status = NT_STATUS_NO_MEMORY;
432 char *link_target = NULL;
435 #if defined(HAVE_BROKEN_READLINK)
436 char link_target_buf[PATH_MAX];
438 char link_target_buf[7];
442 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
444 if (is_named_stream(smb_fname)) {
445 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
449 if (ppreflist == NULL && preferral_count == NULL) {
451 * We're only checking if this is a DFS
452 * redirect. We don't need to return data.
454 bufsize = sizeof(link_target_buf);
455 link_target = link_target_buf;
458 link_target = talloc_array(mem_ctx, char, bufsize);
464 referral_len = readlinkat(fsp_get_io_fd(dirfsp),
465 smb_fname->base_name,
468 if (referral_len == -1) {
469 if (errno == EINVAL) {
471 * If the path isn't a link, readlinkat
472 * returns EINVAL. Allow the caller to
475 DBG_INFO("%s is not a link.\n", smb_fname->base_name);
476 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
478 status = map_nt_error_from_unix(errno);
479 DBG_ERR("Error reading "
480 "msdfs link %s: %s\n",
481 smb_fname->base_name,
486 link_target[referral_len] = '\0';
488 DBG_INFO("%s -> %s\n",
489 smb_fname->base_name,
492 if (!strnequal(link_target, "msdfs:", 6)) {
493 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
497 ret = sys_lstat(smb_fname->base_name,
499 lp_fake_directory_create_times(SNUM(handle->conn)));
501 status = map_nt_error_from_unix(errno);
505 if (ppreflist == NULL && preferral_count == NULL) {
506 /* Early return for checking if this is a DFS link. */
510 ok = parse_msdfs_symlink(mem_ctx,
511 lp_msdfs_shuffle_referrals(SNUM(handle->conn)),
517 status = NT_STATUS_OK;
519 status = NT_STATUS_NO_MEMORY;
524 if (link_target != link_target_buf) {
525 TALLOC_FREE(link_target);
530 static NTSTATUS vfswrap_snap_check_path(struct vfs_handle_struct *handle,
532 const char *service_path,
535 return NT_STATUS_NOT_SUPPORTED;
538 static NTSTATUS vfswrap_snap_create(struct vfs_handle_struct *handle,
540 const char *base_volume,
546 return NT_STATUS_NOT_SUPPORTED;
549 static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle,
554 return NT_STATUS_NOT_SUPPORTED;
557 /* Directory operations */
559 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
566 START_PROFILE(syscall_fdopendir);
567 result = sys_fdopendir(fsp_get_io_fd(fsp));
568 END_PROFILE(syscall_fdopendir);
573 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
574 struct files_struct *dirfsp,
576 SMB_STRUCT_STAT *sbuf)
578 struct dirent *result;
579 bool do_stat = false;
580 bool fake_ctime = lp_fake_directory_create_times(SNUM(handle->conn));
581 int flags = AT_SYMLINK_NOFOLLOW;
585 START_PROFILE(syscall_readdir);
587 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
591 result = readdir(dirp);
592 END_PROFILE(syscall_readdir);
597 if (result == NULL) {
602 * Default Posix readdir() does not give us stat info.
603 * Set to invalid to indicate we didn't return this info.
605 SET_STAT_INVALID(*sbuf);
607 /* See if we can efficiently return this. */
612 ret = fstatat(dirfd(dirp),
621 * As this is an optimization, ignore it if we stat'ed a
622 * symlink for non-POSIX context. Make the caller do it again
623 * as we don't know if they wanted the link info, or its
626 if (S_ISLNK(st.st_mode) &&
627 !(dirfsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH))
631 init_stat_ex_from_stat(sbuf, &st, fake_ctime);
636 static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
637 const struct smb_filename *fname,
639 struct readdir_attr_data **attr_data)
641 return NT_STATUS_NOT_SUPPORTED;
644 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
646 START_PROFILE(syscall_seekdir);
647 seekdir(dirp, offset);
648 END_PROFILE(syscall_seekdir);
651 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
654 START_PROFILE(syscall_telldir);
655 result = telldir(dirp);
656 END_PROFILE(syscall_telldir);
660 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
662 START_PROFILE(syscall_rewinddir);
664 END_PROFILE(syscall_rewinddir);
667 static int vfswrap_mkdirat(vfs_handle_struct *handle,
668 struct files_struct *dirfsp,
669 const struct smb_filename *smb_fname,
673 struct smb_filename *parent = NULL;
676 START_PROFILE(syscall_mkdirat);
678 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
680 if (lp_inherit_acls(SNUM(handle->conn))) {
681 ok = parent_smb_fname(talloc_tos(), smb_fname, &parent, NULL);
682 if (ok && directory_has_default_acl(handle->conn,
686 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
692 result = mkdirat(fsp_get_pathref_fd(dirfsp), smb_fname->base_name, mode);
694 END_PROFILE(syscall_mkdirat);
698 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
702 START_PROFILE(syscall_closedir);
703 result = closedir(dirp);
704 END_PROFILE(syscall_closedir);
708 /* File operations */
710 static int vfswrap_openat(vfs_handle_struct *handle,
711 const struct files_struct *dirfsp,
712 const struct smb_filename *smb_fname,
717 bool have_opath = false;
718 bool became_root = false;
721 START_PROFILE(syscall_openat);
723 if (is_named_stream(smb_fname)) {
731 if (fsp->fsp_flags.is_pathref) {
736 if (fsp->fsp_flags.is_pathref && !have_opath) {
741 result = openat(fsp_get_pathref_fd(dirfsp),
742 smb_fname->base_name,
750 fsp->fsp_flags.have_proc_fds = fsp->conn->have_proc_fds;
753 END_PROFILE(syscall_openat);
756 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
757 struct smb_request *req,
758 struct smb_filename *smb_fname,
759 uint32_t access_mask,
760 uint32_t share_access,
761 uint32_t create_disposition,
762 uint32_t create_options,
763 uint32_t file_attributes,
764 uint32_t oplock_request,
765 const struct smb2_lease *lease,
766 uint64_t allocation_size,
767 uint32_t private_flags,
768 struct security_descriptor *sd,
769 struct ea_list *ea_list,
770 files_struct **result,
772 const struct smb2_create_blobs *in_context_blobs,
773 struct smb2_create_blobs *out_context_blobs)
775 return create_file_default(handle->conn, req, smb_fname,
776 access_mask, share_access,
777 create_disposition, create_options,
778 file_attributes, oplock_request, lease,
779 allocation_size, private_flags,
781 pinfo, in_context_blobs, out_context_blobs);
784 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
788 START_PROFILE(syscall_close);
789 result = fd_close_posix(fsp);
790 END_PROFILE(syscall_close);
794 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
795 size_t n, off_t offset)
799 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
800 START_PROFILE_BYTES(syscall_pread, n);
801 result = sys_pread_full(fsp_get_io_fd(fsp), data, n, offset);
802 END_PROFILE_BYTES(syscall_pread);
804 if (result == -1 && errno == ESPIPE) {
805 /* Maintain the fiction that pipes can be seeked (sought?) on. */
806 result = sys_read(fsp_get_io_fd(fsp), data, n);
807 fh_set_pos(fsp->fh, 0);
810 #else /* HAVE_PREAD */
813 #endif /* HAVE_PREAD */
818 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
819 size_t n, off_t offset)
823 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
824 START_PROFILE_BYTES(syscall_pwrite, n);
825 result = sys_pwrite_full(fsp_get_io_fd(fsp), data, n, offset);
826 END_PROFILE_BYTES(syscall_pwrite);
828 if (result == -1 && errno == ESPIPE) {
829 /* Maintain the fiction that pipes can be sought on. */
830 result = sys_write(fsp_get_io_fd(fsp), data, n);
833 #else /* HAVE_PWRITE */
836 #endif /* HAVE_PWRITE */
841 struct vfswrap_pread_state {
848 struct vfs_aio_state vfs_aio_state;
849 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
852 static void vfs_pread_do(void *private_data);
853 static void vfs_pread_done(struct tevent_req *subreq);
854 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state);
856 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
858 struct tevent_context *ev,
859 struct files_struct *fsp,
861 size_t n, off_t offset)
863 struct tevent_req *req, *subreq;
864 struct vfswrap_pread_state *state;
866 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
872 state->fd = fsp_get_io_fd(fsp);
875 state->offset = offset;
877 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
878 state->profile_bytes, n);
879 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
881 subreq = pthreadpool_tevent_job_send(
882 state, ev, handle->conn->sconn->pool,
883 vfs_pread_do, state);
884 if (tevent_req_nomem(subreq, req)) {
885 return tevent_req_post(req, ev);
887 tevent_req_set_callback(subreq, vfs_pread_done, req);
889 talloc_set_destructor(state, vfs_pread_state_destructor);
894 static void vfs_pread_do(void *private_data)
896 struct vfswrap_pread_state *state = talloc_get_type_abort(
897 private_data, struct vfswrap_pread_state);
898 struct timespec start_time;
899 struct timespec end_time;
901 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
903 PROFILE_TIMESTAMP(&start_time);
905 state->ret = sys_pread_full(state->fd,
910 if (state->ret == -1) {
911 state->vfs_aio_state.error = errno;
914 PROFILE_TIMESTAMP(&end_time);
916 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
918 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
921 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state)
926 static void vfs_pread_done(struct tevent_req *subreq)
928 struct tevent_req *req = tevent_req_callback_data(
929 subreq, struct tevent_req);
930 struct vfswrap_pread_state *state = tevent_req_data(
931 req, struct vfswrap_pread_state);
934 ret = pthreadpool_tevent_job_recv(subreq);
936 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
937 talloc_set_destructor(state, NULL);
940 tevent_req_error(req, ret);
944 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
945 * means the lower level pthreadpool failed to create a new
946 * thread. Fallback to sync processing in that case to allow
947 * some progress for the client.
952 tevent_req_done(req);
955 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
956 struct vfs_aio_state *vfs_aio_state)
958 struct vfswrap_pread_state *state = tevent_req_data(
959 req, struct vfswrap_pread_state);
961 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
965 *vfs_aio_state = state->vfs_aio_state;
969 struct vfswrap_pwrite_state {
976 struct vfs_aio_state vfs_aio_state;
977 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
980 static void vfs_pwrite_do(void *private_data);
981 static void vfs_pwrite_done(struct tevent_req *subreq);
982 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state);
984 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
986 struct tevent_context *ev,
987 struct files_struct *fsp,
989 size_t n, off_t offset)
991 struct tevent_req *req, *subreq;
992 struct vfswrap_pwrite_state *state;
994 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
1000 state->fd = fsp_get_io_fd(fsp);
1003 state->offset = offset;
1005 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
1006 state->profile_bytes, n);
1007 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1009 subreq = pthreadpool_tevent_job_send(
1010 state, ev, handle->conn->sconn->pool,
1011 vfs_pwrite_do, state);
1012 if (tevent_req_nomem(subreq, req)) {
1013 return tevent_req_post(req, ev);
1015 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
1017 talloc_set_destructor(state, vfs_pwrite_state_destructor);
1022 static void vfs_pwrite_do(void *private_data)
1024 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
1025 private_data, struct vfswrap_pwrite_state);
1026 struct timespec start_time;
1027 struct timespec end_time;
1029 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
1031 PROFILE_TIMESTAMP(&start_time);
1033 state->ret = sys_pwrite_full(state->fd,
1038 if (state->ret == -1) {
1039 state->vfs_aio_state.error = errno;
1042 PROFILE_TIMESTAMP(&end_time);
1044 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1046 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1049 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state)
1054 static void vfs_pwrite_done(struct tevent_req *subreq)
1056 struct tevent_req *req = tevent_req_callback_data(
1057 subreq, struct tevent_req);
1058 struct vfswrap_pwrite_state *state = tevent_req_data(
1059 req, struct vfswrap_pwrite_state);
1062 ret = pthreadpool_tevent_job_recv(subreq);
1063 TALLOC_FREE(subreq);
1064 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1065 talloc_set_destructor(state, NULL);
1067 if (ret != EAGAIN) {
1068 tevent_req_error(req, ret);
1072 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1073 * means the lower level pthreadpool failed to create a new
1074 * thread. Fallback to sync processing in that case to allow
1075 * some progress for the client.
1077 vfs_pwrite_do(state);
1080 tevent_req_done(req);
1083 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
1084 struct vfs_aio_state *vfs_aio_state)
1086 struct vfswrap_pwrite_state *state = tevent_req_data(
1087 req, struct vfswrap_pwrite_state);
1089 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1093 *vfs_aio_state = state->vfs_aio_state;
1097 struct vfswrap_fsync_state {
1101 struct vfs_aio_state vfs_aio_state;
1102 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
1105 static void vfs_fsync_do(void *private_data);
1106 static void vfs_fsync_done(struct tevent_req *subreq);
1107 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state);
1109 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
1110 TALLOC_CTX *mem_ctx,
1111 struct tevent_context *ev,
1112 struct files_struct *fsp)
1114 struct tevent_req *req, *subreq;
1115 struct vfswrap_fsync_state *state;
1117 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
1123 state->fd = fsp_get_io_fd(fsp);
1125 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_fsync, profile_p,
1126 state->profile_bytes, 0);
1127 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1129 subreq = pthreadpool_tevent_job_send(
1130 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
1131 if (tevent_req_nomem(subreq, req)) {
1132 return tevent_req_post(req, ev);
1134 tevent_req_set_callback(subreq, vfs_fsync_done, req);
1136 talloc_set_destructor(state, vfs_fsync_state_destructor);
1141 static void vfs_fsync_do(void *private_data)
1143 struct vfswrap_fsync_state *state = talloc_get_type_abort(
1144 private_data, struct vfswrap_fsync_state);
1145 struct timespec start_time;
1146 struct timespec end_time;
1148 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
1150 PROFILE_TIMESTAMP(&start_time);
1153 state->ret = fsync(state->fd);
1154 } while ((state->ret == -1) && (errno == EINTR));
1156 if (state->ret == -1) {
1157 state->vfs_aio_state.error = errno;
1160 PROFILE_TIMESTAMP(&end_time);
1162 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1164 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1167 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state)
1172 static void vfs_fsync_done(struct tevent_req *subreq)
1174 struct tevent_req *req = tevent_req_callback_data(
1175 subreq, struct tevent_req);
1176 struct vfswrap_fsync_state *state = tevent_req_data(
1177 req, struct vfswrap_fsync_state);
1180 ret = pthreadpool_tevent_job_recv(subreq);
1181 TALLOC_FREE(subreq);
1182 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1183 talloc_set_destructor(state, NULL);
1185 if (ret != EAGAIN) {
1186 tevent_req_error(req, ret);
1190 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1191 * means the lower level pthreadpool failed to create a new
1192 * thread. Fallback to sync processing in that case to allow
1193 * some progress for the client.
1195 vfs_fsync_do(state);
1198 tevent_req_done(req);
1201 static int vfswrap_fsync_recv(struct tevent_req *req,
1202 struct vfs_aio_state *vfs_aio_state)
1204 struct vfswrap_fsync_state *state = tevent_req_data(
1205 req, struct vfswrap_fsync_state);
1207 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1211 *vfs_aio_state = state->vfs_aio_state;
1215 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1219 START_PROFILE(syscall_lseek);
1221 result = lseek(fsp_get_io_fd(fsp), offset, whence);
1223 * We want to maintain the fiction that we can seek
1224 * on a fifo for file system purposes. This allows
1225 * people to set up UNIX fifo's that feed data to Windows
1226 * applications. JRA.
1229 if((result == -1) && (errno == ESPIPE)) {
1234 END_PROFILE(syscall_lseek);
1238 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1239 off_t offset, size_t n)
1243 START_PROFILE_BYTES(syscall_sendfile, n);
1244 result = sys_sendfile(tofd, fsp_get_io_fd(fromfsp), hdr, offset, n);
1245 END_PROFILE_BYTES(syscall_sendfile);
1249 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1251 files_struct *tofsp,
1257 START_PROFILE_BYTES(syscall_recvfile, n);
1258 result = sys_recvfile(fromfd, fsp_get_io_fd(tofsp), offset, n);
1259 END_PROFILE_BYTES(syscall_recvfile);
1263 static int vfswrap_renameat(vfs_handle_struct *handle,
1264 files_struct *srcfsp,
1265 const struct smb_filename *smb_fname_src,
1266 files_struct *dstfsp,
1267 const struct smb_filename *smb_fname_dst)
1271 START_PROFILE(syscall_renameat);
1273 if (is_named_stream(smb_fname_src) || is_named_stream(smb_fname_dst)) {
1278 result = renameat(fsp_get_pathref_fd(srcfsp),
1279 smb_fname_src->base_name,
1280 fsp_get_pathref_fd(dstfsp),
1281 smb_fname_dst->base_name);
1284 END_PROFILE(syscall_renameat);
1288 static int vfswrap_stat(vfs_handle_struct *handle,
1289 struct smb_filename *smb_fname)
1293 START_PROFILE(syscall_stat);
1295 if (is_named_stream(smb_fname)) {
1300 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1301 lp_fake_directory_create_times(SNUM(handle->conn)));
1303 END_PROFILE(syscall_stat);
1307 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1311 START_PROFILE(syscall_fstat);
1312 result = sys_fstat(fsp_get_pathref_fd(fsp),
1313 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1314 END_PROFILE(syscall_fstat);
1318 static int vfswrap_lstat(vfs_handle_struct *handle,
1319 struct smb_filename *smb_fname)
1323 START_PROFILE(syscall_lstat);
1325 if (is_named_stream(smb_fname)) {
1330 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1331 lp_fake_directory_create_times(SNUM(handle->conn)));
1333 END_PROFILE(syscall_lstat);
1337 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1339 enum vfs_translate_direction direction,
1340 TALLOC_CTX *mem_ctx,
1343 return NT_STATUS_NONE_MAPPED;
1347 * Implement the default fsctl operation.
1349 static bool vfswrap_logged_ioctl_message = false;
1351 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1352 struct files_struct *fsp,
1355 uint16_t req_flags, /* Needed for UNICODE ... */
1356 const uint8_t *_in_data,
1358 uint8_t **_out_data,
1359 uint32_t max_out_len,
1362 const char *in_data = (const char *)_in_data;
1363 char **out_data = (char **)_out_data;
1367 case FSCTL_SET_SPARSE:
1369 bool set_sparse = true;
1371 if (in_len >= 1 && in_data[0] == 0) {
1375 status = file_set_sparse(handle->conn, fsp, set_sparse);
1377 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1378 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1379 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1380 nt_errstr(status)));
1385 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1387 unsigned char objid[16];
1388 char *return_data = NULL;
1390 /* This should return the object-id on this file.
1391 * I think I'll make this be the inode+dev. JRA.
1394 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1395 fsp_fnum_dbg(fsp)));
1397 *out_len = MIN(max_out_len, 64);
1399 /* Hmmm, will this cause problems if less data asked for? */
1400 return_data = talloc_array(ctx, char, 64);
1401 if (return_data == NULL) {
1402 return NT_STATUS_NO_MEMORY;
1405 /* For backwards compatibility only store the dev/inode. */
1406 push_file_id_16(return_data, &fsp->file_id);
1407 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1408 push_file_id_16(return_data+32, &fsp->file_id);
1409 memset(return_data+48, 0, 16);
1410 *out_data = return_data;
1411 return NT_STATUS_OK;
1414 case FSCTL_GET_REPARSE_POINT:
1416 status = fsctl_get_reparse_point(
1417 fsp, ctx, out_data, max_out_len, out_len);
1421 case FSCTL_SET_REPARSE_POINT:
1423 status = fsctl_set_reparse_point(fsp, ctx, _in_data, in_len);
1427 case FSCTL_DELETE_REPARSE_POINT:
1429 status = fsctl_del_reparse_point(fsp, ctx, _in_data, in_len);
1433 case FSCTL_GET_SHADOW_COPY_DATA:
1436 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1437 * and return their volume names. If max_data_count is 16, then it is just
1438 * asking for the number of volumes and length of the combined names.
1440 * pdata is the data allocated by our caller, but that uses
1441 * total_data_count (which is 0 in our case) rather than max_data_count.
1442 * Allocate the correct amount and return the pointer to let
1443 * it be deallocated when we return.
1445 struct shadow_copy_data *shadow_data = NULL;
1446 bool labels = False;
1447 uint32_t labels_data_count = 0;
1449 char *cur_pdata = NULL;
1451 if (max_out_len < 16) {
1452 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1454 return NT_STATUS_INVALID_PARAMETER;
1457 if (max_out_len > 16) {
1461 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1462 if (shadow_data == NULL) {
1463 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1464 return NT_STATUS_NO_MEMORY;
1468 * Call the VFS routine to actually do the work.
1470 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1473 /* broken module didn't set errno on error */
1474 status = NT_STATUS_UNSUCCESSFUL;
1476 status = map_nt_error_from_unix(errno);
1477 if (NT_STATUS_EQUAL(status,
1478 NT_STATUS_NOT_SUPPORTED)) {
1482 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1483 "connectpath %s, failed - %s.\n",
1484 fsp->conn->connectpath,
1485 nt_errstr(status)));
1486 TALLOC_FREE(shadow_data);
1490 labels_data_count = (shadow_data->num_volumes * 2 *
1491 sizeof(SHADOW_COPY_LABEL)) + 2;
1496 *out_len = 12 + labels_data_count;
1499 if (max_out_len < *out_len) {
1500 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1501 max_out_len, *out_len));
1502 TALLOC_FREE(shadow_data);
1503 return NT_STATUS_BUFFER_TOO_SMALL;
1506 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1507 if (cur_pdata == NULL) {
1508 TALLOC_FREE(shadow_data);
1509 return NT_STATUS_NO_MEMORY;
1512 *out_data = cur_pdata;
1514 /* num_volumes 4 bytes */
1515 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1518 /* num_labels 4 bytes */
1519 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1522 /* needed_data_count 4 bytes */
1523 SIVAL(cur_pdata, 8, labels_data_count);
1527 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1528 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1529 if (labels && shadow_data->labels) {
1530 for (i=0; i<shadow_data->num_volumes; i++) {
1532 status = srvstr_push(cur_pdata, req_flags,
1533 cur_pdata, shadow_data->labels[i],
1534 2 * sizeof(SHADOW_COPY_LABEL),
1535 STR_UNICODE|STR_TERMINATE, &len);
1536 if (!NT_STATUS_IS_OK(status)) {
1537 TALLOC_FREE(*out_data);
1538 TALLOC_FREE(shadow_data);
1541 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1542 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1546 TALLOC_FREE(shadow_data);
1548 return NT_STATUS_OK;
1551 case FSCTL_FIND_FILES_BY_SID:
1553 /* pretend this succeeded -
1555 * we have to send back a list with all files owned by this SID
1557 * but I have to check that --metze
1561 struct dom_sid_buf buf;
1565 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1566 fsp_fnum_dbg(fsp)));
1569 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1570 return NT_STATUS_INVALID_PARAMETER;
1573 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1575 /* unknown 4 bytes: this is not the length of the sid :-( */
1576 /*unknown = IVAL(pdata,0);*/
1578 ret = sid_parse(_in_data + 4, sid_len, &sid);
1580 return NT_STATUS_INVALID_PARAMETER;
1582 DEBUGADD(10, ("for SID: %s\n",
1583 dom_sid_str_buf(&sid, &buf)));
1585 if (!sid_to_uid(&sid, &uid)) {
1586 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1587 dom_sid_str_buf(&sid, &buf),
1588 (unsigned long)sid_len));
1592 /* we can take a look at the find source :-)
1594 * find ./ -uid $uid -name '*' is what we need here
1597 * and send 4bytes len and then NULL terminated unicode strings
1600 * but I don't know how to deal with the paged results
1601 * (maybe we can hang the result anywhere in the fsp struct)
1603 * but I don't know how to deal with the paged results
1604 * (maybe we can hang the result anywhere in the fsp struct)
1606 * we don't send all files at once
1607 * and at the next we should *not* start from the beginning,
1608 * so we have to cache the result
1613 /* this works for now... */
1614 return NT_STATUS_OK;
1617 case FSCTL_QUERY_ALLOCATED_RANGES:
1619 /* FIXME: This is just a dummy reply, telling that all of the
1620 * file is allocated. MKS cp needs that.
1621 * Adding the real allocated ranges via FIEMAP on Linux
1622 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1623 * this FSCTL correct for sparse files.
1625 uint64_t offset, length;
1626 char *out_data_tmp = NULL;
1629 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1631 return NT_STATUS_INVALID_PARAMETER;
1634 if (max_out_len < 16) {
1635 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1637 return NT_STATUS_INVALID_PARAMETER;
1640 offset = BVAL(in_data,0);
1641 length = BVAL(in_data,8);
1643 if (offset + length < offset) {
1644 /* No 64-bit integer wrap. */
1645 return NT_STATUS_INVALID_PARAMETER;
1648 /* Shouldn't this be SMB_VFS_STAT ... ? */
1649 status = vfs_stat_fsp(fsp);
1650 if (!NT_STATUS_IS_OK(status)) {
1655 out_data_tmp = talloc_array(ctx, char, *out_len);
1656 if (out_data_tmp == NULL) {
1657 DEBUG(10, ("unable to allocate memory for response\n"));
1658 return NT_STATUS_NO_MEMORY;
1661 if (offset > fsp->fsp_name->st.st_ex_size ||
1662 fsp->fsp_name->st.st_ex_size == 0 ||
1664 memset(out_data_tmp, 0, *out_len);
1666 uint64_t end = offset + length;
1667 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1668 SBVAL(out_data_tmp, 0, 0);
1669 SBVAL(out_data_tmp, 8, end);
1672 *out_data = out_data_tmp;
1674 return NT_STATUS_OK;
1677 case FSCTL_IS_VOLUME_DIRTY:
1679 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1680 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1682 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1683 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1685 return NT_STATUS_INVALID_PARAMETER;
1690 * Only print once ... unfortunately there could be lots of
1691 * different FSCTLs that are called.
1693 if (!vfswrap_logged_ioctl_message) {
1694 vfswrap_logged_ioctl_message = true;
1695 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1696 __func__, function));
1700 return NT_STATUS_NOT_SUPPORTED;
1703 static bool vfswrap_is_offline(struct connection_struct *conn,
1704 const struct smb_filename *fname);
1706 struct vfswrap_get_dos_attributes_state {
1707 struct vfs_aio_state aio_state;
1708 connection_struct *conn;
1709 TALLOC_CTX *mem_ctx;
1710 struct tevent_context *ev;
1711 files_struct *dir_fsp;
1712 struct smb_filename *smb_fname;
1717 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq);
1719 static struct tevent_req *vfswrap_get_dos_attributes_send(
1720 TALLOC_CTX *mem_ctx,
1721 struct tevent_context *ev,
1722 struct vfs_handle_struct *handle,
1723 files_struct *dir_fsp,
1724 struct smb_filename *smb_fname)
1726 struct tevent_req *req = NULL;
1727 struct tevent_req *subreq = NULL;
1728 struct vfswrap_get_dos_attributes_state *state = NULL;
1730 req = tevent_req_create(mem_ctx, &state,
1731 struct vfswrap_get_dos_attributes_state);
1736 *state = (struct vfswrap_get_dos_attributes_state) {
1737 .conn = dir_fsp->conn,
1741 .smb_fname = smb_fname,
1744 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1748 SAMBA_XATTR_DOS_ATTRIB,
1750 if (tevent_req_nomem(subreq, req)) {
1751 return tevent_req_post(req, ev);
1753 tevent_req_set_callback(subreq,
1754 vfswrap_get_dos_attributes_getxattr_done,
1760 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq)
1762 struct tevent_req *req =
1763 tevent_req_callback_data(subreq,
1765 struct vfswrap_get_dos_attributes_state *state =
1766 tevent_req_data(req,
1767 struct vfswrap_get_dos_attributes_state);
1769 DATA_BLOB blob = {0};
1771 char *tofree = NULL;
1772 char pathbuf[PATH_MAX+1];
1774 struct smb_filename smb_fname;
1778 xattr_size = SMB_VFS_GETXATTRAT_RECV(subreq,
1782 TALLOC_FREE(subreq);
1783 if (xattr_size == -1) {
1784 status = map_nt_error_from_unix(state->aio_state.error);
1786 if (state->as_root) {
1787 tevent_req_nterror(req, status);
1790 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1791 tevent_req_nterror(req, status);
1795 state->as_root = true;
1798 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1802 SAMBA_XATTR_DOS_ATTRIB,
1805 if (tevent_req_nomem(subreq, req)) {
1808 tevent_req_set_callback(subreq,
1809 vfswrap_get_dos_attributes_getxattr_done,
1814 blob.length = xattr_size;
1816 status = parse_dos_attribute_blob(state->smb_fname,
1819 if (!NT_STATUS_IS_OK(status)) {
1820 tevent_req_nterror(req, status);
1824 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
1825 state->smb_fname->base_name,
1830 if (pathlen == -1) {
1831 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1835 smb_fname = (struct smb_filename) {
1837 .st = state->smb_fname->st,
1838 .flags = state->smb_fname->flags,
1839 .twrp = state->smb_fname->twrp,
1842 offline = vfswrap_is_offline(state->conn, &smb_fname);
1844 state->dosmode |= FILE_ATTRIBUTE_OFFLINE;
1846 TALLOC_FREE(tofree);
1848 tevent_req_done(req);
1852 static NTSTATUS vfswrap_get_dos_attributes_recv(struct tevent_req *req,
1853 struct vfs_aio_state *aio_state,
1856 struct vfswrap_get_dos_attributes_state *state =
1857 tevent_req_data(req,
1858 struct vfswrap_get_dos_attributes_state);
1861 if (tevent_req_is_nterror(req, &status)) {
1862 tevent_req_received(req);
1866 *aio_state = state->aio_state;
1867 *dosmode = state->dosmode;
1868 tevent_req_received(req);
1869 return NT_STATUS_OK;
1872 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1873 struct files_struct *fsp,
1878 offline = vfswrap_is_offline(handle->conn, fsp->fsp_name);
1880 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1883 return fget_ea_dos_attribute(fsp, dosmode);
1886 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1887 const struct smb_filename *smb_fname,
1890 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1893 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1894 struct files_struct *fsp,
1897 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1900 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1902 struct vfswrap_offload_read_state {
1906 static struct tevent_req *vfswrap_offload_read_send(
1907 TALLOC_CTX *mem_ctx,
1908 struct tevent_context *ev,
1909 struct vfs_handle_struct *handle,
1910 struct files_struct *fsp,
1916 struct tevent_req *req = NULL;
1917 struct vfswrap_offload_read_state *state = NULL;
1920 req = tevent_req_create(mem_ctx, &state,
1921 struct vfswrap_offload_read_state);
1926 status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1927 &vfswrap_offload_ctx);
1928 if (tevent_req_nterror(req, status)) {
1929 return tevent_req_post(req, ev);
1932 if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1933 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1934 return tevent_req_post(req, ev);
1937 status = vfs_offload_token_create_blob(state, fsp, fsctl,
1939 if (tevent_req_nterror(req, status)) {
1940 return tevent_req_post(req, ev);
1943 status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1945 if (tevent_req_nterror(req, status)) {
1946 return tevent_req_post(req, ev);
1949 tevent_req_done(req);
1950 return tevent_req_post(req, ev);
1953 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
1954 struct vfs_handle_struct *handle,
1955 TALLOC_CTX *mem_ctx,
1958 struct vfswrap_offload_read_state *state = tevent_req_data(
1959 req, struct vfswrap_offload_read_state);
1962 if (tevent_req_is_nterror(req, &status)) {
1963 tevent_req_received(req);
1967 token->length = state->token.length;
1968 token->data = talloc_move(mem_ctx, &state->token.data);
1970 tevent_req_received(req);
1971 return NT_STATUS_OK;
1974 struct vfswrap_offload_write_state {
1976 bool read_lck_locked;
1977 bool write_lck_locked;
1979 struct tevent_context *src_ev;
1980 struct files_struct *src_fsp;
1982 struct tevent_context *dst_ev;
1983 struct files_struct *dst_fsp;
1987 size_t next_io_size;
1990 static void vfswrap_offload_write_cleanup(struct tevent_req *req,
1991 enum tevent_req_state req_state)
1993 struct vfswrap_offload_write_state *state = tevent_req_data(
1994 req, struct vfswrap_offload_write_state);
1997 if (state->dst_fsp == NULL) {
2001 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2003 state->dst_fsp = NULL;
2006 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
2008 static struct tevent_req *vfswrap_offload_write_send(
2009 struct vfs_handle_struct *handle,
2010 TALLOC_CTX *mem_ctx,
2011 struct tevent_context *ev,
2014 off_t transfer_offset,
2015 struct files_struct *dest_fsp,
2019 struct tevent_req *req;
2020 struct vfswrap_offload_write_state *state = NULL;
2021 /* off_t is signed! */
2022 off_t max_offset = INT64_MAX - to_copy;
2023 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
2024 files_struct *src_fsp = NULL;
2028 req = tevent_req_create(mem_ctx, &state,
2029 struct vfswrap_offload_write_state);
2034 *state = (struct vfswrap_offload_write_state) {
2036 .src_off = transfer_offset,
2038 .dst_fsp = dest_fsp,
2039 .dst_off = dest_off,
2041 .remaining = to_copy,
2044 tevent_req_set_cleanup_fn(req, vfswrap_offload_write_cleanup);
2047 case FSCTL_SRV_COPYCHUNK:
2048 case FSCTL_SRV_COPYCHUNK_WRITE:
2051 case FSCTL_OFFLOAD_WRITE:
2052 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
2053 return tevent_req_post(req, ev);
2055 case FSCTL_DUP_EXTENTS_TO_FILE:
2056 DBG_DEBUG("COW clones not supported by vfs_default\n");
2057 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2058 return tevent_req_post(req, ev);
2061 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2062 return tevent_req_post(req, ev);
2066 * From here on we assume a copy-chunk fsctl
2070 tevent_req_done(req);
2071 return tevent_req_post(req, ev);
2074 if (state->src_off > max_offset) {
2076 * Protect integer checks below.
2078 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2079 return tevent_req_post(req, ev);
2081 if (state->src_off < 0) {
2083 * Protect integer checks below.
2085 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2086 return tevent_req_post(req, ev);
2088 if (state->dst_off > max_offset) {
2090 * Protect integer checks below.
2092 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2093 return tevent_req_post(req, ev);
2095 if (state->dst_off < 0) {
2097 * Protect integer checks below.
2099 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2100 return tevent_req_post(req, ev);
2103 status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
2105 if (tevent_req_nterror(req, status)) {
2106 return tevent_req_post(req, ev);
2109 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
2111 status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
2112 if (!NT_STATUS_IS_OK(status)) {
2113 tevent_req_nterror(req, status);
2114 return tevent_req_post(req, ev);
2117 ok = change_to_user_and_service_by_fsp(src_fsp);
2119 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2120 return tevent_req_post(req, ev);
2123 state->src_ev = src_fsp->conn->sconn->ev_ctx;
2124 state->src_fsp = src_fsp;
2126 status = vfs_stat_fsp(src_fsp);
2127 if (tevent_req_nterror(req, status)) {
2128 return tevent_req_post(req, ev);
2131 if (src_fsp->fsp_name->st.st_ex_size < state->src_off + to_copy) {
2133 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
2134 * If the SourceOffset or SourceOffset + Length extends beyond
2135 * the end of file, the server SHOULD<240> treat this as a
2136 * STATUS_END_OF_FILE error.
2138 * <240> Section 3.3.5.15.6: Windows servers will return
2139 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
2141 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
2142 return tevent_req_post(req, ev);
2145 state->buf = talloc_array(state, uint8_t, num);
2146 if (tevent_req_nomem(state->buf, req)) {
2147 return tevent_req_post(req, ev);
2150 status = vfswrap_offload_write_loop(req);
2151 if (!NT_STATUS_IS_OK(status)) {
2152 tevent_req_nterror(req, status);
2153 return tevent_req_post(req, ev);
2159 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
2161 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
2163 struct vfswrap_offload_write_state *state = tevent_req_data(
2164 req, struct vfswrap_offload_write_state);
2165 struct tevent_req *subreq = NULL;
2166 struct lock_struct read_lck;
2170 * This is called under the context of state->src_fsp.
2173 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
2175 init_strict_lock_struct(state->src_fsp,
2176 state->src_fsp->op->global->open_persistent_id,
2178 state->next_io_size,
2182 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
2186 return NT_STATUS_FILE_LOCK_CONFLICT;
2189 subreq = SMB_VFS_PREAD_SEND(state,
2193 state->next_io_size,
2195 if (subreq == NULL) {
2196 return NT_STATUS_NO_MEMORY;
2198 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
2200 return NT_STATUS_OK;
2203 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
2205 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
2207 struct tevent_req *req = tevent_req_callback_data(
2208 subreq, struct tevent_req);
2209 struct vfswrap_offload_write_state *state = tevent_req_data(
2210 req, struct vfswrap_offload_write_state);
2211 struct vfs_aio_state aio_state;
2212 struct lock_struct write_lck;
2216 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
2217 TALLOC_FREE(subreq);
2219 DBG_ERR("read failed: %s\n", strerror(aio_state.error));
2220 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2223 if (nread != state->next_io_size) {
2224 DBG_ERR("Short read, only %zd of %zu\n",
2225 nread, state->next_io_size);
2226 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2230 state->src_off += nread;
2232 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2234 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2238 init_strict_lock_struct(state->dst_fsp,
2239 state->dst_fsp->op->global->open_persistent_id,
2241 state->next_io_size,
2245 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
2249 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
2253 subreq = SMB_VFS_PWRITE_SEND(state,
2257 state->next_io_size,
2259 if (subreq == NULL) {
2260 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2263 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
2266 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
2268 struct tevent_req *req = tevent_req_callback_data(
2269 subreq, struct tevent_req);
2270 struct vfswrap_offload_write_state *state = tevent_req_data(
2271 req, struct vfswrap_offload_write_state);
2272 struct vfs_aio_state aio_state;
2277 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
2278 TALLOC_FREE(subreq);
2279 if (nwritten == -1) {
2280 DBG_ERR("write failed: %s\n", strerror(aio_state.error));
2281 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2284 if (nwritten != state->next_io_size) {
2285 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
2286 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2290 state->dst_off += nwritten;
2292 if (state->remaining < nwritten) {
2293 /* Paranoia check */
2294 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2297 state->remaining -= nwritten;
2298 if (state->remaining == 0) {
2299 tevent_req_done(req);
2303 ok = change_to_user_and_service_by_fsp(state->src_fsp);
2305 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2309 status = vfswrap_offload_write_loop(req);
2310 if (!NT_STATUS_IS_OK(status)) {
2311 tevent_req_nterror(req, status);
2318 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
2319 struct tevent_req *req,
2322 struct vfswrap_offload_write_state *state = tevent_req_data(
2323 req, struct vfswrap_offload_write_state);
2326 if (tevent_req_is_nterror(req, &status)) {
2327 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
2329 tevent_req_received(req);
2333 *copied = state->to_copy;
2334 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
2335 tevent_req_received(req);
2337 return NT_STATUS_OK;
2340 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
2341 TALLOC_CTX *mem_ctx,
2342 struct files_struct *fsp,
2343 struct smb_filename *smb_fname,
2344 uint16_t *_compression_fmt)
2346 return NT_STATUS_INVALID_DEVICE_REQUEST;
2349 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
2350 TALLOC_CTX *mem_ctx,
2351 struct files_struct *fsp,
2352 uint16_t compression_fmt)
2354 return NT_STATUS_INVALID_DEVICE_REQUEST;
2357 /********************************************************************
2358 Given a stat buffer return the allocated size on disk, taking into
2359 account sparse files.
2360 ********************************************************************/
2361 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
2362 struct files_struct *fsp,
2363 const SMB_STRUCT_STAT *sbuf)
2367 START_PROFILE(syscall_get_alloc_size);
2369 if(S_ISDIR(sbuf->st_ex_mode)) {
2374 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2375 /* The type of st_blocksize is blkcnt_t which *MUST* be
2376 signed (according to POSIX) and can be less than 64-bits.
2377 Ensure when we're converting to 64 bits wide we don't
2379 #if defined(SIZEOF_BLKCNT_T_8)
2380 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2381 #elif defined(SIZEOF_BLKCNT_T_4)
2383 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2384 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2387 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2391 * Some file systems do not allocate a block for very
2392 * small files. But for non-empty file should report a
2396 uint64_t filesize = get_file_size_stat(sbuf);
2398 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2402 result = get_file_size_stat(sbuf);
2405 if (fsp && fsp->initial_allocation_size)
2406 result = MAX(result,fsp->initial_allocation_size);
2408 result = smb_roundup(handle->conn, result);
2411 END_PROFILE(syscall_get_alloc_size);
2415 static int vfswrap_unlinkat(vfs_handle_struct *handle,
2416 struct files_struct *dirfsp,
2417 const struct smb_filename *smb_fname,
2422 START_PROFILE(syscall_unlinkat);
2424 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2426 if (is_named_stream(smb_fname)) {
2430 result = unlinkat(fsp_get_pathref_fd(dirfsp),
2431 smb_fname->base_name,
2435 END_PROFILE(syscall_unlinkat);
2439 static int vfswrap_chmod(vfs_handle_struct *handle,
2440 const struct smb_filename *smb_fname,
2445 START_PROFILE(syscall_chmod);
2446 result = chmod(smb_fname->base_name, mode);
2447 END_PROFILE(syscall_chmod);
2451 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2455 START_PROFILE(syscall_fchmod);
2456 #if defined(HAVE_FCHMOD)
2457 result = fchmod(fsp_get_io_fd(fsp), mode);
2463 END_PROFILE(syscall_fchmod);
2467 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2472 START_PROFILE(syscall_fchown);
2473 result = fchown(fsp_get_io_fd(fsp), uid, gid);
2474 END_PROFILE(syscall_fchown);
2482 static int vfswrap_lchown(vfs_handle_struct *handle,
2483 const struct smb_filename *smb_fname,
2489 START_PROFILE(syscall_lchown);
2490 result = lchown(smb_fname->base_name, uid, gid);
2491 END_PROFILE(syscall_lchown);
2495 static int vfswrap_chdir(vfs_handle_struct *handle,
2496 const struct smb_filename *smb_fname)
2500 START_PROFILE(syscall_chdir);
2501 result = chdir(smb_fname->base_name);
2502 END_PROFILE(syscall_chdir);
2506 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2510 struct smb_filename *smb_fname = NULL;
2512 START_PROFILE(syscall_getwd);
2513 result = sys_getwd();
2514 END_PROFILE(syscall_getwd);
2516 if (result == NULL) {
2519 smb_fname = synthetic_smb_fname(ctx,
2526 * sys_getwd() *always* returns malloced memory.
2527 * We must free here to avoid leaks:
2528 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2534 /*********************************************************************
2535 nsec timestamp resolution call. Convert down to whatever the underlying
2536 system will support.
2537 **********************************************************************/
2539 static int vfswrap_ntimes(vfs_handle_struct *handle,
2540 const struct smb_filename *smb_fname,
2541 struct smb_file_time *ft)
2545 START_PROFILE(syscall_ntimes);
2547 if (is_named_stream(smb_fname)) {
2553 if (is_omit_timespec(&ft->atime)) {
2554 ft->atime= smb_fname->st.st_ex_atime;
2557 if (is_omit_timespec(&ft->mtime)) {
2558 ft->mtime = smb_fname->st.st_ex_mtime;
2561 if (!is_omit_timespec(&ft->create_time)) {
2562 set_create_timespec_ea(handle->conn,
2567 if ((timespec_compare(&ft->atime,
2568 &smb_fname->st.st_ex_atime) == 0) &&
2569 (timespec_compare(&ft->mtime,
2570 &smb_fname->st.st_ex_mtime) == 0)) {
2575 #if defined(HAVE_UTIMENSAT)
2577 struct timespec ts[2];
2580 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2582 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2584 if (!((result == -1) && (errno == ENOSYS))) {
2588 #if defined(HAVE_UTIMES)
2590 struct timeval tv[2];
2591 tv[0] = convert_timespec_to_timeval(ft->atime);
2592 tv[1] = convert_timespec_to_timeval(ft->mtime);
2593 result = utimes(smb_fname->base_name, tv);
2595 result = utimes(smb_fname->base_name, NULL);
2597 if (!((result == -1) && (errno == ENOSYS))) {
2601 #if defined(HAVE_UTIME)
2603 struct utimbuf times;
2604 times.actime = convert_timespec_to_time_t(ft->atime);
2605 times.modtime = convert_timespec_to_time_t(ft->mtime);
2606 result = utime(smb_fname->base_name, ×);
2608 result = utime(smb_fname->base_name, NULL);
2610 if (!((result == -1) && (errno == ENOSYS))) {
2618 END_PROFILE(syscall_ntimes);
2622 /*********************************************************************
2623 A version of ftruncate that will write the space on disk if strict
2625 **********************************************************************/
2627 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2629 off_t space_to_write;
2630 uint64_t space_avail;
2631 uint64_t bsize,dfree,dsize;
2634 SMB_STRUCT_STAT *pst;
2637 ok = vfs_valid_pwrite_range(len, 0);
2643 status = vfs_stat_fsp(fsp);
2644 if (!NT_STATUS_IS_OK(status)) {
2647 pst = &fsp->fsp_name->st;
2650 if (S_ISFIFO(pst->st_ex_mode))
2654 if (pst->st_ex_size == len)
2657 /* Shrink - just ftruncate. */
2658 if (pst->st_ex_size > len)
2659 return ftruncate(fsp_get_io_fd(fsp), len);
2661 space_to_write = len - pst->st_ex_size;
2663 /* for allocation try fallocate first. This can fail on some
2664 platforms e.g. when the filesystem doesn't support it and no
2665 emulation is being done by the libc (like on AIX with JFS1). In that
2666 case we do our own emulation. fallocate implementations can
2667 return ENOTSUP or EINVAL in cases like that. */
2668 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2669 if (ret == -1 && errno == ENOSPC) {
2675 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2676 "error %d. Falling back to slow manual allocation\n", errno));
2678 /* available disk space is enough or not? */
2680 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2681 /* space_avail is 1k blocks */
2682 if (space_avail == (uint64_t)-1 ||
2683 ((uint64_t)space_to_write/1024 > space_avail) ) {
2688 /* Write out the real space on disk. */
2689 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2697 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2700 SMB_STRUCT_STAT *pst;
2704 START_PROFILE(syscall_ftruncate);
2706 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->fsp_flags.is_sparse) {
2707 result = strict_allocate_ftruncate(handle, fsp, len);
2708 END_PROFILE(syscall_ftruncate);
2712 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2713 ftruncate if the system supports it. Then I discovered that
2714 you can have some filesystems that support ftruncate
2715 expansion and some that don't! On Linux fat can't do
2716 ftruncate extend but ext2 can. */
2718 result = ftruncate(fsp_get_io_fd(fsp), len);
2720 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2721 extend a file with ftruncate. Provide alternate implementation
2724 /* Do an fstat to see if the file is longer than the requested
2725 size in which case the ftruncate above should have
2726 succeeded or shorter, in which case seek to len - 1 and
2727 write 1 byte of zero */
2728 status = vfs_stat_fsp(fsp);
2729 if (!NT_STATUS_IS_OK(status)) {
2733 /* We need to update the files_struct after successful ftruncate */
2738 pst = &fsp->fsp_name->st;
2741 if (S_ISFIFO(pst->st_ex_mode)) {
2747 if (pst->st_ex_size == len) {
2752 if (pst->st_ex_size > len) {
2753 /* the ftruncate should have worked */
2757 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2765 END_PROFILE(syscall_ftruncate);
2769 static int vfswrap_fallocate(vfs_handle_struct *handle,
2777 START_PROFILE(syscall_fallocate);
2779 result = sys_posix_fallocate(fsp_get_io_fd(fsp), offset, len);
2781 * posix_fallocate returns 0 on success, errno on error
2782 * and doesn't set errno. Make it behave like fallocate()
2783 * which returns -1, and sets errno on failure.
2790 /* sys_fallocate handles filtering of unsupported mode flags */
2791 result = sys_fallocate(fsp_get_io_fd(fsp), mode, offset, len);
2793 END_PROFILE(syscall_fallocate);
2797 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2801 START_PROFILE(syscall_fcntl_lock);
2803 if (fsp->fsp_flags.use_ofd_locks) {
2804 op = map_process_lock_to_ofd_lock(op);
2807 result = fcntl_lock(fsp_get_io_fd(fsp), op, offset, count, type);
2808 END_PROFILE(syscall_fcntl_lock);
2812 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2813 uint32_t share_access, uint32_t access_mask)
2815 START_PROFILE(syscall_kernel_flock);
2816 kernel_flock(fsp_get_io_fd(fsp), share_access, access_mask);
2817 END_PROFILE(syscall_kernel_flock);
2821 static int vfswrap_fcntl(vfs_handle_struct *handle, files_struct *fsp, int cmd,
2825 va_list dup_cmd_arg;
2829 START_PROFILE(syscall_fcntl);
2831 va_copy(dup_cmd_arg, cmd_arg);
2837 #if defined(HAVE_OFD_LOCKS)
2842 #if defined(HAVE_F_OWNER_EX)
2846 #if defined(HAVE_RW_HINTS)
2849 case F_GET_FILE_RW_HINT:
2850 case F_SET_FILE_RW_HINT:
2852 argp = va_arg(dup_cmd_arg, void *);
2853 result = sys_fcntl_ptr(fsp_get_io_fd(fsp), cmd, argp);
2856 val = va_arg(dup_cmd_arg, int);
2857 result = sys_fcntl_int(fsp_get_io_fd(fsp), cmd, val);
2860 va_end(dup_cmd_arg);
2862 END_PROFILE(syscall_fcntl);
2866 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2871 START_PROFILE(syscall_fcntl_getlock);
2873 if (fsp->fsp_flags.use_ofd_locks) {
2874 op = map_process_lock_to_ofd_lock(op);
2877 result = fcntl_getlock(fsp_get_io_fd(fsp), op, poffset, pcount, ptype, ppid);
2878 END_PROFILE(syscall_fcntl_getlock);
2882 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2887 START_PROFILE(syscall_linux_setlease);
2889 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2890 result = linux_setlease(fsp_get_io_fd(fsp), leasetype);
2894 END_PROFILE(syscall_linux_setlease);
2898 static int vfswrap_symlinkat(vfs_handle_struct *handle,
2899 const struct smb_filename *link_target,
2900 struct files_struct *dirfsp,
2901 const struct smb_filename *new_smb_fname)
2905 START_PROFILE(syscall_symlinkat);
2907 result = symlinkat(link_target->base_name,
2908 fsp_get_pathref_fd(dirfsp),
2909 new_smb_fname->base_name);
2910 END_PROFILE(syscall_symlinkat);
2914 static int vfswrap_readlinkat(vfs_handle_struct *handle,
2915 const struct files_struct *dirfsp,
2916 const struct smb_filename *smb_fname,
2922 START_PROFILE(syscall_readlinkat);
2924 result = readlinkat(fsp_get_pathref_fd(dirfsp),
2925 smb_fname->base_name,
2929 END_PROFILE(syscall_readlinkat);
2933 static int vfswrap_linkat(vfs_handle_struct *handle,
2934 files_struct *srcfsp,
2935 const struct smb_filename *old_smb_fname,
2936 files_struct *dstfsp,
2937 const struct smb_filename *new_smb_fname,
2942 START_PROFILE(syscall_linkat);
2944 result = linkat(fsp_get_pathref_fd(srcfsp),
2945 old_smb_fname->base_name,
2946 fsp_get_pathref_fd(dstfsp),
2947 new_smb_fname->base_name,
2950 END_PROFILE(syscall_linkat);
2954 static int vfswrap_mknodat(vfs_handle_struct *handle,
2955 files_struct *dirfsp,
2956 const struct smb_filename *smb_fname,
2962 START_PROFILE(syscall_mknodat);
2964 result = sys_mknodat(fsp_get_pathref_fd(dirfsp),
2965 smb_fname->base_name,
2969 END_PROFILE(syscall_mknodat);
2973 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2975 const struct smb_filename *smb_fname)
2978 struct smb_filename *result_fname = NULL;
2980 START_PROFILE(syscall_realpath);
2981 result = sys_realpath(smb_fname->base_name);
2982 END_PROFILE(syscall_realpath);
2984 result_fname = synthetic_smb_fname(ctx,
2992 return result_fname;
2995 static int vfswrap_chflags(vfs_handle_struct *handle,
2996 const struct smb_filename *smb_fname,
3000 return chflags(smb_fname->base_name, flags);
3007 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
3008 const SMB_STRUCT_STAT *sbuf)
3012 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
3016 key.devid = sbuf->st_ex_dev;
3017 key.inode = sbuf->st_ex_ino;
3018 /* key.extid is unused by default. */
3023 static uint64_t vfswrap_fs_file_id(struct vfs_handle_struct *handle,
3024 const SMB_STRUCT_STAT *psbuf)
3028 if (!(psbuf->st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)) {
3029 return psbuf->st_ex_file_id;
3032 if (handle->conn->base_share_dev == psbuf->st_ex_dev) {
3033 return (uint64_t)psbuf->st_ex_ino;
3037 file_id = ((psbuf->st_ex_ino) & UINT32_MAX);
3040 file_id |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32;
3045 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
3046 struct files_struct *fsp,
3047 const struct smb_filename *smb_fname,
3048 TALLOC_CTX *mem_ctx,
3049 unsigned int *pnum_streams,
3050 struct stream_struct **pstreams)
3052 SMB_STRUCT_STAT sbuf;
3053 struct stream_struct *tmp_streams = NULL;
3056 if ((fsp != NULL) && (fsp->fsp_flags.is_directory)) {
3058 * No default streams on directories
3063 if ((fsp != NULL) && (fsp_get_pathref_fd(fsp) != -1)) {
3064 ret = SMB_VFS_FSTAT(fsp, &sbuf);
3067 struct smb_filename *smb_fname_cp = NULL;
3069 smb_fname_cp = cp_smb_filename_nostream(talloc_tos(), smb_fname);
3070 if (smb_fname_cp == NULL) {
3071 return NT_STATUS_NO_MEMORY;
3074 ret = vfs_stat(handle->conn, smb_fname_cp);
3075 sbuf = smb_fname_cp->st;
3076 TALLOC_FREE(smb_fname_cp);
3080 return map_nt_error_from_unix(errno);
3083 if (S_ISDIR(sbuf.st_ex_mode)) {
3087 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
3088 (*pnum_streams) + 1);
3089 if (tmp_streams == NULL) {
3090 return NT_STATUS_NO_MEMORY;
3092 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
3093 if (tmp_streams[*pnum_streams].name == NULL) {
3094 return NT_STATUS_NO_MEMORY;
3096 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
3097 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
3100 *pstreams = tmp_streams;
3102 return NT_STATUS_OK;
3105 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
3106 const struct smb_filename *path,
3108 TALLOC_CTX *mem_ctx,
3112 * Don't fall back to get_real_filename so callers can differentiate
3113 * between a full directory scan and an actual case-insensitive stat.
3119 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
3120 const struct smb_filename *smb_fname)
3122 return handle->conn->connectpath;
3125 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
3126 struct byte_range_lock *br_lck,
3127 struct lock_struct *plock)
3129 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3131 /* Note: blr is not used in the default implementation. */
3132 return brl_lock_windows_default(br_lck, plock);
3135 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
3136 struct byte_range_lock *br_lck,
3137 const struct lock_struct *plock)
3139 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3141 return brl_unlock_windows_default(br_lck, plock);
3144 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
3146 struct lock_struct *plock)
3148 SMB_ASSERT(plock->lock_type == READ_LOCK ||
3149 plock->lock_type == WRITE_LOCK);
3151 return strict_lock_check_default(fsp, plock);
3154 /* NT ACL operations. */
3156 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
3158 uint32_t security_info,
3159 TALLOC_CTX *mem_ctx,
3160 struct security_descriptor **ppdesc)
3164 START_PROFILE(fget_nt_acl);
3165 result = posix_fget_nt_acl(fsp, security_info,
3167 END_PROFILE(fget_nt_acl);
3171 static NTSTATUS vfswrap_get_nt_acl_at(vfs_handle_struct *handle,
3172 struct files_struct *dirfsp,
3173 const struct smb_filename *smb_fname,
3174 uint32_t security_info,
3175 TALLOC_CTX *mem_ctx,
3176 struct security_descriptor **ppdesc)
3180 START_PROFILE(get_nt_acl_at);
3182 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
3184 result = posix_get_nt_acl(handle->conn,
3189 END_PROFILE(get_nt_acl_at);
3193 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
3197 START_PROFILE(fset_nt_acl);
3198 result = set_nt_acl(fsp, security_info_sent, psd);
3199 END_PROFILE(fset_nt_acl);
3203 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
3204 struct smb_filename *file,
3205 struct security_acl *sacl,
3206 uint32_t access_requested,
3207 uint32_t access_denied)
3209 return NT_STATUS_OK; /* Nothing to do here ... */
3212 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
3213 const struct smb_filename *smb_fname,
3214 SMB_ACL_TYPE_T type,
3215 TALLOC_CTX *mem_ctx)
3217 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
3220 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
3222 TALLOC_CTX *mem_ctx)
3224 return sys_acl_get_fd(handle, fsp, mem_ctx);
3227 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
3228 const struct smb_filename *smb_fname,
3229 SMB_ACL_TYPE_T acltype,
3232 return sys_acl_set_file(handle, smb_fname, acltype, theacl);
3235 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
3237 return sys_acl_set_fd(handle, fsp, theacl);
3240 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
3241 const struct smb_filename *smb_fname)
3243 return sys_acl_delete_def_file(handle, smb_fname);
3246 /****************************************************************
3247 Extended attribute operations.
3248 *****************************************************************/
3250 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
3251 const struct smb_filename *smb_fname,
3256 return getxattr(smb_fname->base_name, name, value, size);
3259 struct vfswrap_getxattrat_state {
3260 struct tevent_context *ev;
3261 files_struct *dir_fsp;
3262 const struct smb_filename *smb_fname;
3265 * The following variables are talloced off "state" which is protected
3266 * by a destructor and thus are guaranteed to be safe to be used in the
3267 * job function in the worker thread.
3270 const char *xattr_name;
3271 uint8_t *xattr_value;
3272 struct security_unix_token *token;
3275 struct vfs_aio_state vfs_aio_state;
3276 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
3279 static int vfswrap_getxattrat_state_destructor(
3280 struct vfswrap_getxattrat_state *state)
3285 static void vfswrap_getxattrat_do_sync(struct tevent_req *req);
3286 static void vfswrap_getxattrat_do_async(void *private_data);
3287 static void vfswrap_getxattrat_done(struct tevent_req *subreq);
3289 static struct tevent_req *vfswrap_getxattrat_send(
3290 TALLOC_CTX *mem_ctx,
3291 struct tevent_context *ev,
3292 struct vfs_handle_struct *handle,
3293 files_struct *dir_fsp,
3294 const struct smb_filename *smb_fname,
3295 const char *xattr_name,
3298 struct tevent_req *req = NULL;
3299 struct tevent_req *subreq = NULL;
3300 struct vfswrap_getxattrat_state *state = NULL;
3301 size_t max_threads = 0;
3302 bool have_per_thread_cwd = false;
3303 bool have_per_thread_creds = false;
3304 bool do_async = false;
3306 req = tevent_req_create(mem_ctx, &state,
3307 struct vfswrap_getxattrat_state);
3311 *state = (struct vfswrap_getxattrat_state) {
3314 .smb_fname = smb_fname,
3317 max_threads = pthreadpool_tevent_max_threads(dir_fsp->conn->sconn->pool);
3318 if (max_threads >= 1) {
3320 * We need a non sync threadpool!
3322 have_per_thread_cwd = per_thread_cwd_supported();
3324 #ifdef HAVE_LINUX_THREAD_CREDENTIALS
3325 have_per_thread_creds = true;
3327 if (have_per_thread_cwd && have_per_thread_creds) {
3331 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat, profile_p,
3332 state->profile_bytes, 0);
3334 if (fsp_get_pathref_fd(dir_fsp) == -1) {
3335 DBG_ERR("Need a valid directory fd\n");
3336 tevent_req_error(req, EINVAL);
3337 return tevent_req_post(req, ev);
3340 if (alloc_hint > 0) {
3341 state->xattr_value = talloc_zero_array(state,
3344 if (tevent_req_nomem(state->xattr_value, req)) {
3345 return tevent_req_post(req, ev);
3350 vfswrap_getxattrat_do_sync(req);
3351 return tevent_req_post(req, ev);
3355 * Now allocate all parameters from a memory context that won't go away
3356 * no matter what. These paremeters will get used in threads and we
3357 * can't reliably cancel threads, so all buffers passed to the threads
3358 * must not be freed before all referencing threads terminate.
3361 state->name = talloc_strdup(state, smb_fname->base_name);
3362 if (tevent_req_nomem(state->name, req)) {
3363 return tevent_req_post(req, ev);
3366 state->xattr_name = talloc_strdup(state, xattr_name);
3367 if (tevent_req_nomem(state->xattr_name, req)) {
3368 return tevent_req_post(req, ev);
3372 * This is a hot codepath so at first glance one might think we should
3373 * somehow optimize away the token allocation and do a
3374 * talloc_reference() or similar black magic instead. But due to the
3375 * talloc_stackframe pool per SMB2 request this should be a simple copy
3376 * without a malloc in most cases.
3378 if (geteuid() == sec_initial_uid()) {
3379 state->token = root_unix_token(state);
3381 state->token = copy_unix_token(
3383 dir_fsp->conn->session_info->unix_token);
3385 if (tevent_req_nomem(state->token, req)) {
3386 return tevent_req_post(req, ev);
3389 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3391 subreq = pthreadpool_tevent_job_send(
3394 dir_fsp->conn->sconn->pool,
3395 vfswrap_getxattrat_do_async,
3397 if (tevent_req_nomem(subreq, req)) {
3398 return tevent_req_post(req, ev);
3400 tevent_req_set_callback(subreq, vfswrap_getxattrat_done, req);
3402 talloc_set_destructor(state, vfswrap_getxattrat_state_destructor);
3407 static void vfswrap_getxattrat_do_sync(struct tevent_req *req)
3409 struct vfswrap_getxattrat_state *state = tevent_req_data(
3410 req, struct vfswrap_getxattrat_state);
3412 char *tofree = NULL;
3413 char pathbuf[PATH_MAX+1];
3417 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
3418 state->smb_fname->base_name,
3423 if (pathlen == -1) {
3424 tevent_req_error(req, ENOMEM);
3428 state->xattr_size = getxattr(path,
3431 talloc_array_length(state->xattr_value));
3433 TALLOC_FREE(tofree);
3434 if (state->xattr_size == -1) {
3435 tevent_req_error(req, err);
3439 tevent_req_done(req);
3443 static void vfswrap_getxattrat_do_async(void *private_data)
3445 struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3446 private_data, struct vfswrap_getxattrat_state);
3447 struct timespec start_time;
3448 struct timespec end_time;
3451 PROFILE_TIMESTAMP(&start_time);
3452 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
3455 * Here we simulate a getxattrat()
3456 * call using fchdir();getxattr()
3459 per_thread_cwd_activate();
3461 /* Become the correct credential on this thread. */
3462 ret = set_thread_credentials(state->token->uid,
3464 (size_t)state->token->ngroups,
3465 state->token->groups);
3467 state->xattr_size = -1;
3468 state->vfs_aio_state.error = errno;
3472 ret = fchdir(fsp_get_pathref_fd(state->dir_fsp));
3474 state->xattr_size = -1;
3475 state->vfs_aio_state.error = errno;
3479 state->xattr_size = getxattr(state->name,
3482 talloc_array_length(state->xattr_value));
3483 if (state->xattr_size == -1) {
3484 state->vfs_aio_state.error = errno;
3488 PROFILE_TIMESTAMP(&end_time);
3489 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
3490 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3493 static void vfswrap_getxattrat_done(struct tevent_req *subreq)
3495 struct tevent_req *req = tevent_req_callback_data(
3496 subreq, struct tevent_req);
3497 struct vfswrap_getxattrat_state *state = tevent_req_data(
3498 req, struct vfswrap_getxattrat_state);
3503 * Make sure we run as the user again
3505 ok = change_to_user_and_service_by_fsp(state->dir_fsp);
3508 ret = pthreadpool_tevent_job_recv(subreq);
3509 TALLOC_FREE(subreq);
3510 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
3511 talloc_set_destructor(state, NULL);
3513 if (ret != EAGAIN) {
3514 tevent_req_error(req, ret);
3518 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
3519 * means the lower level pthreadpool failed to create a new
3520 * thread. Fallback to sync processing in that case to allow
3521 * some progress for the client.
3523 vfswrap_getxattrat_do_sync(req);
3527 if (state->xattr_size == -1) {
3528 tevent_req_error(req, state->vfs_aio_state.error);
3532 if (state->xattr_value == NULL) {
3534 * The caller only wanted the size.
3536 tevent_req_done(req);
3541 * shrink the buffer to the returned size.
3542 * (can't fail). It means NULL if size is 0.
3544 state->xattr_value = talloc_realloc(state,
3549 tevent_req_done(req);
3552 static ssize_t vfswrap_getxattrat_recv(struct tevent_req *req,
3553 struct vfs_aio_state *aio_state,
3554 TALLOC_CTX *mem_ctx,
3555 uint8_t **xattr_value)
3557 struct vfswrap_getxattrat_state *state = tevent_req_data(
3558 req, struct vfswrap_getxattrat_state);
3561 if (tevent_req_is_unix_error(req, &aio_state->error)) {
3562 tevent_req_received(req);
3566 *aio_state = state->vfs_aio_state;
3567 xattr_size = state->xattr_size;
3568 if (xattr_value != NULL) {
3569 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
3572 tevent_req_received(req);
3576 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle,
3577 struct files_struct *fsp,
3582 int fd = fsp_get_pathref_fd(fsp);
3584 if (!fsp->fsp_flags.is_pathref) {
3585 return fgetxattr(fd, name, value, size);
3588 if (fsp->fsp_flags.have_proc_fds) {
3589 const char *p = NULL;
3592 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3597 return getxattr(p, name, value, size);
3601 * This is no longer a handle based call.
3603 return getxattr(fsp->fsp_name->base_name, name, value, size);
3606 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
3607 const struct smb_filename *smb_fname,
3611 return listxattr(smb_fname->base_name, list, size);
3614 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
3616 int fd = fsp_get_pathref_fd(fsp);
3618 if (!fsp->fsp_flags.is_pathref) {
3619 return flistxattr(fd, list, size);
3622 if (fsp->fsp_flags.have_proc_fds) {
3623 const char *p = NULL;
3626 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3631 return listxattr(p, list, size);
3635 * This is no longer a handle based call.
3637 return listxattr(fsp->fsp_name->base_name, list, size);
3640 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
3641 const struct smb_filename *smb_fname,
3644 return removexattr(smb_fname->base_name, name);
3647 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
3649 int fd = fsp_get_pathref_fd(fsp);
3651 if (!fsp->fsp_flags.is_pathref) {
3652 return fremovexattr(fd, name);
3655 if (fsp->fsp_flags.have_proc_fds) {
3656 const char *p = NULL;
3659 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3664 return removexattr(p, name);
3668 * This is no longer a handle based call.
3670 return removexattr(fsp->fsp_name->base_name, name);
3673 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
3674 const struct smb_filename *smb_fname,
3680 return setxattr(smb_fname->base_name, name, value, size, flags);
3683 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
3685 int fd = fsp_get_pathref_fd(fsp);
3687 if (!fsp->fsp_flags.is_pathref) {
3688 return fsetxattr(fd, name, value, size, flags);
3691 if (fsp->fsp_flags.have_proc_fds) {
3692 const char *p = NULL;
3695 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3700 return setxattr(p, name, value, size, flags);
3704 * This is no longer a handle based call.
3706 return setxattr(fsp->fsp_name->base_name, name, value, size, flags);
3709 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
3714 static bool vfswrap_is_offline(struct connection_struct *conn,
3715 const struct smb_filename *fname)
3719 bool offline = false;
3721 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
3725 if (!lp_dmapi_support(SNUM(conn)) || !dmapi_have_session()) {
3726 #if defined(ENOTSUP)
3732 status = get_full_smb_filename(talloc_tos(), fname, &path);
3733 if (!NT_STATUS_IS_OK(status)) {
3734 errno = map_errno_from_nt_status(status);
3738 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
3745 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
3746 struct files_struct *fsp,
3747 TALLOC_CTX *mem_ctx,
3750 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
3753 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
3754 struct files_struct *fsp,
3755 const DATA_BLOB old_cookie,
3756 TALLOC_CTX *mem_ctx,
3757 DATA_BLOB *new_cookie)
3759 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
3763 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
3764 struct smb_request *smb1req,
3765 struct smbXsrv_open *op,
3766 const DATA_BLOB old_cookie,
3767 TALLOC_CTX *mem_ctx,
3768 struct files_struct **fsp,
3769 DATA_BLOB *new_cookie)
3771 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
3772 old_cookie, mem_ctx,
3776 static struct vfs_fn_pointers vfs_default_fns = {
3777 /* Disk operations */
3779 .connect_fn = vfswrap_connect,
3780 .disconnect_fn = vfswrap_disconnect,
3781 .disk_free_fn = vfswrap_disk_free,
3782 .get_quota_fn = vfswrap_get_quota,
3783 .set_quota_fn = vfswrap_set_quota,
3784 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3785 .statvfs_fn = vfswrap_statvfs,
3786 .fs_capabilities_fn = vfswrap_fs_capabilities,
3787 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3788 .create_dfs_pathat_fn = vfswrap_create_dfs_pathat,
3789 .read_dfs_pathat_fn = vfswrap_read_dfs_pathat,
3790 .snap_check_path_fn = vfswrap_snap_check_path,
3791 .snap_create_fn = vfswrap_snap_create,
3792 .snap_delete_fn = vfswrap_snap_delete,
3794 /* Directory operations */
3796 .fdopendir_fn = vfswrap_fdopendir,
3797 .readdir_fn = vfswrap_readdir,
3798 .readdir_attr_fn = vfswrap_readdir_attr,
3799 .seekdir_fn = vfswrap_seekdir,
3800 .telldir_fn = vfswrap_telldir,
3801 .rewind_dir_fn = vfswrap_rewinddir,
3802 .mkdirat_fn = vfswrap_mkdirat,
3803 .closedir_fn = vfswrap_closedir,
3805 /* File operations */
3807 .openat_fn = vfswrap_openat,
3808 .create_file_fn = vfswrap_create_file,
3809 .close_fn = vfswrap_close,
3810 .pread_fn = vfswrap_pread,
3811 .pread_send_fn = vfswrap_pread_send,
3812 .pread_recv_fn = vfswrap_pread_recv,
3813 .pwrite_fn = vfswrap_pwrite,
3814 .pwrite_send_fn = vfswrap_pwrite_send,
3815 .pwrite_recv_fn = vfswrap_pwrite_recv,
3816 .lseek_fn = vfswrap_lseek,
3817 .sendfile_fn = vfswrap_sendfile,
3818 .recvfile_fn = vfswrap_recvfile,
3819 .renameat_fn = vfswrap_renameat,
3820 .fsync_send_fn = vfswrap_fsync_send,
3821 .fsync_recv_fn = vfswrap_fsync_recv,
3822 .stat_fn = vfswrap_stat,
3823 .fstat_fn = vfswrap_fstat,
3824 .lstat_fn = vfswrap_lstat,
3825 .get_alloc_size_fn = vfswrap_get_alloc_size,
3826 .unlinkat_fn = vfswrap_unlinkat,
3827 .chmod_fn = vfswrap_chmod,
3828 .fchmod_fn = vfswrap_fchmod,
3829 .fchown_fn = vfswrap_fchown,
3830 .lchown_fn = vfswrap_lchown,
3831 .chdir_fn = vfswrap_chdir,
3832 .getwd_fn = vfswrap_getwd,
3833 .ntimes_fn = vfswrap_ntimes,
3834 .ftruncate_fn = vfswrap_ftruncate,
3835 .fallocate_fn = vfswrap_fallocate,
3836 .lock_fn = vfswrap_lock,
3837 .kernel_flock_fn = vfswrap_kernel_flock,
3838 .fcntl_fn = vfswrap_fcntl,
3839 .linux_setlease_fn = vfswrap_linux_setlease,
3840 .getlock_fn = vfswrap_getlock,
3841 .symlinkat_fn = vfswrap_symlinkat,
3842 .readlinkat_fn = vfswrap_readlinkat,
3843 .linkat_fn = vfswrap_linkat,
3844 .mknodat_fn = vfswrap_mknodat,
3845 .realpath_fn = vfswrap_realpath,
3846 .chflags_fn = vfswrap_chflags,
3847 .file_id_create_fn = vfswrap_file_id_create,
3848 .fs_file_id_fn = vfswrap_fs_file_id,
3849 .streaminfo_fn = vfswrap_streaminfo,
3850 .get_real_filename_fn = vfswrap_get_real_filename,
3851 .connectpath_fn = vfswrap_connectpath,
3852 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
3853 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3854 .strict_lock_check_fn = vfswrap_strict_lock_check,
3855 .translate_name_fn = vfswrap_translate_name,
3856 .fsctl_fn = vfswrap_fsctl,
3857 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
3858 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
3859 .get_dos_attributes_send_fn = vfswrap_get_dos_attributes_send,
3860 .get_dos_attributes_recv_fn = vfswrap_get_dos_attributes_recv,
3861 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
3862 .offload_read_send_fn = vfswrap_offload_read_send,
3863 .offload_read_recv_fn = vfswrap_offload_read_recv,
3864 .offload_write_send_fn = vfswrap_offload_write_send,
3865 .offload_write_recv_fn = vfswrap_offload_write_recv,
3866 .get_compression_fn = vfswrap_get_compression,
3867 .set_compression_fn = vfswrap_set_compression,
3869 /* NT ACL operations. */
3871 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
3872 .get_nt_acl_at_fn = vfswrap_get_nt_acl_at,
3873 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
3874 .audit_file_fn = vfswrap_audit_file,
3876 /* POSIX ACL operations. */
3878 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
3879 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3880 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
3881 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3882 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
3883 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3884 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
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 .listxattr_fn = vfswrap_listxattr,
3892 .flistxattr_fn = vfswrap_flistxattr,
3893 .removexattr_fn = vfswrap_removexattr,
3894 .fremovexattr_fn = vfswrap_fremovexattr,
3895 .setxattr_fn = vfswrap_setxattr,
3896 .fsetxattr_fn = vfswrap_fsetxattr,
3898 /* aio operations */
3899 .aio_force_fn = vfswrap_aio_force,
3901 /* durable handle operations */
3902 .durable_cookie_fn = vfswrap_durable_cookie,
3903 .durable_disconnect_fn = vfswrap_durable_disconnect,
3904 .durable_reconnect_fn = vfswrap_durable_reconnect,
3908 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3911 * Here we need to implement every call!
3913 * As this is the end of the vfs module chain.
3915 smb_vfs_assert_all_fns(&vfs_default_fns, DEFAULT_VFS_MODULE_NAME);
3916 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3917 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);