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 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1707 struct smb_filename *smb_fname,
1712 offline = vfswrap_is_offline(handle->conn, smb_fname);
1714 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1717 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1720 struct vfswrap_get_dos_attributes_state {
1721 struct vfs_aio_state aio_state;
1722 connection_struct *conn;
1723 TALLOC_CTX *mem_ctx;
1724 struct tevent_context *ev;
1725 files_struct *dir_fsp;
1726 struct smb_filename *smb_fname;
1731 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq);
1733 static struct tevent_req *vfswrap_get_dos_attributes_send(
1734 TALLOC_CTX *mem_ctx,
1735 struct tevent_context *ev,
1736 struct vfs_handle_struct *handle,
1737 files_struct *dir_fsp,
1738 struct smb_filename *smb_fname)
1740 struct tevent_req *req = NULL;
1741 struct tevent_req *subreq = NULL;
1742 struct vfswrap_get_dos_attributes_state *state = NULL;
1744 req = tevent_req_create(mem_ctx, &state,
1745 struct vfswrap_get_dos_attributes_state);
1750 *state = (struct vfswrap_get_dos_attributes_state) {
1751 .conn = dir_fsp->conn,
1755 .smb_fname = smb_fname,
1758 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1762 SAMBA_XATTR_DOS_ATTRIB,
1764 if (tevent_req_nomem(subreq, req)) {
1765 return tevent_req_post(req, ev);
1767 tevent_req_set_callback(subreq,
1768 vfswrap_get_dos_attributes_getxattr_done,
1774 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq)
1776 struct tevent_req *req =
1777 tevent_req_callback_data(subreq,
1779 struct vfswrap_get_dos_attributes_state *state =
1780 tevent_req_data(req,
1781 struct vfswrap_get_dos_attributes_state);
1783 DATA_BLOB blob = {0};
1785 char *tofree = NULL;
1786 char pathbuf[PATH_MAX+1];
1788 struct smb_filename smb_fname;
1792 xattr_size = SMB_VFS_GETXATTRAT_RECV(subreq,
1796 TALLOC_FREE(subreq);
1797 if (xattr_size == -1) {
1798 status = map_nt_error_from_unix(state->aio_state.error);
1800 if (state->as_root) {
1801 tevent_req_nterror(req, status);
1804 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1805 tevent_req_nterror(req, status);
1809 state->as_root = true;
1812 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1816 SAMBA_XATTR_DOS_ATTRIB,
1819 if (tevent_req_nomem(subreq, req)) {
1822 tevent_req_set_callback(subreq,
1823 vfswrap_get_dos_attributes_getxattr_done,
1828 blob.length = xattr_size;
1830 status = parse_dos_attribute_blob(state->smb_fname,
1833 if (!NT_STATUS_IS_OK(status)) {
1834 tevent_req_nterror(req, status);
1838 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
1839 state->smb_fname->base_name,
1844 if (pathlen == -1) {
1845 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1849 smb_fname = (struct smb_filename) {
1851 .st = state->smb_fname->st,
1852 .flags = state->smb_fname->flags,
1853 .twrp = state->smb_fname->twrp,
1856 offline = vfswrap_is_offline(state->conn, &smb_fname);
1858 state->dosmode |= FILE_ATTRIBUTE_OFFLINE;
1860 TALLOC_FREE(tofree);
1862 tevent_req_done(req);
1866 static NTSTATUS vfswrap_get_dos_attributes_recv(struct tevent_req *req,
1867 struct vfs_aio_state *aio_state,
1870 struct vfswrap_get_dos_attributes_state *state =
1871 tevent_req_data(req,
1872 struct vfswrap_get_dos_attributes_state);
1875 if (tevent_req_is_nterror(req, &status)) {
1876 tevent_req_received(req);
1880 *aio_state = state->aio_state;
1881 *dosmode = state->dosmode;
1882 tevent_req_received(req);
1883 return NT_STATUS_OK;
1886 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1887 struct files_struct *fsp,
1892 offline = vfswrap_is_offline(handle->conn, fsp->fsp_name);
1894 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1897 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1900 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1901 const struct smb_filename *smb_fname,
1904 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1907 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1908 struct files_struct *fsp,
1911 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1914 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1916 struct vfswrap_offload_read_state {
1920 static struct tevent_req *vfswrap_offload_read_send(
1921 TALLOC_CTX *mem_ctx,
1922 struct tevent_context *ev,
1923 struct vfs_handle_struct *handle,
1924 struct files_struct *fsp,
1930 struct tevent_req *req = NULL;
1931 struct vfswrap_offload_read_state *state = NULL;
1934 req = tevent_req_create(mem_ctx, &state,
1935 struct vfswrap_offload_read_state);
1940 status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1941 &vfswrap_offload_ctx);
1942 if (tevent_req_nterror(req, status)) {
1943 return tevent_req_post(req, ev);
1946 if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1947 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1948 return tevent_req_post(req, ev);
1951 status = vfs_offload_token_create_blob(state, fsp, fsctl,
1953 if (tevent_req_nterror(req, status)) {
1954 return tevent_req_post(req, ev);
1957 status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1959 if (tevent_req_nterror(req, status)) {
1960 return tevent_req_post(req, ev);
1963 tevent_req_done(req);
1964 return tevent_req_post(req, ev);
1967 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
1968 struct vfs_handle_struct *handle,
1969 TALLOC_CTX *mem_ctx,
1972 struct vfswrap_offload_read_state *state = tevent_req_data(
1973 req, struct vfswrap_offload_read_state);
1976 if (tevent_req_is_nterror(req, &status)) {
1977 tevent_req_received(req);
1981 token->length = state->token.length;
1982 token->data = talloc_move(mem_ctx, &state->token.data);
1984 tevent_req_received(req);
1985 return NT_STATUS_OK;
1988 struct vfswrap_offload_write_state {
1990 bool read_lck_locked;
1991 bool write_lck_locked;
1993 struct tevent_context *src_ev;
1994 struct files_struct *src_fsp;
1996 struct tevent_context *dst_ev;
1997 struct files_struct *dst_fsp;
2001 size_t next_io_size;
2004 static void vfswrap_offload_write_cleanup(struct tevent_req *req,
2005 enum tevent_req_state req_state)
2007 struct vfswrap_offload_write_state *state = tevent_req_data(
2008 req, struct vfswrap_offload_write_state);
2011 if (state->dst_fsp == NULL) {
2015 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2017 state->dst_fsp = NULL;
2020 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
2022 static struct tevent_req *vfswrap_offload_write_send(
2023 struct vfs_handle_struct *handle,
2024 TALLOC_CTX *mem_ctx,
2025 struct tevent_context *ev,
2028 off_t transfer_offset,
2029 struct files_struct *dest_fsp,
2033 struct tevent_req *req;
2034 struct vfswrap_offload_write_state *state = NULL;
2035 /* off_t is signed! */
2036 off_t max_offset = INT64_MAX - to_copy;
2037 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
2038 files_struct *src_fsp = NULL;
2042 req = tevent_req_create(mem_ctx, &state,
2043 struct vfswrap_offload_write_state);
2048 *state = (struct vfswrap_offload_write_state) {
2050 .src_off = transfer_offset,
2052 .dst_fsp = dest_fsp,
2053 .dst_off = dest_off,
2055 .remaining = to_copy,
2058 tevent_req_set_cleanup_fn(req, vfswrap_offload_write_cleanup);
2061 case FSCTL_SRV_COPYCHUNK:
2062 case FSCTL_SRV_COPYCHUNK_WRITE:
2065 case FSCTL_OFFLOAD_WRITE:
2066 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
2067 return tevent_req_post(req, ev);
2069 case FSCTL_DUP_EXTENTS_TO_FILE:
2070 DBG_DEBUG("COW clones not supported by vfs_default\n");
2071 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2072 return tevent_req_post(req, ev);
2075 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2076 return tevent_req_post(req, ev);
2080 * From here on we assume a copy-chunk fsctl
2084 tevent_req_done(req);
2085 return tevent_req_post(req, ev);
2088 if (state->src_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->src_off < 0) {
2097 * Protect integer checks below.
2099 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2100 return tevent_req_post(req, ev);
2102 if (state->dst_off > max_offset) {
2104 * Protect integer checks below.
2106 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2107 return tevent_req_post(req, ev);
2109 if (state->dst_off < 0) {
2111 * Protect integer checks below.
2113 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2114 return tevent_req_post(req, ev);
2117 status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
2119 if (tevent_req_nterror(req, status)) {
2120 return tevent_req_post(req, ev);
2123 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
2125 status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
2126 if (!NT_STATUS_IS_OK(status)) {
2127 tevent_req_nterror(req, status);
2128 return tevent_req_post(req, ev);
2131 ok = change_to_user_and_service_by_fsp(src_fsp);
2133 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2134 return tevent_req_post(req, ev);
2137 state->src_ev = src_fsp->conn->sconn->ev_ctx;
2138 state->src_fsp = src_fsp;
2140 status = vfs_stat_fsp(src_fsp);
2141 if (tevent_req_nterror(req, status)) {
2142 return tevent_req_post(req, ev);
2145 if (src_fsp->fsp_name->st.st_ex_size < state->src_off + to_copy) {
2147 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
2148 * If the SourceOffset or SourceOffset + Length extends beyond
2149 * the end of file, the server SHOULD<240> treat this as a
2150 * STATUS_END_OF_FILE error.
2152 * <240> Section 3.3.5.15.6: Windows servers will return
2153 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
2155 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
2156 return tevent_req_post(req, ev);
2159 state->buf = talloc_array(state, uint8_t, num);
2160 if (tevent_req_nomem(state->buf, req)) {
2161 return tevent_req_post(req, ev);
2164 status = vfswrap_offload_write_loop(req);
2165 if (!NT_STATUS_IS_OK(status)) {
2166 tevent_req_nterror(req, status);
2167 return tevent_req_post(req, ev);
2173 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
2175 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
2177 struct vfswrap_offload_write_state *state = tevent_req_data(
2178 req, struct vfswrap_offload_write_state);
2179 struct tevent_req *subreq = NULL;
2180 struct lock_struct read_lck;
2184 * This is called under the context of state->src_fsp.
2187 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
2189 init_strict_lock_struct(state->src_fsp,
2190 state->src_fsp->op->global->open_persistent_id,
2192 state->next_io_size,
2196 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
2200 return NT_STATUS_FILE_LOCK_CONFLICT;
2203 subreq = SMB_VFS_PREAD_SEND(state,
2207 state->next_io_size,
2209 if (subreq == NULL) {
2210 return NT_STATUS_NO_MEMORY;
2212 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
2214 return NT_STATUS_OK;
2217 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
2219 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
2221 struct tevent_req *req = tevent_req_callback_data(
2222 subreq, struct tevent_req);
2223 struct vfswrap_offload_write_state *state = tevent_req_data(
2224 req, struct vfswrap_offload_write_state);
2225 struct vfs_aio_state aio_state;
2226 struct lock_struct write_lck;
2230 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
2231 TALLOC_FREE(subreq);
2233 DBG_ERR("read failed: %s\n", strerror(aio_state.error));
2234 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2237 if (nread != state->next_io_size) {
2238 DBG_ERR("Short read, only %zd of %zu\n",
2239 nread, state->next_io_size);
2240 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2244 state->src_off += nread;
2246 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2248 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2252 init_strict_lock_struct(state->dst_fsp,
2253 state->dst_fsp->op->global->open_persistent_id,
2255 state->next_io_size,
2259 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
2263 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
2267 subreq = SMB_VFS_PWRITE_SEND(state,
2271 state->next_io_size,
2273 if (subreq == NULL) {
2274 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2277 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
2280 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
2282 struct tevent_req *req = tevent_req_callback_data(
2283 subreq, struct tevent_req);
2284 struct vfswrap_offload_write_state *state = tevent_req_data(
2285 req, struct vfswrap_offload_write_state);
2286 struct vfs_aio_state aio_state;
2291 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
2292 TALLOC_FREE(subreq);
2293 if (nwritten == -1) {
2294 DBG_ERR("write failed: %s\n", strerror(aio_state.error));
2295 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2298 if (nwritten != state->next_io_size) {
2299 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
2300 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2304 state->dst_off += nwritten;
2306 if (state->remaining < nwritten) {
2307 /* Paranoia check */
2308 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2311 state->remaining -= nwritten;
2312 if (state->remaining == 0) {
2313 tevent_req_done(req);
2317 ok = change_to_user_and_service_by_fsp(state->src_fsp);
2319 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2323 status = vfswrap_offload_write_loop(req);
2324 if (!NT_STATUS_IS_OK(status)) {
2325 tevent_req_nterror(req, status);
2332 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
2333 struct tevent_req *req,
2336 struct vfswrap_offload_write_state *state = tevent_req_data(
2337 req, struct vfswrap_offload_write_state);
2340 if (tevent_req_is_nterror(req, &status)) {
2341 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
2343 tevent_req_received(req);
2347 *copied = state->to_copy;
2348 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
2349 tevent_req_received(req);
2351 return NT_STATUS_OK;
2354 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
2355 TALLOC_CTX *mem_ctx,
2356 struct files_struct *fsp,
2357 struct smb_filename *smb_fname,
2358 uint16_t *_compression_fmt)
2360 return NT_STATUS_INVALID_DEVICE_REQUEST;
2363 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
2364 TALLOC_CTX *mem_ctx,
2365 struct files_struct *fsp,
2366 uint16_t compression_fmt)
2368 return NT_STATUS_INVALID_DEVICE_REQUEST;
2371 /********************************************************************
2372 Given a stat buffer return the allocated size on disk, taking into
2373 account sparse files.
2374 ********************************************************************/
2375 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
2376 struct files_struct *fsp,
2377 const SMB_STRUCT_STAT *sbuf)
2381 START_PROFILE(syscall_get_alloc_size);
2383 if(S_ISDIR(sbuf->st_ex_mode)) {
2388 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2389 /* The type of st_blocksize is blkcnt_t which *MUST* be
2390 signed (according to POSIX) and can be less than 64-bits.
2391 Ensure when we're converting to 64 bits wide we don't
2393 #if defined(SIZEOF_BLKCNT_T_8)
2394 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2395 #elif defined(SIZEOF_BLKCNT_T_4)
2397 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2398 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2401 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2405 * Some file systems do not allocate a block for very
2406 * small files. But for non-empty file should report a
2410 uint64_t filesize = get_file_size_stat(sbuf);
2412 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2416 result = get_file_size_stat(sbuf);
2419 if (fsp && fsp->initial_allocation_size)
2420 result = MAX(result,fsp->initial_allocation_size);
2422 result = smb_roundup(handle->conn, result);
2425 END_PROFILE(syscall_get_alloc_size);
2429 static int vfswrap_unlinkat(vfs_handle_struct *handle,
2430 struct files_struct *dirfsp,
2431 const struct smb_filename *smb_fname,
2436 START_PROFILE(syscall_unlinkat);
2438 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2440 if (is_named_stream(smb_fname)) {
2444 result = unlinkat(fsp_get_pathref_fd(dirfsp),
2445 smb_fname->base_name,
2449 END_PROFILE(syscall_unlinkat);
2453 static int vfswrap_chmod(vfs_handle_struct *handle,
2454 const struct smb_filename *smb_fname,
2459 START_PROFILE(syscall_chmod);
2460 result = chmod(smb_fname->base_name, mode);
2461 END_PROFILE(syscall_chmod);
2465 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2469 START_PROFILE(syscall_fchmod);
2470 #if defined(HAVE_FCHMOD)
2471 result = fchmod(fsp_get_io_fd(fsp), mode);
2477 END_PROFILE(syscall_fchmod);
2481 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2486 START_PROFILE(syscall_fchown);
2487 result = fchown(fsp_get_io_fd(fsp), uid, gid);
2488 END_PROFILE(syscall_fchown);
2496 static int vfswrap_lchown(vfs_handle_struct *handle,
2497 const struct smb_filename *smb_fname,
2503 START_PROFILE(syscall_lchown);
2504 result = lchown(smb_fname->base_name, uid, gid);
2505 END_PROFILE(syscall_lchown);
2509 static int vfswrap_chdir(vfs_handle_struct *handle,
2510 const struct smb_filename *smb_fname)
2514 START_PROFILE(syscall_chdir);
2515 result = chdir(smb_fname->base_name);
2516 END_PROFILE(syscall_chdir);
2520 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2524 struct smb_filename *smb_fname = NULL;
2526 START_PROFILE(syscall_getwd);
2527 result = sys_getwd();
2528 END_PROFILE(syscall_getwd);
2530 if (result == NULL) {
2533 smb_fname = synthetic_smb_fname(ctx,
2540 * sys_getwd() *always* returns malloced memory.
2541 * We must free here to avoid leaks:
2542 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2548 /*********************************************************************
2549 nsec timestamp resolution call. Convert down to whatever the underlying
2550 system will support.
2551 **********************************************************************/
2553 static int vfswrap_ntimes(vfs_handle_struct *handle,
2554 const struct smb_filename *smb_fname,
2555 struct smb_file_time *ft)
2559 START_PROFILE(syscall_ntimes);
2561 if (is_named_stream(smb_fname)) {
2567 if (is_omit_timespec(&ft->atime)) {
2568 ft->atime= smb_fname->st.st_ex_atime;
2571 if (is_omit_timespec(&ft->mtime)) {
2572 ft->mtime = smb_fname->st.st_ex_mtime;
2575 if (!is_omit_timespec(&ft->create_time)) {
2576 set_create_timespec_ea(handle->conn,
2581 if ((timespec_compare(&ft->atime,
2582 &smb_fname->st.st_ex_atime) == 0) &&
2583 (timespec_compare(&ft->mtime,
2584 &smb_fname->st.st_ex_mtime) == 0)) {
2589 #if defined(HAVE_UTIMENSAT)
2591 struct timespec ts[2];
2594 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2596 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2598 if (!((result == -1) && (errno == ENOSYS))) {
2602 #if defined(HAVE_UTIMES)
2604 struct timeval tv[2];
2605 tv[0] = convert_timespec_to_timeval(ft->atime);
2606 tv[1] = convert_timespec_to_timeval(ft->mtime);
2607 result = utimes(smb_fname->base_name, tv);
2609 result = utimes(smb_fname->base_name, NULL);
2611 if (!((result == -1) && (errno == ENOSYS))) {
2615 #if defined(HAVE_UTIME)
2617 struct utimbuf times;
2618 times.actime = convert_timespec_to_time_t(ft->atime);
2619 times.modtime = convert_timespec_to_time_t(ft->mtime);
2620 result = utime(smb_fname->base_name, ×);
2622 result = utime(smb_fname->base_name, NULL);
2624 if (!((result == -1) && (errno == ENOSYS))) {
2632 END_PROFILE(syscall_ntimes);
2636 /*********************************************************************
2637 A version of ftruncate that will write the space on disk if strict
2639 **********************************************************************/
2641 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2643 off_t space_to_write;
2644 uint64_t space_avail;
2645 uint64_t bsize,dfree,dsize;
2648 SMB_STRUCT_STAT *pst;
2651 ok = vfs_valid_pwrite_range(len, 0);
2657 status = vfs_stat_fsp(fsp);
2658 if (!NT_STATUS_IS_OK(status)) {
2661 pst = &fsp->fsp_name->st;
2664 if (S_ISFIFO(pst->st_ex_mode))
2668 if (pst->st_ex_size == len)
2671 /* Shrink - just ftruncate. */
2672 if (pst->st_ex_size > len)
2673 return ftruncate(fsp_get_io_fd(fsp), len);
2675 space_to_write = len - pst->st_ex_size;
2677 /* for allocation try fallocate first. This can fail on some
2678 platforms e.g. when the filesystem doesn't support it and no
2679 emulation is being done by the libc (like on AIX with JFS1). In that
2680 case we do our own emulation. fallocate implementations can
2681 return ENOTSUP or EINVAL in cases like that. */
2682 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2683 if (ret == -1 && errno == ENOSPC) {
2689 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2690 "error %d. Falling back to slow manual allocation\n", errno));
2692 /* available disk space is enough or not? */
2694 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2695 /* space_avail is 1k blocks */
2696 if (space_avail == (uint64_t)-1 ||
2697 ((uint64_t)space_to_write/1024 > space_avail) ) {
2702 /* Write out the real space on disk. */
2703 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2711 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2714 SMB_STRUCT_STAT *pst;
2718 START_PROFILE(syscall_ftruncate);
2720 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->fsp_flags.is_sparse) {
2721 result = strict_allocate_ftruncate(handle, fsp, len);
2722 END_PROFILE(syscall_ftruncate);
2726 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2727 ftruncate if the system supports it. Then I discovered that
2728 you can have some filesystems that support ftruncate
2729 expansion and some that don't! On Linux fat can't do
2730 ftruncate extend but ext2 can. */
2732 result = ftruncate(fsp_get_io_fd(fsp), len);
2734 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2735 extend a file with ftruncate. Provide alternate implementation
2738 /* Do an fstat to see if the file is longer than the requested
2739 size in which case the ftruncate above should have
2740 succeeded or shorter, in which case seek to len - 1 and
2741 write 1 byte of zero */
2742 status = vfs_stat_fsp(fsp);
2743 if (!NT_STATUS_IS_OK(status)) {
2747 /* We need to update the files_struct after successful ftruncate */
2752 pst = &fsp->fsp_name->st;
2755 if (S_ISFIFO(pst->st_ex_mode)) {
2761 if (pst->st_ex_size == len) {
2766 if (pst->st_ex_size > len) {
2767 /* the ftruncate should have worked */
2771 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2779 END_PROFILE(syscall_ftruncate);
2783 static int vfswrap_fallocate(vfs_handle_struct *handle,
2791 START_PROFILE(syscall_fallocate);
2793 result = sys_posix_fallocate(fsp_get_io_fd(fsp), offset, len);
2795 * posix_fallocate returns 0 on success, errno on error
2796 * and doesn't set errno. Make it behave like fallocate()
2797 * which returns -1, and sets errno on failure.
2804 /* sys_fallocate handles filtering of unsupported mode flags */
2805 result = sys_fallocate(fsp_get_io_fd(fsp), mode, offset, len);
2807 END_PROFILE(syscall_fallocate);
2811 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2815 START_PROFILE(syscall_fcntl_lock);
2817 if (fsp->fsp_flags.use_ofd_locks) {
2818 op = map_process_lock_to_ofd_lock(op);
2821 result = fcntl_lock(fsp_get_io_fd(fsp), op, offset, count, type);
2822 END_PROFILE(syscall_fcntl_lock);
2826 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2827 uint32_t share_access, uint32_t access_mask)
2829 START_PROFILE(syscall_kernel_flock);
2830 kernel_flock(fsp_get_io_fd(fsp), share_access, access_mask);
2831 END_PROFILE(syscall_kernel_flock);
2835 static int vfswrap_fcntl(vfs_handle_struct *handle, files_struct *fsp, int cmd,
2839 va_list dup_cmd_arg;
2843 START_PROFILE(syscall_fcntl);
2845 va_copy(dup_cmd_arg, cmd_arg);
2851 #if defined(HAVE_OFD_LOCKS)
2856 #if defined(HAVE_F_OWNER_EX)
2860 #if defined(HAVE_RW_HINTS)
2863 case F_GET_FILE_RW_HINT:
2864 case F_SET_FILE_RW_HINT:
2866 argp = va_arg(dup_cmd_arg, void *);
2867 result = sys_fcntl_ptr(fsp_get_io_fd(fsp), cmd, argp);
2870 val = va_arg(dup_cmd_arg, int);
2871 result = sys_fcntl_int(fsp_get_io_fd(fsp), cmd, val);
2874 va_end(dup_cmd_arg);
2876 END_PROFILE(syscall_fcntl);
2880 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2885 START_PROFILE(syscall_fcntl_getlock);
2887 if (fsp->fsp_flags.use_ofd_locks) {
2888 op = map_process_lock_to_ofd_lock(op);
2891 result = fcntl_getlock(fsp_get_io_fd(fsp), op, poffset, pcount, ptype, ppid);
2892 END_PROFILE(syscall_fcntl_getlock);
2896 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2901 START_PROFILE(syscall_linux_setlease);
2903 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2904 result = linux_setlease(fsp_get_io_fd(fsp), leasetype);
2908 END_PROFILE(syscall_linux_setlease);
2912 static int vfswrap_symlinkat(vfs_handle_struct *handle,
2913 const struct smb_filename *link_target,
2914 struct files_struct *dirfsp,
2915 const struct smb_filename *new_smb_fname)
2919 START_PROFILE(syscall_symlinkat);
2921 result = symlinkat(link_target->base_name,
2922 fsp_get_pathref_fd(dirfsp),
2923 new_smb_fname->base_name);
2924 END_PROFILE(syscall_symlinkat);
2928 static int vfswrap_readlinkat(vfs_handle_struct *handle,
2929 const struct files_struct *dirfsp,
2930 const struct smb_filename *smb_fname,
2936 START_PROFILE(syscall_readlinkat);
2938 result = readlinkat(fsp_get_pathref_fd(dirfsp),
2939 smb_fname->base_name,
2943 END_PROFILE(syscall_readlinkat);
2947 static int vfswrap_linkat(vfs_handle_struct *handle,
2948 files_struct *srcfsp,
2949 const struct smb_filename *old_smb_fname,
2950 files_struct *dstfsp,
2951 const struct smb_filename *new_smb_fname,
2956 START_PROFILE(syscall_linkat);
2958 result = linkat(fsp_get_pathref_fd(srcfsp),
2959 old_smb_fname->base_name,
2960 fsp_get_pathref_fd(dstfsp),
2961 new_smb_fname->base_name,
2964 END_PROFILE(syscall_linkat);
2968 static int vfswrap_mknodat(vfs_handle_struct *handle,
2969 files_struct *dirfsp,
2970 const struct smb_filename *smb_fname,
2976 START_PROFILE(syscall_mknodat);
2978 result = sys_mknodat(fsp_get_pathref_fd(dirfsp),
2979 smb_fname->base_name,
2983 END_PROFILE(syscall_mknodat);
2987 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2989 const struct smb_filename *smb_fname)
2992 struct smb_filename *result_fname = NULL;
2994 START_PROFILE(syscall_realpath);
2995 result = sys_realpath(smb_fname->base_name);
2996 END_PROFILE(syscall_realpath);
2998 result_fname = synthetic_smb_fname(ctx,
3006 return result_fname;
3009 static int vfswrap_chflags(vfs_handle_struct *handle,
3010 const struct smb_filename *smb_fname,
3014 return chflags(smb_fname->base_name, flags);
3021 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
3022 const SMB_STRUCT_STAT *sbuf)
3026 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
3030 key.devid = sbuf->st_ex_dev;
3031 key.inode = sbuf->st_ex_ino;
3032 /* key.extid is unused by default. */
3037 static uint64_t vfswrap_fs_file_id(struct vfs_handle_struct *handle,
3038 const SMB_STRUCT_STAT *psbuf)
3042 if (!(psbuf->st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)) {
3043 return psbuf->st_ex_file_id;
3046 if (handle->conn->base_share_dev == psbuf->st_ex_dev) {
3047 return (uint64_t)psbuf->st_ex_ino;
3051 file_id = ((psbuf->st_ex_ino) & UINT32_MAX);
3054 file_id |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32;
3059 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
3060 struct files_struct *fsp,
3061 const struct smb_filename *smb_fname,
3062 TALLOC_CTX *mem_ctx,
3063 unsigned int *pnum_streams,
3064 struct stream_struct **pstreams)
3066 SMB_STRUCT_STAT sbuf;
3067 struct stream_struct *tmp_streams = NULL;
3070 if ((fsp != NULL) && (fsp->fsp_flags.is_directory)) {
3072 * No default streams on directories
3077 if ((fsp != NULL) && (fsp_get_pathref_fd(fsp) != -1)) {
3078 ret = SMB_VFS_FSTAT(fsp, &sbuf);
3081 struct smb_filename *smb_fname_cp = NULL;
3083 smb_fname_cp = cp_smb_filename_nostream(talloc_tos(), smb_fname);
3084 if (smb_fname_cp == NULL) {
3085 return NT_STATUS_NO_MEMORY;
3088 ret = vfs_stat(handle->conn, smb_fname_cp);
3089 sbuf = smb_fname_cp->st;
3090 TALLOC_FREE(smb_fname_cp);
3094 return map_nt_error_from_unix(errno);
3097 if (S_ISDIR(sbuf.st_ex_mode)) {
3101 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
3102 (*pnum_streams) + 1);
3103 if (tmp_streams == NULL) {
3104 return NT_STATUS_NO_MEMORY;
3106 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
3107 if (tmp_streams[*pnum_streams].name == NULL) {
3108 return NT_STATUS_NO_MEMORY;
3110 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
3111 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
3114 *pstreams = tmp_streams;
3116 return NT_STATUS_OK;
3119 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
3120 const struct smb_filename *path,
3122 TALLOC_CTX *mem_ctx,
3126 * Don't fall back to get_real_filename so callers can differentiate
3127 * between a full directory scan and an actual case-insensitive stat.
3133 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
3134 const struct smb_filename *smb_fname)
3136 return handle->conn->connectpath;
3139 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
3140 struct byte_range_lock *br_lck,
3141 struct lock_struct *plock)
3143 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3145 /* Note: blr is not used in the default implementation. */
3146 return brl_lock_windows_default(br_lck, plock);
3149 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
3150 struct byte_range_lock *br_lck,
3151 const struct lock_struct *plock)
3153 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3155 return brl_unlock_windows_default(br_lck, plock);
3158 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
3160 struct lock_struct *plock)
3162 SMB_ASSERT(plock->lock_type == READ_LOCK ||
3163 plock->lock_type == WRITE_LOCK);
3165 return strict_lock_check_default(fsp, plock);
3168 /* NT ACL operations. */
3170 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
3172 uint32_t security_info,
3173 TALLOC_CTX *mem_ctx,
3174 struct security_descriptor **ppdesc)
3178 START_PROFILE(fget_nt_acl);
3179 result = posix_fget_nt_acl(fsp, security_info,
3181 END_PROFILE(fget_nt_acl);
3185 static NTSTATUS vfswrap_get_nt_acl_at(vfs_handle_struct *handle,
3186 struct files_struct *dirfsp,
3187 const struct smb_filename *smb_fname,
3188 uint32_t security_info,
3189 TALLOC_CTX *mem_ctx,
3190 struct security_descriptor **ppdesc)
3194 START_PROFILE(get_nt_acl_at);
3196 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
3198 result = posix_get_nt_acl(handle->conn,
3203 END_PROFILE(get_nt_acl_at);
3207 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
3211 START_PROFILE(fset_nt_acl);
3212 result = set_nt_acl(fsp, security_info_sent, psd);
3213 END_PROFILE(fset_nt_acl);
3217 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
3218 struct smb_filename *file,
3219 struct security_acl *sacl,
3220 uint32_t access_requested,
3221 uint32_t access_denied)
3223 return NT_STATUS_OK; /* Nothing to do here ... */
3226 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
3227 const struct smb_filename *smb_fname,
3228 SMB_ACL_TYPE_T type,
3229 TALLOC_CTX *mem_ctx)
3231 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
3234 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
3236 TALLOC_CTX *mem_ctx)
3238 return sys_acl_get_fd(handle, fsp, mem_ctx);
3241 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
3242 const struct smb_filename *smb_fname,
3243 SMB_ACL_TYPE_T acltype,
3246 return sys_acl_set_file(handle, smb_fname, acltype, theacl);
3249 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
3251 return sys_acl_set_fd(handle, fsp, theacl);
3254 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
3255 const struct smb_filename *smb_fname)
3257 return sys_acl_delete_def_file(handle, smb_fname);
3260 /****************************************************************
3261 Extended attribute operations.
3262 *****************************************************************/
3264 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
3265 const struct smb_filename *smb_fname,
3270 return getxattr(smb_fname->base_name, name, value, size);
3273 struct vfswrap_getxattrat_state {
3274 struct tevent_context *ev;
3275 files_struct *dir_fsp;
3276 const struct smb_filename *smb_fname;
3279 * The following variables are talloced off "state" which is protected
3280 * by a destructor and thus are guaranteed to be safe to be used in the
3281 * job function in the worker thread.
3284 const char *xattr_name;
3285 uint8_t *xattr_value;
3286 struct security_unix_token *token;
3289 struct vfs_aio_state vfs_aio_state;
3290 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
3293 static int vfswrap_getxattrat_state_destructor(
3294 struct vfswrap_getxattrat_state *state)
3299 static void vfswrap_getxattrat_do_sync(struct tevent_req *req);
3300 static void vfswrap_getxattrat_do_async(void *private_data);
3301 static void vfswrap_getxattrat_done(struct tevent_req *subreq);
3303 static struct tevent_req *vfswrap_getxattrat_send(
3304 TALLOC_CTX *mem_ctx,
3305 struct tevent_context *ev,
3306 struct vfs_handle_struct *handle,
3307 files_struct *dir_fsp,
3308 const struct smb_filename *smb_fname,
3309 const char *xattr_name,
3312 struct tevent_req *req = NULL;
3313 struct tevent_req *subreq = NULL;
3314 struct vfswrap_getxattrat_state *state = NULL;
3315 size_t max_threads = 0;
3316 bool have_per_thread_cwd = false;
3317 bool have_per_thread_creds = false;
3318 bool do_async = false;
3320 req = tevent_req_create(mem_ctx, &state,
3321 struct vfswrap_getxattrat_state);
3325 *state = (struct vfswrap_getxattrat_state) {
3328 .smb_fname = smb_fname,
3331 max_threads = pthreadpool_tevent_max_threads(dir_fsp->conn->sconn->pool);
3332 if (max_threads >= 1) {
3334 * We need a non sync threadpool!
3336 have_per_thread_cwd = per_thread_cwd_supported();
3338 #ifdef HAVE_LINUX_THREAD_CREDENTIALS
3339 have_per_thread_creds = true;
3341 if (have_per_thread_cwd && have_per_thread_creds) {
3345 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat, profile_p,
3346 state->profile_bytes, 0);
3348 if (fsp_get_pathref_fd(dir_fsp) == -1) {
3349 DBG_ERR("Need a valid directory fd\n");
3350 tevent_req_error(req, EINVAL);
3351 return tevent_req_post(req, ev);
3354 if (alloc_hint > 0) {
3355 state->xattr_value = talloc_zero_array(state,
3358 if (tevent_req_nomem(state->xattr_value, req)) {
3359 return tevent_req_post(req, ev);
3364 vfswrap_getxattrat_do_sync(req);
3365 return tevent_req_post(req, ev);
3369 * Now allocate all parameters from a memory context that won't go away
3370 * no matter what. These paremeters will get used in threads and we
3371 * can't reliably cancel threads, so all buffers passed to the threads
3372 * must not be freed before all referencing threads terminate.
3375 state->name = talloc_strdup(state, smb_fname->base_name);
3376 if (tevent_req_nomem(state->name, req)) {
3377 return tevent_req_post(req, ev);
3380 state->xattr_name = talloc_strdup(state, xattr_name);
3381 if (tevent_req_nomem(state->xattr_name, req)) {
3382 return tevent_req_post(req, ev);
3386 * This is a hot codepath so at first glance one might think we should
3387 * somehow optimize away the token allocation and do a
3388 * talloc_reference() or similar black magic instead. But due to the
3389 * talloc_stackframe pool per SMB2 request this should be a simple copy
3390 * without a malloc in most cases.
3392 if (geteuid() == sec_initial_uid()) {
3393 state->token = root_unix_token(state);
3395 state->token = copy_unix_token(
3397 dir_fsp->conn->session_info->unix_token);
3399 if (tevent_req_nomem(state->token, req)) {
3400 return tevent_req_post(req, ev);
3403 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3405 subreq = pthreadpool_tevent_job_send(
3408 dir_fsp->conn->sconn->pool,
3409 vfswrap_getxattrat_do_async,
3411 if (tevent_req_nomem(subreq, req)) {
3412 return tevent_req_post(req, ev);
3414 tevent_req_set_callback(subreq, vfswrap_getxattrat_done, req);
3416 talloc_set_destructor(state, vfswrap_getxattrat_state_destructor);
3421 static void vfswrap_getxattrat_do_sync(struct tevent_req *req)
3423 struct vfswrap_getxattrat_state *state = tevent_req_data(
3424 req, struct vfswrap_getxattrat_state);
3426 char *tofree = NULL;
3427 char pathbuf[PATH_MAX+1];
3431 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
3432 state->smb_fname->base_name,
3437 if (pathlen == -1) {
3438 tevent_req_error(req, ENOMEM);
3442 state->xattr_size = getxattr(path,
3445 talloc_array_length(state->xattr_value));
3447 TALLOC_FREE(tofree);
3448 if (state->xattr_size == -1) {
3449 tevent_req_error(req, err);
3453 tevent_req_done(req);
3457 static void vfswrap_getxattrat_do_async(void *private_data)
3459 struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3460 private_data, struct vfswrap_getxattrat_state);
3461 struct timespec start_time;
3462 struct timespec end_time;
3465 PROFILE_TIMESTAMP(&start_time);
3466 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
3469 * Here we simulate a getxattrat()
3470 * call using fchdir();getxattr()
3473 per_thread_cwd_activate();
3475 /* Become the correct credential on this thread. */
3476 ret = set_thread_credentials(state->token->uid,
3478 (size_t)state->token->ngroups,
3479 state->token->groups);
3481 state->xattr_size = -1;
3482 state->vfs_aio_state.error = errno;
3486 ret = fchdir(fsp_get_pathref_fd(state->dir_fsp));
3488 state->xattr_size = -1;
3489 state->vfs_aio_state.error = errno;
3493 state->xattr_size = getxattr(state->name,
3496 talloc_array_length(state->xattr_value));
3497 if (state->xattr_size == -1) {
3498 state->vfs_aio_state.error = errno;
3502 PROFILE_TIMESTAMP(&end_time);
3503 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
3504 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3507 static void vfswrap_getxattrat_done(struct tevent_req *subreq)
3509 struct tevent_req *req = tevent_req_callback_data(
3510 subreq, struct tevent_req);
3511 struct vfswrap_getxattrat_state *state = tevent_req_data(
3512 req, struct vfswrap_getxattrat_state);
3517 * Make sure we run as the user again
3519 ok = change_to_user_and_service_by_fsp(state->dir_fsp);
3522 ret = pthreadpool_tevent_job_recv(subreq);
3523 TALLOC_FREE(subreq);
3524 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
3525 talloc_set_destructor(state, NULL);
3527 if (ret != EAGAIN) {
3528 tevent_req_error(req, ret);
3532 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
3533 * means the lower level pthreadpool failed to create a new
3534 * thread. Fallback to sync processing in that case to allow
3535 * some progress for the client.
3537 vfswrap_getxattrat_do_sync(req);
3541 if (state->xattr_size == -1) {
3542 tevent_req_error(req, state->vfs_aio_state.error);
3546 if (state->xattr_value == NULL) {
3548 * The caller only wanted the size.
3550 tevent_req_done(req);
3555 * shrink the buffer to the returned size.
3556 * (can't fail). It means NULL if size is 0.
3558 state->xattr_value = talloc_realloc(state,
3563 tevent_req_done(req);
3566 static ssize_t vfswrap_getxattrat_recv(struct tevent_req *req,
3567 struct vfs_aio_state *aio_state,
3568 TALLOC_CTX *mem_ctx,
3569 uint8_t **xattr_value)
3571 struct vfswrap_getxattrat_state *state = tevent_req_data(
3572 req, struct vfswrap_getxattrat_state);
3575 if (tevent_req_is_unix_error(req, &aio_state->error)) {
3576 tevent_req_received(req);
3580 *aio_state = state->vfs_aio_state;
3581 xattr_size = state->xattr_size;
3582 if (xattr_value != NULL) {
3583 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
3586 tevent_req_received(req);
3590 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle,
3591 struct files_struct *fsp,
3596 int fd = fsp_get_pathref_fd(fsp);
3598 if (!fsp->fsp_flags.is_pathref) {
3599 return fgetxattr(fd, name, value, size);
3602 if (fsp->fsp_flags.have_proc_fds) {
3603 const char *p = NULL;
3606 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3611 return getxattr(p, name, value, size);
3615 * This is no longer a handle based call.
3617 return getxattr(fsp->fsp_name->base_name, name, value, size);
3620 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
3621 const struct smb_filename *smb_fname,
3625 return listxattr(smb_fname->base_name, list, size);
3628 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
3630 int fd = fsp_get_pathref_fd(fsp);
3632 if (!fsp->fsp_flags.is_pathref) {
3633 return flistxattr(fd, list, size);
3636 if (fsp->fsp_flags.have_proc_fds) {
3637 const char *p = NULL;
3640 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3645 return listxattr(p, list, size);
3649 * This is no longer a handle based call.
3651 return listxattr(fsp->fsp_name->base_name, list, size);
3654 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
3655 const struct smb_filename *smb_fname,
3658 return removexattr(smb_fname->base_name, name);
3661 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
3663 int fd = fsp_get_pathref_fd(fsp);
3665 if (!fsp->fsp_flags.is_pathref) {
3666 return fremovexattr(fd, name);
3669 if (fsp->fsp_flags.have_proc_fds) {
3670 const char *p = NULL;
3673 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3678 return removexattr(p, name);
3682 * This is no longer a handle based call.
3684 return removexattr(fsp->fsp_name->base_name, name);
3687 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
3688 const struct smb_filename *smb_fname,
3694 return setxattr(smb_fname->base_name, name, value, size, flags);
3697 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
3699 int fd = fsp_get_pathref_fd(fsp);
3701 if (!fsp->fsp_flags.is_pathref) {
3702 return fsetxattr(fd, name, value, size, flags);
3705 if (fsp->fsp_flags.have_proc_fds) {
3706 const char *p = NULL;
3709 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3714 return setxattr(p, name, value, size, flags);
3718 * This is no longer a handle based call.
3720 return setxattr(fsp->fsp_name->base_name, name, value, size, flags);
3723 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
3728 static bool vfswrap_is_offline(struct connection_struct *conn,
3729 const struct smb_filename *fname)
3733 bool offline = false;
3735 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
3739 if (!lp_dmapi_support(SNUM(conn)) || !dmapi_have_session()) {
3740 #if defined(ENOTSUP)
3746 status = get_full_smb_filename(talloc_tos(), fname, &path);
3747 if (!NT_STATUS_IS_OK(status)) {
3748 errno = map_errno_from_nt_status(status);
3752 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
3759 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
3760 struct files_struct *fsp,
3761 TALLOC_CTX *mem_ctx,
3764 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
3767 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
3768 struct files_struct *fsp,
3769 const DATA_BLOB old_cookie,
3770 TALLOC_CTX *mem_ctx,
3771 DATA_BLOB *new_cookie)
3773 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
3777 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
3778 struct smb_request *smb1req,
3779 struct smbXsrv_open *op,
3780 const DATA_BLOB old_cookie,
3781 TALLOC_CTX *mem_ctx,
3782 struct files_struct **fsp,
3783 DATA_BLOB *new_cookie)
3785 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
3786 old_cookie, mem_ctx,
3790 static struct vfs_fn_pointers vfs_default_fns = {
3791 /* Disk operations */
3793 .connect_fn = vfswrap_connect,
3794 .disconnect_fn = vfswrap_disconnect,
3795 .disk_free_fn = vfswrap_disk_free,
3796 .get_quota_fn = vfswrap_get_quota,
3797 .set_quota_fn = vfswrap_set_quota,
3798 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3799 .statvfs_fn = vfswrap_statvfs,
3800 .fs_capabilities_fn = vfswrap_fs_capabilities,
3801 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3802 .create_dfs_pathat_fn = vfswrap_create_dfs_pathat,
3803 .read_dfs_pathat_fn = vfswrap_read_dfs_pathat,
3804 .snap_check_path_fn = vfswrap_snap_check_path,
3805 .snap_create_fn = vfswrap_snap_create,
3806 .snap_delete_fn = vfswrap_snap_delete,
3808 /* Directory operations */
3810 .fdopendir_fn = vfswrap_fdopendir,
3811 .readdir_fn = vfswrap_readdir,
3812 .readdir_attr_fn = vfswrap_readdir_attr,
3813 .seekdir_fn = vfswrap_seekdir,
3814 .telldir_fn = vfswrap_telldir,
3815 .rewind_dir_fn = vfswrap_rewinddir,
3816 .mkdirat_fn = vfswrap_mkdirat,
3817 .closedir_fn = vfswrap_closedir,
3819 /* File operations */
3821 .openat_fn = vfswrap_openat,
3822 .create_file_fn = vfswrap_create_file,
3823 .close_fn = vfswrap_close,
3824 .pread_fn = vfswrap_pread,
3825 .pread_send_fn = vfswrap_pread_send,
3826 .pread_recv_fn = vfswrap_pread_recv,
3827 .pwrite_fn = vfswrap_pwrite,
3828 .pwrite_send_fn = vfswrap_pwrite_send,
3829 .pwrite_recv_fn = vfswrap_pwrite_recv,
3830 .lseek_fn = vfswrap_lseek,
3831 .sendfile_fn = vfswrap_sendfile,
3832 .recvfile_fn = vfswrap_recvfile,
3833 .renameat_fn = vfswrap_renameat,
3834 .fsync_send_fn = vfswrap_fsync_send,
3835 .fsync_recv_fn = vfswrap_fsync_recv,
3836 .stat_fn = vfswrap_stat,
3837 .fstat_fn = vfswrap_fstat,
3838 .lstat_fn = vfswrap_lstat,
3839 .get_alloc_size_fn = vfswrap_get_alloc_size,
3840 .unlinkat_fn = vfswrap_unlinkat,
3841 .chmod_fn = vfswrap_chmod,
3842 .fchmod_fn = vfswrap_fchmod,
3843 .fchown_fn = vfswrap_fchown,
3844 .lchown_fn = vfswrap_lchown,
3845 .chdir_fn = vfswrap_chdir,
3846 .getwd_fn = vfswrap_getwd,
3847 .ntimes_fn = vfswrap_ntimes,
3848 .ftruncate_fn = vfswrap_ftruncate,
3849 .fallocate_fn = vfswrap_fallocate,
3850 .lock_fn = vfswrap_lock,
3851 .kernel_flock_fn = vfswrap_kernel_flock,
3852 .fcntl_fn = vfswrap_fcntl,
3853 .linux_setlease_fn = vfswrap_linux_setlease,
3854 .getlock_fn = vfswrap_getlock,
3855 .symlinkat_fn = vfswrap_symlinkat,
3856 .readlinkat_fn = vfswrap_readlinkat,
3857 .linkat_fn = vfswrap_linkat,
3858 .mknodat_fn = vfswrap_mknodat,
3859 .realpath_fn = vfswrap_realpath,
3860 .chflags_fn = vfswrap_chflags,
3861 .file_id_create_fn = vfswrap_file_id_create,
3862 .fs_file_id_fn = vfswrap_fs_file_id,
3863 .streaminfo_fn = vfswrap_streaminfo,
3864 .get_real_filename_fn = vfswrap_get_real_filename,
3865 .connectpath_fn = vfswrap_connectpath,
3866 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
3867 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3868 .strict_lock_check_fn = vfswrap_strict_lock_check,
3869 .translate_name_fn = vfswrap_translate_name,
3870 .fsctl_fn = vfswrap_fsctl,
3871 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
3872 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
3873 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
3874 .get_dos_attributes_send_fn = vfswrap_get_dos_attributes_send,
3875 .get_dos_attributes_recv_fn = vfswrap_get_dos_attributes_recv,
3876 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
3877 .offload_read_send_fn = vfswrap_offload_read_send,
3878 .offload_read_recv_fn = vfswrap_offload_read_recv,
3879 .offload_write_send_fn = vfswrap_offload_write_send,
3880 .offload_write_recv_fn = vfswrap_offload_write_recv,
3881 .get_compression_fn = vfswrap_get_compression,
3882 .set_compression_fn = vfswrap_set_compression,
3884 /* NT ACL operations. */
3886 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
3887 .get_nt_acl_at_fn = vfswrap_get_nt_acl_at,
3888 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
3889 .audit_file_fn = vfswrap_audit_file,
3891 /* POSIX ACL operations. */
3893 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
3894 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3895 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
3896 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3897 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
3898 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3899 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
3901 /* EA operations. */
3902 .getxattr_fn = vfswrap_getxattr,
3903 .getxattrat_send_fn = vfswrap_getxattrat_send,
3904 .getxattrat_recv_fn = vfswrap_getxattrat_recv,
3905 .fgetxattr_fn = vfswrap_fgetxattr,
3906 .listxattr_fn = vfswrap_listxattr,
3907 .flistxattr_fn = vfswrap_flistxattr,
3908 .removexattr_fn = vfswrap_removexattr,
3909 .fremovexattr_fn = vfswrap_fremovexattr,
3910 .setxattr_fn = vfswrap_setxattr,
3911 .fsetxattr_fn = vfswrap_fsetxattr,
3913 /* aio operations */
3914 .aio_force_fn = vfswrap_aio_force,
3916 /* durable handle operations */
3917 .durable_cookie_fn = vfswrap_durable_cookie,
3918 .durable_disconnect_fn = vfswrap_durable_disconnect,
3919 .durable_reconnect_fn = vfswrap_durable_reconnect,
3923 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3926 * Here we need to implement every call!
3928 * As this is the end of the vfs module chain.
3930 smb_vfs_assert_all_fns(&vfs_default_fns, DEFAULT_VFS_MODULE_NAME);
3931 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3932 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);