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;
580 START_PROFILE(syscall_readdir);
581 result = readdir(dirp);
582 END_PROFILE(syscall_readdir);
584 /* Default Posix readdir() does not give us stat info.
585 * Set to invalid to indicate we didn't return this info. */
586 SET_STAT_INVALID(*sbuf);
587 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
588 if (result != NULL) {
589 /* See if we can efficiently return this. */
591 int flags = AT_SYMLINK_NOFOLLOW;
592 int ret = fstatat(dirfd(dirp),
597 * As this is an optimization,
598 * ignore it if we stat'ed a
599 * symlink. Make the caller
600 * do it again as we don't
601 * know if they wanted the link
602 * info, or its target info.
604 if ((ret == 0) && (!S_ISLNK(st.st_mode))) {
605 init_stat_ex_from_stat(sbuf,
607 lp_fake_directory_create_times(
608 SNUM(handle->conn)));
616 static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
617 const struct smb_filename *fname,
619 struct readdir_attr_data **attr_data)
621 return NT_STATUS_NOT_SUPPORTED;
624 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
626 START_PROFILE(syscall_seekdir);
627 seekdir(dirp, offset);
628 END_PROFILE(syscall_seekdir);
631 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
634 START_PROFILE(syscall_telldir);
635 result = telldir(dirp);
636 END_PROFILE(syscall_telldir);
640 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
642 START_PROFILE(syscall_rewinddir);
644 END_PROFILE(syscall_rewinddir);
647 static int vfswrap_mkdirat(vfs_handle_struct *handle,
648 struct files_struct *dirfsp,
649 const struct smb_filename *smb_fname,
653 struct smb_filename *parent = NULL;
656 START_PROFILE(syscall_mkdirat);
658 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
660 if (lp_inherit_acls(SNUM(handle->conn))) {
661 ok = parent_smb_fname(talloc_tos(), smb_fname, &parent, NULL);
662 if (ok && directory_has_default_acl(handle->conn,
666 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
672 result = mkdirat(fsp_get_pathref_fd(dirfsp), smb_fname->base_name, mode);
674 END_PROFILE(syscall_mkdirat);
678 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
682 START_PROFILE(syscall_closedir);
683 result = closedir(dirp);
684 END_PROFILE(syscall_closedir);
688 /* File operations */
690 static int vfswrap_openat(vfs_handle_struct *handle,
691 const struct files_struct *dirfsp,
692 const struct smb_filename *smb_fname,
697 bool have_opath = false;
698 bool became_root = false;
701 START_PROFILE(syscall_openat);
703 if (is_named_stream(smb_fname)) {
711 if (fsp->fsp_flags.is_pathref) {
716 if (fsp->fsp_flags.is_pathref && !have_opath) {
721 result = openat(fsp_get_pathref_fd(dirfsp),
722 smb_fname->base_name,
730 fsp->fsp_flags.have_proc_fds = fsp->conn->have_proc_fds;
733 END_PROFILE(syscall_openat);
736 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
737 struct smb_request *req,
738 struct smb_filename *smb_fname,
739 uint32_t access_mask,
740 uint32_t share_access,
741 uint32_t create_disposition,
742 uint32_t create_options,
743 uint32_t file_attributes,
744 uint32_t oplock_request,
745 const struct smb2_lease *lease,
746 uint64_t allocation_size,
747 uint32_t private_flags,
748 struct security_descriptor *sd,
749 struct ea_list *ea_list,
750 files_struct **result,
752 const struct smb2_create_blobs *in_context_blobs,
753 struct smb2_create_blobs *out_context_blobs)
755 return create_file_default(handle->conn, req, smb_fname,
756 access_mask, share_access,
757 create_disposition, create_options,
758 file_attributes, oplock_request, lease,
759 allocation_size, private_flags,
761 pinfo, in_context_blobs, out_context_blobs);
764 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
768 START_PROFILE(syscall_close);
769 result = fd_close_posix(fsp);
770 END_PROFILE(syscall_close);
774 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
775 size_t n, off_t offset)
779 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
780 START_PROFILE_BYTES(syscall_pread, n);
781 result = sys_pread_full(fsp_get_io_fd(fsp), data, n, offset);
782 END_PROFILE_BYTES(syscall_pread);
784 if (result == -1 && errno == ESPIPE) {
785 /* Maintain the fiction that pipes can be seeked (sought?) on. */
786 result = sys_read(fsp_get_io_fd(fsp), data, n);
787 fh_set_pos(fsp->fh, 0);
790 #else /* HAVE_PREAD */
793 #endif /* HAVE_PREAD */
798 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
799 size_t n, off_t offset)
803 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
804 START_PROFILE_BYTES(syscall_pwrite, n);
805 result = sys_pwrite_full(fsp_get_io_fd(fsp), data, n, offset);
806 END_PROFILE_BYTES(syscall_pwrite);
808 if (result == -1 && errno == ESPIPE) {
809 /* Maintain the fiction that pipes can be sought on. */
810 result = sys_write(fsp_get_io_fd(fsp), data, n);
813 #else /* HAVE_PWRITE */
816 #endif /* HAVE_PWRITE */
821 struct vfswrap_pread_state {
828 struct vfs_aio_state vfs_aio_state;
829 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
832 static void vfs_pread_do(void *private_data);
833 static void vfs_pread_done(struct tevent_req *subreq);
834 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state);
836 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
838 struct tevent_context *ev,
839 struct files_struct *fsp,
841 size_t n, off_t offset)
843 struct tevent_req *req, *subreq;
844 struct vfswrap_pread_state *state;
846 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
852 state->fd = fsp_get_io_fd(fsp);
855 state->offset = offset;
857 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
858 state->profile_bytes, n);
859 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
861 subreq = pthreadpool_tevent_job_send(
862 state, ev, handle->conn->sconn->pool,
863 vfs_pread_do, state);
864 if (tevent_req_nomem(subreq, req)) {
865 return tevent_req_post(req, ev);
867 tevent_req_set_callback(subreq, vfs_pread_done, req);
869 talloc_set_destructor(state, vfs_pread_state_destructor);
874 static void vfs_pread_do(void *private_data)
876 struct vfswrap_pread_state *state = talloc_get_type_abort(
877 private_data, struct vfswrap_pread_state);
878 struct timespec start_time;
879 struct timespec end_time;
881 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
883 PROFILE_TIMESTAMP(&start_time);
885 state->ret = sys_pread_full(state->fd,
890 if (state->ret == -1) {
891 state->vfs_aio_state.error = errno;
894 PROFILE_TIMESTAMP(&end_time);
896 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
898 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
901 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state)
906 static void vfs_pread_done(struct tevent_req *subreq)
908 struct tevent_req *req = tevent_req_callback_data(
909 subreq, struct tevent_req);
910 struct vfswrap_pread_state *state = tevent_req_data(
911 req, struct vfswrap_pread_state);
914 ret = pthreadpool_tevent_job_recv(subreq);
916 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
917 talloc_set_destructor(state, NULL);
920 tevent_req_error(req, ret);
924 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
925 * means the lower level pthreadpool failed to create a new
926 * thread. Fallback to sync processing in that case to allow
927 * some progress for the client.
932 tevent_req_done(req);
935 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
936 struct vfs_aio_state *vfs_aio_state)
938 struct vfswrap_pread_state *state = tevent_req_data(
939 req, struct vfswrap_pread_state);
941 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
945 *vfs_aio_state = state->vfs_aio_state;
949 struct vfswrap_pwrite_state {
956 struct vfs_aio_state vfs_aio_state;
957 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
960 static void vfs_pwrite_do(void *private_data);
961 static void vfs_pwrite_done(struct tevent_req *subreq);
962 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state);
964 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
966 struct tevent_context *ev,
967 struct files_struct *fsp,
969 size_t n, off_t offset)
971 struct tevent_req *req, *subreq;
972 struct vfswrap_pwrite_state *state;
974 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
980 state->fd = fsp_get_io_fd(fsp);
983 state->offset = offset;
985 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
986 state->profile_bytes, n);
987 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
989 subreq = pthreadpool_tevent_job_send(
990 state, ev, handle->conn->sconn->pool,
991 vfs_pwrite_do, state);
992 if (tevent_req_nomem(subreq, req)) {
993 return tevent_req_post(req, ev);
995 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
997 talloc_set_destructor(state, vfs_pwrite_state_destructor);
1002 static void vfs_pwrite_do(void *private_data)
1004 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
1005 private_data, struct vfswrap_pwrite_state);
1006 struct timespec start_time;
1007 struct timespec end_time;
1009 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
1011 PROFILE_TIMESTAMP(&start_time);
1013 state->ret = sys_pwrite_full(state->fd,
1018 if (state->ret == -1) {
1019 state->vfs_aio_state.error = errno;
1022 PROFILE_TIMESTAMP(&end_time);
1024 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1026 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1029 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state)
1034 static void vfs_pwrite_done(struct tevent_req *subreq)
1036 struct tevent_req *req = tevent_req_callback_data(
1037 subreq, struct tevent_req);
1038 struct vfswrap_pwrite_state *state = tevent_req_data(
1039 req, struct vfswrap_pwrite_state);
1042 ret = pthreadpool_tevent_job_recv(subreq);
1043 TALLOC_FREE(subreq);
1044 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1045 talloc_set_destructor(state, NULL);
1047 if (ret != EAGAIN) {
1048 tevent_req_error(req, ret);
1052 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1053 * means the lower level pthreadpool failed to create a new
1054 * thread. Fallback to sync processing in that case to allow
1055 * some progress for the client.
1057 vfs_pwrite_do(state);
1060 tevent_req_done(req);
1063 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
1064 struct vfs_aio_state *vfs_aio_state)
1066 struct vfswrap_pwrite_state *state = tevent_req_data(
1067 req, struct vfswrap_pwrite_state);
1069 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1073 *vfs_aio_state = state->vfs_aio_state;
1077 struct vfswrap_fsync_state {
1081 struct vfs_aio_state vfs_aio_state;
1082 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
1085 static void vfs_fsync_do(void *private_data);
1086 static void vfs_fsync_done(struct tevent_req *subreq);
1087 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state);
1089 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
1090 TALLOC_CTX *mem_ctx,
1091 struct tevent_context *ev,
1092 struct files_struct *fsp)
1094 struct tevent_req *req, *subreq;
1095 struct vfswrap_fsync_state *state;
1097 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
1103 state->fd = fsp_get_io_fd(fsp);
1105 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_fsync, profile_p,
1106 state->profile_bytes, 0);
1107 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1109 subreq = pthreadpool_tevent_job_send(
1110 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
1111 if (tevent_req_nomem(subreq, req)) {
1112 return tevent_req_post(req, ev);
1114 tevent_req_set_callback(subreq, vfs_fsync_done, req);
1116 talloc_set_destructor(state, vfs_fsync_state_destructor);
1121 static void vfs_fsync_do(void *private_data)
1123 struct vfswrap_fsync_state *state = talloc_get_type_abort(
1124 private_data, struct vfswrap_fsync_state);
1125 struct timespec start_time;
1126 struct timespec end_time;
1128 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
1130 PROFILE_TIMESTAMP(&start_time);
1133 state->ret = fsync(state->fd);
1134 } while ((state->ret == -1) && (errno == EINTR));
1136 if (state->ret == -1) {
1137 state->vfs_aio_state.error = errno;
1140 PROFILE_TIMESTAMP(&end_time);
1142 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1144 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1147 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state)
1152 static void vfs_fsync_done(struct tevent_req *subreq)
1154 struct tevent_req *req = tevent_req_callback_data(
1155 subreq, struct tevent_req);
1156 struct vfswrap_fsync_state *state = tevent_req_data(
1157 req, struct vfswrap_fsync_state);
1160 ret = pthreadpool_tevent_job_recv(subreq);
1161 TALLOC_FREE(subreq);
1162 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1163 talloc_set_destructor(state, NULL);
1165 if (ret != EAGAIN) {
1166 tevent_req_error(req, ret);
1170 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1171 * means the lower level pthreadpool failed to create a new
1172 * thread. Fallback to sync processing in that case to allow
1173 * some progress for the client.
1175 vfs_fsync_do(state);
1178 tevent_req_done(req);
1181 static int vfswrap_fsync_recv(struct tevent_req *req,
1182 struct vfs_aio_state *vfs_aio_state)
1184 struct vfswrap_fsync_state *state = tevent_req_data(
1185 req, struct vfswrap_fsync_state);
1187 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1191 *vfs_aio_state = state->vfs_aio_state;
1195 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1199 START_PROFILE(syscall_lseek);
1201 result = lseek(fsp_get_io_fd(fsp), offset, whence);
1203 * We want to maintain the fiction that we can seek
1204 * on a fifo for file system purposes. This allows
1205 * people to set up UNIX fifo's that feed data to Windows
1206 * applications. JRA.
1209 if((result == -1) && (errno == ESPIPE)) {
1214 END_PROFILE(syscall_lseek);
1218 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1219 off_t offset, size_t n)
1223 START_PROFILE_BYTES(syscall_sendfile, n);
1224 result = sys_sendfile(tofd, fsp_get_io_fd(fromfsp), hdr, offset, n);
1225 END_PROFILE_BYTES(syscall_sendfile);
1229 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1231 files_struct *tofsp,
1237 START_PROFILE_BYTES(syscall_recvfile, n);
1238 result = sys_recvfile(fromfd, fsp_get_io_fd(tofsp), offset, n);
1239 END_PROFILE_BYTES(syscall_recvfile);
1243 static int vfswrap_renameat(vfs_handle_struct *handle,
1244 files_struct *srcfsp,
1245 const struct smb_filename *smb_fname_src,
1246 files_struct *dstfsp,
1247 const struct smb_filename *smb_fname_dst)
1251 START_PROFILE(syscall_renameat);
1253 if (is_named_stream(smb_fname_src) || is_named_stream(smb_fname_dst)) {
1258 result = renameat(fsp_get_pathref_fd(srcfsp),
1259 smb_fname_src->base_name,
1260 fsp_get_pathref_fd(dstfsp),
1261 smb_fname_dst->base_name);
1264 END_PROFILE(syscall_renameat);
1268 static int vfswrap_stat(vfs_handle_struct *handle,
1269 struct smb_filename *smb_fname)
1273 START_PROFILE(syscall_stat);
1275 if (is_named_stream(smb_fname)) {
1280 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1281 lp_fake_directory_create_times(SNUM(handle->conn)));
1283 END_PROFILE(syscall_stat);
1287 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1291 START_PROFILE(syscall_fstat);
1292 result = sys_fstat(fsp_get_pathref_fd(fsp),
1293 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1294 END_PROFILE(syscall_fstat);
1298 static int vfswrap_lstat(vfs_handle_struct *handle,
1299 struct smb_filename *smb_fname)
1303 START_PROFILE(syscall_lstat);
1305 if (is_named_stream(smb_fname)) {
1310 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1311 lp_fake_directory_create_times(SNUM(handle->conn)));
1313 END_PROFILE(syscall_lstat);
1317 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1319 enum vfs_translate_direction direction,
1320 TALLOC_CTX *mem_ctx,
1323 return NT_STATUS_NONE_MAPPED;
1327 * Implement the default fsctl operation.
1329 static bool vfswrap_logged_ioctl_message = false;
1331 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1332 struct files_struct *fsp,
1335 uint16_t req_flags, /* Needed for UNICODE ... */
1336 const uint8_t *_in_data,
1338 uint8_t **_out_data,
1339 uint32_t max_out_len,
1342 const char *in_data = (const char *)_in_data;
1343 char **out_data = (char **)_out_data;
1347 case FSCTL_SET_SPARSE:
1349 bool set_sparse = true;
1351 if (in_len >= 1 && in_data[0] == 0) {
1355 status = file_set_sparse(handle->conn, fsp, set_sparse);
1357 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1358 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1359 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1360 nt_errstr(status)));
1365 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1367 unsigned char objid[16];
1368 char *return_data = NULL;
1370 /* This should return the object-id on this file.
1371 * I think I'll make this be the inode+dev. JRA.
1374 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1375 fsp_fnum_dbg(fsp)));
1377 *out_len = MIN(max_out_len, 64);
1379 /* Hmmm, will this cause problems if less data asked for? */
1380 return_data = talloc_array(ctx, char, 64);
1381 if (return_data == NULL) {
1382 return NT_STATUS_NO_MEMORY;
1385 /* For backwards compatibility only store the dev/inode. */
1386 push_file_id_16(return_data, &fsp->file_id);
1387 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1388 push_file_id_16(return_data+32, &fsp->file_id);
1389 memset(return_data+48, 0, 16);
1390 *out_data = return_data;
1391 return NT_STATUS_OK;
1394 case FSCTL_GET_REPARSE_POINT:
1396 status = fsctl_get_reparse_point(
1397 fsp, ctx, out_data, max_out_len, out_len);
1401 case FSCTL_SET_REPARSE_POINT:
1403 status = fsctl_set_reparse_point(fsp, ctx, _in_data, in_len);
1407 case FSCTL_DELETE_REPARSE_POINT:
1409 status = fsctl_del_reparse_point(fsp, ctx, _in_data, in_len);
1413 case FSCTL_GET_SHADOW_COPY_DATA:
1416 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1417 * and return their volume names. If max_data_count is 16, then it is just
1418 * asking for the number of volumes and length of the combined names.
1420 * pdata is the data allocated by our caller, but that uses
1421 * total_data_count (which is 0 in our case) rather than max_data_count.
1422 * Allocate the correct amount and return the pointer to let
1423 * it be deallocated when we return.
1425 struct shadow_copy_data *shadow_data = NULL;
1426 bool labels = False;
1427 uint32_t labels_data_count = 0;
1429 char *cur_pdata = NULL;
1431 if (max_out_len < 16) {
1432 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1434 return NT_STATUS_INVALID_PARAMETER;
1437 if (max_out_len > 16) {
1441 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1442 if (shadow_data == NULL) {
1443 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1444 return NT_STATUS_NO_MEMORY;
1448 * Call the VFS routine to actually do the work.
1450 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1453 /* broken module didn't set errno on error */
1454 status = NT_STATUS_UNSUCCESSFUL;
1456 status = map_nt_error_from_unix(errno);
1457 if (NT_STATUS_EQUAL(status,
1458 NT_STATUS_NOT_SUPPORTED)) {
1462 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1463 "connectpath %s, failed - %s.\n",
1464 fsp->conn->connectpath,
1465 nt_errstr(status)));
1466 TALLOC_FREE(shadow_data);
1470 labels_data_count = (shadow_data->num_volumes * 2 *
1471 sizeof(SHADOW_COPY_LABEL)) + 2;
1476 *out_len = 12 + labels_data_count;
1479 if (max_out_len < *out_len) {
1480 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1481 max_out_len, *out_len));
1482 TALLOC_FREE(shadow_data);
1483 return NT_STATUS_BUFFER_TOO_SMALL;
1486 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1487 if (cur_pdata == NULL) {
1488 TALLOC_FREE(shadow_data);
1489 return NT_STATUS_NO_MEMORY;
1492 *out_data = cur_pdata;
1494 /* num_volumes 4 bytes */
1495 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1498 /* num_labels 4 bytes */
1499 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1502 /* needed_data_count 4 bytes */
1503 SIVAL(cur_pdata, 8, labels_data_count);
1507 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1508 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1509 if (labels && shadow_data->labels) {
1510 for (i=0; i<shadow_data->num_volumes; i++) {
1512 status = srvstr_push(cur_pdata, req_flags,
1513 cur_pdata, shadow_data->labels[i],
1514 2 * sizeof(SHADOW_COPY_LABEL),
1515 STR_UNICODE|STR_TERMINATE, &len);
1516 if (!NT_STATUS_IS_OK(status)) {
1517 TALLOC_FREE(*out_data);
1518 TALLOC_FREE(shadow_data);
1521 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1522 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1526 TALLOC_FREE(shadow_data);
1528 return NT_STATUS_OK;
1531 case FSCTL_FIND_FILES_BY_SID:
1533 /* pretend this succeeded -
1535 * we have to send back a list with all files owned by this SID
1537 * but I have to check that --metze
1541 struct dom_sid_buf buf;
1545 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1546 fsp_fnum_dbg(fsp)));
1549 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1550 return NT_STATUS_INVALID_PARAMETER;
1553 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1555 /* unknown 4 bytes: this is not the length of the sid :-( */
1556 /*unknown = IVAL(pdata,0);*/
1558 ret = sid_parse(_in_data + 4, sid_len, &sid);
1560 return NT_STATUS_INVALID_PARAMETER;
1562 DEBUGADD(10, ("for SID: %s\n",
1563 dom_sid_str_buf(&sid, &buf)));
1565 if (!sid_to_uid(&sid, &uid)) {
1566 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1567 dom_sid_str_buf(&sid, &buf),
1568 (unsigned long)sid_len));
1572 /* we can take a look at the find source :-)
1574 * find ./ -uid $uid -name '*' is what we need here
1577 * and send 4bytes len and then NULL terminated unicode strings
1580 * but I don't know how to deal with the paged results
1581 * (maybe we can hang the result anywhere in the fsp struct)
1583 * but I don't know how to deal with the paged results
1584 * (maybe we can hang the result anywhere in the fsp struct)
1586 * we don't send all files at once
1587 * and at the next we should *not* start from the beginning,
1588 * so we have to cache the result
1593 /* this works for now... */
1594 return NT_STATUS_OK;
1597 case FSCTL_QUERY_ALLOCATED_RANGES:
1599 /* FIXME: This is just a dummy reply, telling that all of the
1600 * file is allocated. MKS cp needs that.
1601 * Adding the real allocated ranges via FIEMAP on Linux
1602 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1603 * this FSCTL correct for sparse files.
1605 uint64_t offset, length;
1606 char *out_data_tmp = NULL;
1609 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1611 return NT_STATUS_INVALID_PARAMETER;
1614 if (max_out_len < 16) {
1615 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1617 return NT_STATUS_INVALID_PARAMETER;
1620 offset = BVAL(in_data,0);
1621 length = BVAL(in_data,8);
1623 if (offset + length < offset) {
1624 /* No 64-bit integer wrap. */
1625 return NT_STATUS_INVALID_PARAMETER;
1628 /* Shouldn't this be SMB_VFS_STAT ... ? */
1629 status = vfs_stat_fsp(fsp);
1630 if (!NT_STATUS_IS_OK(status)) {
1635 out_data_tmp = talloc_array(ctx, char, *out_len);
1636 if (out_data_tmp == NULL) {
1637 DEBUG(10, ("unable to allocate memory for response\n"));
1638 return NT_STATUS_NO_MEMORY;
1641 if (offset > fsp->fsp_name->st.st_ex_size ||
1642 fsp->fsp_name->st.st_ex_size == 0 ||
1644 memset(out_data_tmp, 0, *out_len);
1646 uint64_t end = offset + length;
1647 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1648 SBVAL(out_data_tmp, 0, 0);
1649 SBVAL(out_data_tmp, 8, end);
1652 *out_data = out_data_tmp;
1654 return NT_STATUS_OK;
1657 case FSCTL_IS_VOLUME_DIRTY:
1659 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1660 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1662 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1663 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1665 return NT_STATUS_INVALID_PARAMETER;
1670 * Only print once ... unfortunately there could be lots of
1671 * different FSCTLs that are called.
1673 if (!vfswrap_logged_ioctl_message) {
1674 vfswrap_logged_ioctl_message = true;
1675 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1676 __func__, function));
1680 return NT_STATUS_NOT_SUPPORTED;
1683 static bool vfswrap_is_offline(struct connection_struct *conn,
1684 const struct smb_filename *fname);
1686 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1687 struct smb_filename *smb_fname,
1692 offline = vfswrap_is_offline(handle->conn, smb_fname);
1694 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1697 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1700 struct vfswrap_get_dos_attributes_state {
1701 struct vfs_aio_state aio_state;
1702 connection_struct *conn;
1703 TALLOC_CTX *mem_ctx;
1704 struct tevent_context *ev;
1705 files_struct *dir_fsp;
1706 struct smb_filename *smb_fname;
1711 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq);
1713 static struct tevent_req *vfswrap_get_dos_attributes_send(
1714 TALLOC_CTX *mem_ctx,
1715 struct tevent_context *ev,
1716 struct vfs_handle_struct *handle,
1717 files_struct *dir_fsp,
1718 struct smb_filename *smb_fname)
1720 struct tevent_req *req = NULL;
1721 struct tevent_req *subreq = NULL;
1722 struct vfswrap_get_dos_attributes_state *state = NULL;
1724 req = tevent_req_create(mem_ctx, &state,
1725 struct vfswrap_get_dos_attributes_state);
1730 *state = (struct vfswrap_get_dos_attributes_state) {
1731 .conn = dir_fsp->conn,
1735 .smb_fname = smb_fname,
1738 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1742 SAMBA_XATTR_DOS_ATTRIB,
1744 if (tevent_req_nomem(subreq, req)) {
1745 return tevent_req_post(req, ev);
1747 tevent_req_set_callback(subreq,
1748 vfswrap_get_dos_attributes_getxattr_done,
1754 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq)
1756 struct tevent_req *req =
1757 tevent_req_callback_data(subreq,
1759 struct vfswrap_get_dos_attributes_state *state =
1760 tevent_req_data(req,
1761 struct vfswrap_get_dos_attributes_state);
1763 DATA_BLOB blob = {0};
1765 char *tofree = NULL;
1766 char pathbuf[PATH_MAX+1];
1768 struct smb_filename smb_fname;
1772 xattr_size = SMB_VFS_GETXATTRAT_RECV(subreq,
1776 TALLOC_FREE(subreq);
1777 if (xattr_size == -1) {
1778 status = map_nt_error_from_unix(state->aio_state.error);
1780 if (state->as_root) {
1781 tevent_req_nterror(req, status);
1784 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1785 tevent_req_nterror(req, status);
1789 state->as_root = true;
1792 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1796 SAMBA_XATTR_DOS_ATTRIB,
1799 if (tevent_req_nomem(subreq, req)) {
1802 tevent_req_set_callback(subreq,
1803 vfswrap_get_dos_attributes_getxattr_done,
1808 blob.length = xattr_size;
1810 status = parse_dos_attribute_blob(state->smb_fname,
1813 if (!NT_STATUS_IS_OK(status)) {
1814 tevent_req_nterror(req, status);
1818 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
1819 state->smb_fname->base_name,
1824 if (pathlen == -1) {
1825 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1829 smb_fname = (struct smb_filename) {
1831 .st = state->smb_fname->st,
1832 .flags = state->smb_fname->flags,
1833 .twrp = state->smb_fname->twrp,
1836 offline = vfswrap_is_offline(state->conn, &smb_fname);
1838 state->dosmode |= FILE_ATTRIBUTE_OFFLINE;
1840 TALLOC_FREE(tofree);
1842 tevent_req_done(req);
1846 static NTSTATUS vfswrap_get_dos_attributes_recv(struct tevent_req *req,
1847 struct vfs_aio_state *aio_state,
1850 struct vfswrap_get_dos_attributes_state *state =
1851 tevent_req_data(req,
1852 struct vfswrap_get_dos_attributes_state);
1855 if (tevent_req_is_nterror(req, &status)) {
1856 tevent_req_received(req);
1860 *aio_state = state->aio_state;
1861 *dosmode = state->dosmode;
1862 tevent_req_received(req);
1863 return NT_STATUS_OK;
1866 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1867 struct files_struct *fsp,
1872 offline = vfswrap_is_offline(handle->conn, fsp->fsp_name);
1874 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1877 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1880 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1881 const struct smb_filename *smb_fname,
1884 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1887 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1888 struct files_struct *fsp,
1891 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1894 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1896 struct vfswrap_offload_read_state {
1900 static struct tevent_req *vfswrap_offload_read_send(
1901 TALLOC_CTX *mem_ctx,
1902 struct tevent_context *ev,
1903 struct vfs_handle_struct *handle,
1904 struct files_struct *fsp,
1910 struct tevent_req *req = NULL;
1911 struct vfswrap_offload_read_state *state = NULL;
1914 req = tevent_req_create(mem_ctx, &state,
1915 struct vfswrap_offload_read_state);
1920 status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1921 &vfswrap_offload_ctx);
1922 if (tevent_req_nterror(req, status)) {
1923 return tevent_req_post(req, ev);
1926 if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1927 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1928 return tevent_req_post(req, ev);
1931 status = vfs_offload_token_create_blob(state, fsp, fsctl,
1933 if (tevent_req_nterror(req, status)) {
1934 return tevent_req_post(req, ev);
1937 status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1939 if (tevent_req_nterror(req, status)) {
1940 return tevent_req_post(req, ev);
1943 tevent_req_done(req);
1944 return tevent_req_post(req, ev);
1947 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
1948 struct vfs_handle_struct *handle,
1949 TALLOC_CTX *mem_ctx,
1952 struct vfswrap_offload_read_state *state = tevent_req_data(
1953 req, struct vfswrap_offload_read_state);
1956 if (tevent_req_is_nterror(req, &status)) {
1957 tevent_req_received(req);
1961 token->length = state->token.length;
1962 token->data = talloc_move(mem_ctx, &state->token.data);
1964 tevent_req_received(req);
1965 return NT_STATUS_OK;
1968 struct vfswrap_offload_write_state {
1970 bool read_lck_locked;
1971 bool write_lck_locked;
1973 struct tevent_context *src_ev;
1974 struct files_struct *src_fsp;
1976 struct tevent_context *dst_ev;
1977 struct files_struct *dst_fsp;
1981 size_t next_io_size;
1984 static void vfswrap_offload_write_cleanup(struct tevent_req *req,
1985 enum tevent_req_state req_state)
1987 struct vfswrap_offload_write_state *state = tevent_req_data(
1988 req, struct vfswrap_offload_write_state);
1991 if (state->dst_fsp == NULL) {
1995 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
1997 state->dst_fsp = NULL;
2000 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
2002 static struct tevent_req *vfswrap_offload_write_send(
2003 struct vfs_handle_struct *handle,
2004 TALLOC_CTX *mem_ctx,
2005 struct tevent_context *ev,
2008 off_t transfer_offset,
2009 struct files_struct *dest_fsp,
2013 struct tevent_req *req;
2014 struct vfswrap_offload_write_state *state = NULL;
2015 /* off_t is signed! */
2016 off_t max_offset = INT64_MAX - to_copy;
2017 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
2018 files_struct *src_fsp = NULL;
2022 req = tevent_req_create(mem_ctx, &state,
2023 struct vfswrap_offload_write_state);
2028 *state = (struct vfswrap_offload_write_state) {
2030 .src_off = transfer_offset,
2032 .dst_fsp = dest_fsp,
2033 .dst_off = dest_off,
2035 .remaining = to_copy,
2038 tevent_req_set_cleanup_fn(req, vfswrap_offload_write_cleanup);
2041 case FSCTL_SRV_COPYCHUNK:
2042 case FSCTL_SRV_COPYCHUNK_WRITE:
2045 case FSCTL_OFFLOAD_WRITE:
2046 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
2047 return tevent_req_post(req, ev);
2049 case FSCTL_DUP_EXTENTS_TO_FILE:
2050 DBG_DEBUG("COW clones not supported by vfs_default\n");
2051 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2052 return tevent_req_post(req, ev);
2055 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2056 return tevent_req_post(req, ev);
2060 * From here on we assume a copy-chunk fsctl
2064 tevent_req_done(req);
2065 return tevent_req_post(req, ev);
2068 if (state->src_off > max_offset) {
2070 * Protect integer checks below.
2072 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2073 return tevent_req_post(req, ev);
2075 if (state->src_off < 0) {
2077 * Protect integer checks below.
2079 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2080 return tevent_req_post(req, ev);
2082 if (state->dst_off > max_offset) {
2084 * Protect integer checks below.
2086 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2087 return tevent_req_post(req, ev);
2089 if (state->dst_off < 0) {
2091 * Protect integer checks below.
2093 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2094 return tevent_req_post(req, ev);
2097 status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
2099 if (tevent_req_nterror(req, status)) {
2100 return tevent_req_post(req, ev);
2103 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
2105 status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
2106 if (!NT_STATUS_IS_OK(status)) {
2107 tevent_req_nterror(req, status);
2108 return tevent_req_post(req, ev);
2111 ok = change_to_user_and_service_by_fsp(src_fsp);
2113 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2114 return tevent_req_post(req, ev);
2117 state->src_ev = src_fsp->conn->sconn->ev_ctx;
2118 state->src_fsp = src_fsp;
2120 status = vfs_stat_fsp(src_fsp);
2121 if (tevent_req_nterror(req, status)) {
2122 return tevent_req_post(req, ev);
2125 if (src_fsp->fsp_name->st.st_ex_size < state->src_off + to_copy) {
2127 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
2128 * If the SourceOffset or SourceOffset + Length extends beyond
2129 * the end of file, the server SHOULD<240> treat this as a
2130 * STATUS_END_OF_FILE error.
2132 * <240> Section 3.3.5.15.6: Windows servers will return
2133 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
2135 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
2136 return tevent_req_post(req, ev);
2139 state->buf = talloc_array(state, uint8_t, num);
2140 if (tevent_req_nomem(state->buf, req)) {
2141 return tevent_req_post(req, ev);
2144 status = vfswrap_offload_write_loop(req);
2145 if (!NT_STATUS_IS_OK(status)) {
2146 tevent_req_nterror(req, status);
2147 return tevent_req_post(req, ev);
2153 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
2155 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
2157 struct vfswrap_offload_write_state *state = tevent_req_data(
2158 req, struct vfswrap_offload_write_state);
2159 struct tevent_req *subreq = NULL;
2160 struct lock_struct read_lck;
2164 * This is called under the context of state->src_fsp.
2167 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
2169 init_strict_lock_struct(state->src_fsp,
2170 state->src_fsp->op->global->open_persistent_id,
2172 state->next_io_size,
2176 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
2180 return NT_STATUS_FILE_LOCK_CONFLICT;
2183 subreq = SMB_VFS_PREAD_SEND(state,
2187 state->next_io_size,
2189 if (subreq == NULL) {
2190 return NT_STATUS_NO_MEMORY;
2192 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
2194 return NT_STATUS_OK;
2197 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
2199 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
2201 struct tevent_req *req = tevent_req_callback_data(
2202 subreq, struct tevent_req);
2203 struct vfswrap_offload_write_state *state = tevent_req_data(
2204 req, struct vfswrap_offload_write_state);
2205 struct vfs_aio_state aio_state;
2206 struct lock_struct write_lck;
2210 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
2211 TALLOC_FREE(subreq);
2213 DBG_ERR("read failed: %s\n", strerror(aio_state.error));
2214 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2217 if (nread != state->next_io_size) {
2218 DBG_ERR("Short read, only %zd of %zu\n",
2219 nread, state->next_io_size);
2220 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2224 state->src_off += nread;
2226 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2228 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2232 init_strict_lock_struct(state->dst_fsp,
2233 state->dst_fsp->op->global->open_persistent_id,
2235 state->next_io_size,
2239 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
2243 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
2247 subreq = SMB_VFS_PWRITE_SEND(state,
2251 state->next_io_size,
2253 if (subreq == NULL) {
2254 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2257 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
2260 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
2262 struct tevent_req *req = tevent_req_callback_data(
2263 subreq, struct tevent_req);
2264 struct vfswrap_offload_write_state *state = tevent_req_data(
2265 req, struct vfswrap_offload_write_state);
2266 struct vfs_aio_state aio_state;
2271 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
2272 TALLOC_FREE(subreq);
2273 if (nwritten == -1) {
2274 DBG_ERR("write failed: %s\n", strerror(aio_state.error));
2275 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2278 if (nwritten != state->next_io_size) {
2279 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
2280 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2284 state->dst_off += nwritten;
2286 if (state->remaining < nwritten) {
2287 /* Paranoia check */
2288 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2291 state->remaining -= nwritten;
2292 if (state->remaining == 0) {
2293 tevent_req_done(req);
2297 ok = change_to_user_and_service_by_fsp(state->src_fsp);
2299 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2303 status = vfswrap_offload_write_loop(req);
2304 if (!NT_STATUS_IS_OK(status)) {
2305 tevent_req_nterror(req, status);
2312 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
2313 struct tevent_req *req,
2316 struct vfswrap_offload_write_state *state = tevent_req_data(
2317 req, struct vfswrap_offload_write_state);
2320 if (tevent_req_is_nterror(req, &status)) {
2321 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
2323 tevent_req_received(req);
2327 *copied = state->to_copy;
2328 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
2329 tevent_req_received(req);
2331 return NT_STATUS_OK;
2334 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
2335 TALLOC_CTX *mem_ctx,
2336 struct files_struct *fsp,
2337 struct smb_filename *smb_fname,
2338 uint16_t *_compression_fmt)
2340 return NT_STATUS_INVALID_DEVICE_REQUEST;
2343 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
2344 TALLOC_CTX *mem_ctx,
2345 struct files_struct *fsp,
2346 uint16_t compression_fmt)
2348 return NT_STATUS_INVALID_DEVICE_REQUEST;
2351 /********************************************************************
2352 Given a stat buffer return the allocated size on disk, taking into
2353 account sparse files.
2354 ********************************************************************/
2355 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
2356 struct files_struct *fsp,
2357 const SMB_STRUCT_STAT *sbuf)
2361 START_PROFILE(syscall_get_alloc_size);
2363 if(S_ISDIR(sbuf->st_ex_mode)) {
2368 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2369 /* The type of st_blocksize is blkcnt_t which *MUST* be
2370 signed (according to POSIX) and can be less than 64-bits.
2371 Ensure when we're converting to 64 bits wide we don't
2373 #if defined(SIZEOF_BLKCNT_T_8)
2374 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2375 #elif defined(SIZEOF_BLKCNT_T_4)
2377 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2378 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2381 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2385 * Some file systems do not allocate a block for very
2386 * small files. But for non-empty file should report a
2390 uint64_t filesize = get_file_size_stat(sbuf);
2392 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2396 result = get_file_size_stat(sbuf);
2399 if (fsp && fsp->initial_allocation_size)
2400 result = MAX(result,fsp->initial_allocation_size);
2402 result = smb_roundup(handle->conn, result);
2405 END_PROFILE(syscall_get_alloc_size);
2409 static int vfswrap_unlinkat(vfs_handle_struct *handle,
2410 struct files_struct *dirfsp,
2411 const struct smb_filename *smb_fname,
2416 START_PROFILE(syscall_unlinkat);
2418 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2420 if (is_named_stream(smb_fname)) {
2424 result = unlinkat(fsp_get_pathref_fd(dirfsp),
2425 smb_fname->base_name,
2429 END_PROFILE(syscall_unlinkat);
2433 static int vfswrap_chmod(vfs_handle_struct *handle,
2434 const struct smb_filename *smb_fname,
2439 START_PROFILE(syscall_chmod);
2440 result = chmod(smb_fname->base_name, mode);
2441 END_PROFILE(syscall_chmod);
2445 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2449 START_PROFILE(syscall_fchmod);
2450 #if defined(HAVE_FCHMOD)
2451 result = fchmod(fsp_get_io_fd(fsp), mode);
2457 END_PROFILE(syscall_fchmod);
2461 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2466 START_PROFILE(syscall_fchown);
2467 result = fchown(fsp_get_io_fd(fsp), uid, gid);
2468 END_PROFILE(syscall_fchown);
2476 static int vfswrap_lchown(vfs_handle_struct *handle,
2477 const struct smb_filename *smb_fname,
2483 START_PROFILE(syscall_lchown);
2484 result = lchown(smb_fname->base_name, uid, gid);
2485 END_PROFILE(syscall_lchown);
2489 static int vfswrap_chdir(vfs_handle_struct *handle,
2490 const struct smb_filename *smb_fname)
2494 START_PROFILE(syscall_chdir);
2495 result = chdir(smb_fname->base_name);
2496 END_PROFILE(syscall_chdir);
2500 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2504 struct smb_filename *smb_fname = NULL;
2506 START_PROFILE(syscall_getwd);
2507 result = sys_getwd();
2508 END_PROFILE(syscall_getwd);
2510 if (result == NULL) {
2513 smb_fname = synthetic_smb_fname(ctx,
2520 * sys_getwd() *always* returns malloced memory.
2521 * We must free here to avoid leaks:
2522 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2528 /*********************************************************************
2529 nsec timestamp resolution call. Convert down to whatever the underlying
2530 system will support.
2531 **********************************************************************/
2533 static int vfswrap_ntimes(vfs_handle_struct *handle,
2534 const struct smb_filename *smb_fname,
2535 struct smb_file_time *ft)
2539 START_PROFILE(syscall_ntimes);
2541 if (is_named_stream(smb_fname)) {
2547 if (is_omit_timespec(&ft->atime)) {
2548 ft->atime= smb_fname->st.st_ex_atime;
2551 if (is_omit_timespec(&ft->mtime)) {
2552 ft->mtime = smb_fname->st.st_ex_mtime;
2555 if (!is_omit_timespec(&ft->create_time)) {
2556 set_create_timespec_ea(handle->conn,
2561 if ((timespec_compare(&ft->atime,
2562 &smb_fname->st.st_ex_atime) == 0) &&
2563 (timespec_compare(&ft->mtime,
2564 &smb_fname->st.st_ex_mtime) == 0)) {
2569 #if defined(HAVE_UTIMENSAT)
2571 struct timespec ts[2];
2574 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2576 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2578 if (!((result == -1) && (errno == ENOSYS))) {
2582 #if defined(HAVE_UTIMES)
2584 struct timeval tv[2];
2585 tv[0] = convert_timespec_to_timeval(ft->atime);
2586 tv[1] = convert_timespec_to_timeval(ft->mtime);
2587 result = utimes(smb_fname->base_name, tv);
2589 result = utimes(smb_fname->base_name, NULL);
2591 if (!((result == -1) && (errno == ENOSYS))) {
2595 #if defined(HAVE_UTIME)
2597 struct utimbuf times;
2598 times.actime = convert_timespec_to_time_t(ft->atime);
2599 times.modtime = convert_timespec_to_time_t(ft->mtime);
2600 result = utime(smb_fname->base_name, ×);
2602 result = utime(smb_fname->base_name, NULL);
2604 if (!((result == -1) && (errno == ENOSYS))) {
2612 END_PROFILE(syscall_ntimes);
2616 /*********************************************************************
2617 A version of ftruncate that will write the space on disk if strict
2619 **********************************************************************/
2621 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2623 off_t space_to_write;
2624 uint64_t space_avail;
2625 uint64_t bsize,dfree,dsize;
2628 SMB_STRUCT_STAT *pst;
2631 ok = vfs_valid_pwrite_range(len, 0);
2637 status = vfs_stat_fsp(fsp);
2638 if (!NT_STATUS_IS_OK(status)) {
2641 pst = &fsp->fsp_name->st;
2644 if (S_ISFIFO(pst->st_ex_mode))
2648 if (pst->st_ex_size == len)
2651 /* Shrink - just ftruncate. */
2652 if (pst->st_ex_size > len)
2653 return ftruncate(fsp_get_io_fd(fsp), len);
2655 space_to_write = len - pst->st_ex_size;
2657 /* for allocation try fallocate first. This can fail on some
2658 platforms e.g. when the filesystem doesn't support it and no
2659 emulation is being done by the libc (like on AIX with JFS1). In that
2660 case we do our own emulation. fallocate implementations can
2661 return ENOTSUP or EINVAL in cases like that. */
2662 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2663 if (ret == -1 && errno == ENOSPC) {
2669 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2670 "error %d. Falling back to slow manual allocation\n", errno));
2672 /* available disk space is enough or not? */
2674 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2675 /* space_avail is 1k blocks */
2676 if (space_avail == (uint64_t)-1 ||
2677 ((uint64_t)space_to_write/1024 > space_avail) ) {
2682 /* Write out the real space on disk. */
2683 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2691 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2694 SMB_STRUCT_STAT *pst;
2698 START_PROFILE(syscall_ftruncate);
2700 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->fsp_flags.is_sparse) {
2701 result = strict_allocate_ftruncate(handle, fsp, len);
2702 END_PROFILE(syscall_ftruncate);
2706 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2707 ftruncate if the system supports it. Then I discovered that
2708 you can have some filesystems that support ftruncate
2709 expansion and some that don't! On Linux fat can't do
2710 ftruncate extend but ext2 can. */
2712 result = ftruncate(fsp_get_io_fd(fsp), len);
2714 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2715 extend a file with ftruncate. Provide alternate implementation
2718 /* Do an fstat to see if the file is longer than the requested
2719 size in which case the ftruncate above should have
2720 succeeded or shorter, in which case seek to len - 1 and
2721 write 1 byte of zero */
2722 status = vfs_stat_fsp(fsp);
2723 if (!NT_STATUS_IS_OK(status)) {
2727 /* We need to update the files_struct after successful ftruncate */
2732 pst = &fsp->fsp_name->st;
2735 if (S_ISFIFO(pst->st_ex_mode)) {
2741 if (pst->st_ex_size == len) {
2746 if (pst->st_ex_size > len) {
2747 /* the ftruncate should have worked */
2751 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2759 END_PROFILE(syscall_ftruncate);
2763 static int vfswrap_fallocate(vfs_handle_struct *handle,
2771 START_PROFILE(syscall_fallocate);
2773 result = sys_posix_fallocate(fsp_get_io_fd(fsp), offset, len);
2775 * posix_fallocate returns 0 on success, errno on error
2776 * and doesn't set errno. Make it behave like fallocate()
2777 * which returns -1, and sets errno on failure.
2784 /* sys_fallocate handles filtering of unsupported mode flags */
2785 result = sys_fallocate(fsp_get_io_fd(fsp), mode, offset, len);
2787 END_PROFILE(syscall_fallocate);
2791 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2795 START_PROFILE(syscall_fcntl_lock);
2797 if (fsp->fsp_flags.use_ofd_locks) {
2798 op = map_process_lock_to_ofd_lock(op);
2801 result = fcntl_lock(fsp_get_io_fd(fsp), op, offset, count, type);
2802 END_PROFILE(syscall_fcntl_lock);
2806 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2807 uint32_t share_access, uint32_t access_mask)
2809 START_PROFILE(syscall_kernel_flock);
2810 kernel_flock(fsp_get_io_fd(fsp), share_access, access_mask);
2811 END_PROFILE(syscall_kernel_flock);
2815 static int vfswrap_fcntl(vfs_handle_struct *handle, files_struct *fsp, int cmd,
2819 va_list dup_cmd_arg;
2823 START_PROFILE(syscall_fcntl);
2825 va_copy(dup_cmd_arg, cmd_arg);
2831 #if defined(HAVE_OFD_LOCKS)
2836 #if defined(HAVE_F_OWNER_EX)
2840 #if defined(HAVE_RW_HINTS)
2843 case F_GET_FILE_RW_HINT:
2844 case F_SET_FILE_RW_HINT:
2846 argp = va_arg(dup_cmd_arg, void *);
2847 result = sys_fcntl_ptr(fsp_get_io_fd(fsp), cmd, argp);
2850 val = va_arg(dup_cmd_arg, int);
2851 result = sys_fcntl_int(fsp_get_io_fd(fsp), cmd, val);
2854 va_end(dup_cmd_arg);
2856 END_PROFILE(syscall_fcntl);
2860 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2865 START_PROFILE(syscall_fcntl_getlock);
2867 if (fsp->fsp_flags.use_ofd_locks) {
2868 op = map_process_lock_to_ofd_lock(op);
2871 result = fcntl_getlock(fsp_get_io_fd(fsp), op, poffset, pcount, ptype, ppid);
2872 END_PROFILE(syscall_fcntl_getlock);
2876 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2881 START_PROFILE(syscall_linux_setlease);
2883 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2884 result = linux_setlease(fsp_get_io_fd(fsp), leasetype);
2888 END_PROFILE(syscall_linux_setlease);
2892 static int vfswrap_symlinkat(vfs_handle_struct *handle,
2893 const struct smb_filename *link_target,
2894 struct files_struct *dirfsp,
2895 const struct smb_filename *new_smb_fname)
2899 START_PROFILE(syscall_symlinkat);
2901 result = symlinkat(link_target->base_name,
2902 fsp_get_pathref_fd(dirfsp),
2903 new_smb_fname->base_name);
2904 END_PROFILE(syscall_symlinkat);
2908 static int vfswrap_readlinkat(vfs_handle_struct *handle,
2909 const struct files_struct *dirfsp,
2910 const struct smb_filename *smb_fname,
2916 START_PROFILE(syscall_readlinkat);
2918 result = readlinkat(fsp_get_pathref_fd(dirfsp),
2919 smb_fname->base_name,
2923 END_PROFILE(syscall_readlinkat);
2927 static int vfswrap_linkat(vfs_handle_struct *handle,
2928 files_struct *srcfsp,
2929 const struct smb_filename *old_smb_fname,
2930 files_struct *dstfsp,
2931 const struct smb_filename *new_smb_fname,
2936 START_PROFILE(syscall_linkat);
2938 result = linkat(fsp_get_pathref_fd(srcfsp),
2939 old_smb_fname->base_name,
2940 fsp_get_pathref_fd(dstfsp),
2941 new_smb_fname->base_name,
2944 END_PROFILE(syscall_linkat);
2948 static int vfswrap_mknodat(vfs_handle_struct *handle,
2949 files_struct *dirfsp,
2950 const struct smb_filename *smb_fname,
2956 START_PROFILE(syscall_mknodat);
2958 result = sys_mknodat(fsp_get_pathref_fd(dirfsp),
2959 smb_fname->base_name,
2963 END_PROFILE(syscall_mknodat);
2967 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2969 const struct smb_filename *smb_fname)
2972 struct smb_filename *result_fname = NULL;
2974 START_PROFILE(syscall_realpath);
2975 result = sys_realpath(smb_fname->base_name);
2976 END_PROFILE(syscall_realpath);
2978 result_fname = synthetic_smb_fname(ctx,
2986 return result_fname;
2989 static int vfswrap_chflags(vfs_handle_struct *handle,
2990 const struct smb_filename *smb_fname,
2994 return chflags(smb_fname->base_name, flags);
3001 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
3002 const SMB_STRUCT_STAT *sbuf)
3006 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
3010 key.devid = sbuf->st_ex_dev;
3011 key.inode = sbuf->st_ex_ino;
3012 /* key.extid is unused by default. */
3017 static uint64_t vfswrap_fs_file_id(struct vfs_handle_struct *handle,
3018 const SMB_STRUCT_STAT *psbuf)
3022 if (!(psbuf->st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)) {
3023 return psbuf->st_ex_file_id;
3026 if (handle->conn->base_share_dev == psbuf->st_ex_dev) {
3027 return (uint64_t)psbuf->st_ex_ino;
3031 file_id = ((psbuf->st_ex_ino) & UINT32_MAX);
3034 file_id |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32;
3039 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
3040 struct files_struct *fsp,
3041 const struct smb_filename *smb_fname,
3042 TALLOC_CTX *mem_ctx,
3043 unsigned int *pnum_streams,
3044 struct stream_struct **pstreams)
3046 SMB_STRUCT_STAT sbuf;
3047 struct stream_struct *tmp_streams = NULL;
3050 if ((fsp != NULL) && (fsp->fsp_flags.is_directory)) {
3052 * No default streams on directories
3057 if ((fsp != NULL) && (fsp_get_pathref_fd(fsp) != -1)) {
3058 ret = SMB_VFS_FSTAT(fsp, &sbuf);
3061 struct smb_filename *smb_fname_cp = NULL;
3063 smb_fname_cp = cp_smb_filename_nostream(talloc_tos(), smb_fname);
3064 if (smb_fname_cp == NULL) {
3065 return NT_STATUS_NO_MEMORY;
3068 ret = vfs_stat(handle->conn, smb_fname_cp);
3069 sbuf = smb_fname_cp->st;
3070 TALLOC_FREE(smb_fname_cp);
3074 return map_nt_error_from_unix(errno);
3077 if (S_ISDIR(sbuf.st_ex_mode)) {
3081 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
3082 (*pnum_streams) + 1);
3083 if (tmp_streams == NULL) {
3084 return NT_STATUS_NO_MEMORY;
3086 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
3087 if (tmp_streams[*pnum_streams].name == NULL) {
3088 return NT_STATUS_NO_MEMORY;
3090 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
3091 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
3094 *pstreams = tmp_streams;
3096 return NT_STATUS_OK;
3099 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
3100 const struct smb_filename *path,
3102 TALLOC_CTX *mem_ctx,
3106 * Don't fall back to get_real_filename so callers can differentiate
3107 * between a full directory scan and an actual case-insensitive stat.
3113 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
3114 const struct smb_filename *smb_fname)
3116 return handle->conn->connectpath;
3119 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
3120 struct byte_range_lock *br_lck,
3121 struct lock_struct *plock)
3123 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3125 /* Note: blr is not used in the default implementation. */
3126 return brl_lock_windows_default(br_lck, plock);
3129 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
3130 struct byte_range_lock *br_lck,
3131 const struct lock_struct *plock)
3133 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3135 return brl_unlock_windows_default(br_lck, plock);
3138 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
3140 struct lock_struct *plock)
3142 SMB_ASSERT(plock->lock_type == READ_LOCK ||
3143 plock->lock_type == WRITE_LOCK);
3145 return strict_lock_check_default(fsp, plock);
3148 /* NT ACL operations. */
3150 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
3152 uint32_t security_info,
3153 TALLOC_CTX *mem_ctx,
3154 struct security_descriptor **ppdesc)
3158 START_PROFILE(fget_nt_acl);
3159 result = posix_fget_nt_acl(fsp, security_info,
3161 END_PROFILE(fget_nt_acl);
3165 static NTSTATUS vfswrap_get_nt_acl_at(vfs_handle_struct *handle,
3166 struct files_struct *dirfsp,
3167 const struct smb_filename *smb_fname,
3168 uint32_t security_info,
3169 TALLOC_CTX *mem_ctx,
3170 struct security_descriptor **ppdesc)
3174 START_PROFILE(get_nt_acl_at);
3176 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
3178 result = posix_get_nt_acl(handle->conn,
3183 END_PROFILE(get_nt_acl_at);
3187 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
3191 START_PROFILE(fset_nt_acl);
3192 result = set_nt_acl(fsp, security_info_sent, psd);
3193 END_PROFILE(fset_nt_acl);
3197 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
3198 struct smb_filename *file,
3199 struct security_acl *sacl,
3200 uint32_t access_requested,
3201 uint32_t access_denied)
3203 return NT_STATUS_OK; /* Nothing to do here ... */
3206 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
3207 const struct smb_filename *smb_fname,
3208 SMB_ACL_TYPE_T type,
3209 TALLOC_CTX *mem_ctx)
3211 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
3214 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
3216 TALLOC_CTX *mem_ctx)
3218 return sys_acl_get_fd(handle, fsp, mem_ctx);
3221 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
3222 const struct smb_filename *smb_fname,
3223 SMB_ACL_TYPE_T acltype,
3226 return sys_acl_set_file(handle, smb_fname, acltype, theacl);
3229 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
3231 return sys_acl_set_fd(handle, fsp, theacl);
3234 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
3235 const struct smb_filename *smb_fname)
3237 return sys_acl_delete_def_file(handle, smb_fname);
3240 /****************************************************************
3241 Extended attribute operations.
3242 *****************************************************************/
3244 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
3245 const struct smb_filename *smb_fname,
3250 return getxattr(smb_fname->base_name, name, value, size);
3253 struct vfswrap_getxattrat_state {
3254 struct tevent_context *ev;
3255 files_struct *dir_fsp;
3256 const struct smb_filename *smb_fname;
3259 * The following variables are talloced off "state" which is protected
3260 * by a destructor and thus are guaranteed to be safe to be used in the
3261 * job function in the worker thread.
3264 const char *xattr_name;
3265 uint8_t *xattr_value;
3266 struct security_unix_token *token;
3269 struct vfs_aio_state vfs_aio_state;
3270 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
3273 static int vfswrap_getxattrat_state_destructor(
3274 struct vfswrap_getxattrat_state *state)
3279 static void vfswrap_getxattrat_do_sync(struct tevent_req *req);
3280 static void vfswrap_getxattrat_do_async(void *private_data);
3281 static void vfswrap_getxattrat_done(struct tevent_req *subreq);
3283 static struct tevent_req *vfswrap_getxattrat_send(
3284 TALLOC_CTX *mem_ctx,
3285 struct tevent_context *ev,
3286 struct vfs_handle_struct *handle,
3287 files_struct *dir_fsp,
3288 const struct smb_filename *smb_fname,
3289 const char *xattr_name,
3292 struct tevent_req *req = NULL;
3293 struct tevent_req *subreq = NULL;
3294 struct vfswrap_getxattrat_state *state = NULL;
3295 size_t max_threads = 0;
3296 bool have_per_thread_cwd = false;
3297 bool have_per_thread_creds = false;
3298 bool do_async = false;
3300 req = tevent_req_create(mem_ctx, &state,
3301 struct vfswrap_getxattrat_state);
3305 *state = (struct vfswrap_getxattrat_state) {
3308 .smb_fname = smb_fname,
3311 max_threads = pthreadpool_tevent_max_threads(dir_fsp->conn->sconn->pool);
3312 if (max_threads >= 1) {
3314 * We need a non sync threadpool!
3316 have_per_thread_cwd = per_thread_cwd_supported();
3318 #ifdef HAVE_LINUX_THREAD_CREDENTIALS
3319 have_per_thread_creds = true;
3321 if (have_per_thread_cwd && have_per_thread_creds) {
3325 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat, profile_p,
3326 state->profile_bytes, 0);
3328 if (fsp_get_pathref_fd(dir_fsp) == -1) {
3329 DBG_ERR("Need a valid directory fd\n");
3330 tevent_req_error(req, EINVAL);
3331 return tevent_req_post(req, ev);
3334 if (alloc_hint > 0) {
3335 state->xattr_value = talloc_zero_array(state,
3338 if (tevent_req_nomem(state->xattr_value, req)) {
3339 return tevent_req_post(req, ev);
3344 vfswrap_getxattrat_do_sync(req);
3345 return tevent_req_post(req, ev);
3349 * Now allocate all parameters from a memory context that won't go away
3350 * no matter what. These paremeters will get used in threads and we
3351 * can't reliably cancel threads, so all buffers passed to the threads
3352 * must not be freed before all referencing threads terminate.
3355 state->name = talloc_strdup(state, smb_fname->base_name);
3356 if (tevent_req_nomem(state->name, req)) {
3357 return tevent_req_post(req, ev);
3360 state->xattr_name = talloc_strdup(state, xattr_name);
3361 if (tevent_req_nomem(state->xattr_name, req)) {
3362 return tevent_req_post(req, ev);
3366 * This is a hot codepath so at first glance one might think we should
3367 * somehow optimize away the token allocation and do a
3368 * talloc_reference() or similar black magic instead. But due to the
3369 * talloc_stackframe pool per SMB2 request this should be a simple copy
3370 * without a malloc in most cases.
3372 if (geteuid() == sec_initial_uid()) {
3373 state->token = root_unix_token(state);
3375 state->token = copy_unix_token(
3377 dir_fsp->conn->session_info->unix_token);
3379 if (tevent_req_nomem(state->token, req)) {
3380 return tevent_req_post(req, ev);
3383 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3385 subreq = pthreadpool_tevent_job_send(
3388 dir_fsp->conn->sconn->pool,
3389 vfswrap_getxattrat_do_async,
3391 if (tevent_req_nomem(subreq, req)) {
3392 return tevent_req_post(req, ev);
3394 tevent_req_set_callback(subreq, vfswrap_getxattrat_done, req);
3396 talloc_set_destructor(state, vfswrap_getxattrat_state_destructor);
3401 static void vfswrap_getxattrat_do_sync(struct tevent_req *req)
3403 struct vfswrap_getxattrat_state *state = tevent_req_data(
3404 req, struct vfswrap_getxattrat_state);
3406 char *tofree = NULL;
3407 char pathbuf[PATH_MAX+1];
3411 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
3412 state->smb_fname->base_name,
3417 if (pathlen == -1) {
3418 tevent_req_error(req, ENOMEM);
3422 state->xattr_size = getxattr(path,
3425 talloc_array_length(state->xattr_value));
3427 TALLOC_FREE(tofree);
3428 if (state->xattr_size == -1) {
3429 tevent_req_error(req, err);
3433 tevent_req_done(req);
3437 static void vfswrap_getxattrat_do_async(void *private_data)
3439 struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3440 private_data, struct vfswrap_getxattrat_state);
3441 struct timespec start_time;
3442 struct timespec end_time;
3445 PROFILE_TIMESTAMP(&start_time);
3446 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
3449 * Here we simulate a getxattrat()
3450 * call using fchdir();getxattr()
3453 per_thread_cwd_activate();
3455 /* Become the correct credential on this thread. */
3456 ret = set_thread_credentials(state->token->uid,
3458 (size_t)state->token->ngroups,
3459 state->token->groups);
3461 state->xattr_size = -1;
3462 state->vfs_aio_state.error = errno;
3466 ret = fchdir(fsp_get_pathref_fd(state->dir_fsp));
3468 state->xattr_size = -1;
3469 state->vfs_aio_state.error = errno;
3473 state->xattr_size = getxattr(state->name,
3476 talloc_array_length(state->xattr_value));
3477 if (state->xattr_size == -1) {
3478 state->vfs_aio_state.error = errno;
3482 PROFILE_TIMESTAMP(&end_time);
3483 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
3484 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3487 static void vfswrap_getxattrat_done(struct tevent_req *subreq)
3489 struct tevent_req *req = tevent_req_callback_data(
3490 subreq, struct tevent_req);
3491 struct vfswrap_getxattrat_state *state = tevent_req_data(
3492 req, struct vfswrap_getxattrat_state);
3497 * Make sure we run as the user again
3499 ok = change_to_user_and_service_by_fsp(state->dir_fsp);
3502 ret = pthreadpool_tevent_job_recv(subreq);
3503 TALLOC_FREE(subreq);
3504 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
3505 talloc_set_destructor(state, NULL);
3507 if (ret != EAGAIN) {
3508 tevent_req_error(req, ret);
3512 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
3513 * means the lower level pthreadpool failed to create a new
3514 * thread. Fallback to sync processing in that case to allow
3515 * some progress for the client.
3517 vfswrap_getxattrat_do_sync(req);
3521 if (state->xattr_size == -1) {
3522 tevent_req_error(req, state->vfs_aio_state.error);
3526 if (state->xattr_value == NULL) {
3528 * The caller only wanted the size.
3530 tevent_req_done(req);
3535 * shrink the buffer to the returned size.
3536 * (can't fail). It means NULL if size is 0.
3538 state->xattr_value = talloc_realloc(state,
3543 tevent_req_done(req);
3546 static ssize_t vfswrap_getxattrat_recv(struct tevent_req *req,
3547 struct vfs_aio_state *aio_state,
3548 TALLOC_CTX *mem_ctx,
3549 uint8_t **xattr_value)
3551 struct vfswrap_getxattrat_state *state = tevent_req_data(
3552 req, struct vfswrap_getxattrat_state);
3555 if (tevent_req_is_unix_error(req, &aio_state->error)) {
3556 tevent_req_received(req);
3560 *aio_state = state->vfs_aio_state;
3561 xattr_size = state->xattr_size;
3562 if (xattr_value != NULL) {
3563 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
3566 tevent_req_received(req);
3570 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle,
3571 struct files_struct *fsp,
3576 int fd = fsp_get_pathref_fd(fsp);
3578 if (!fsp->fsp_flags.is_pathref) {
3579 return fgetxattr(fd, name, value, size);
3582 if (fsp->fsp_flags.have_proc_fds) {
3583 const char *p = NULL;
3586 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3591 return getxattr(p, name, value, size);
3595 * This is no longer a handle based call.
3597 return getxattr(fsp->fsp_name->base_name, name, value, size);
3600 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
3601 const struct smb_filename *smb_fname,
3605 return listxattr(smb_fname->base_name, list, size);
3608 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
3610 int fd = fsp_get_pathref_fd(fsp);
3612 if (!fsp->fsp_flags.is_pathref) {
3613 return flistxattr(fd, list, size);
3616 if (fsp->fsp_flags.have_proc_fds) {
3617 const char *p = NULL;
3620 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3625 return listxattr(p, list, size);
3629 * This is no longer a handle based call.
3631 return listxattr(fsp->fsp_name->base_name, list, size);
3634 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
3635 const struct smb_filename *smb_fname,
3638 return removexattr(smb_fname->base_name, name);
3641 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
3643 int fd = fsp_get_pathref_fd(fsp);
3645 if (!fsp->fsp_flags.is_pathref) {
3646 return fremovexattr(fd, name);
3649 if (fsp->fsp_flags.have_proc_fds) {
3650 const char *p = NULL;
3653 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3658 return removexattr(p, name);
3662 * This is no longer a handle based call.
3664 return removexattr(fsp->fsp_name->base_name, name);
3667 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
3668 const struct smb_filename *smb_fname,
3674 return setxattr(smb_fname->base_name, name, value, size, flags);
3677 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
3679 int fd = fsp_get_pathref_fd(fsp);
3681 if (!fsp->fsp_flags.is_pathref) {
3682 return fsetxattr(fd, name, value, size, flags);
3685 if (fsp->fsp_flags.have_proc_fds) {
3686 const char *p = NULL;
3689 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3694 return setxattr(p, name, value, size, flags);
3698 * This is no longer a handle based call.
3700 return setxattr(fsp->fsp_name->base_name, name, value, size, flags);
3703 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
3708 static bool vfswrap_is_offline(struct connection_struct *conn,
3709 const struct smb_filename *fname)
3713 bool offline = false;
3715 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
3719 if (!lp_dmapi_support(SNUM(conn)) || !dmapi_have_session()) {
3720 #if defined(ENOTSUP)
3726 status = get_full_smb_filename(talloc_tos(), fname, &path);
3727 if (!NT_STATUS_IS_OK(status)) {
3728 errno = map_errno_from_nt_status(status);
3732 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
3739 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
3740 struct files_struct *fsp,
3741 TALLOC_CTX *mem_ctx,
3744 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
3747 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
3748 struct files_struct *fsp,
3749 const DATA_BLOB old_cookie,
3750 TALLOC_CTX *mem_ctx,
3751 DATA_BLOB *new_cookie)
3753 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
3757 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
3758 struct smb_request *smb1req,
3759 struct smbXsrv_open *op,
3760 const DATA_BLOB old_cookie,
3761 TALLOC_CTX *mem_ctx,
3762 struct files_struct **fsp,
3763 DATA_BLOB *new_cookie)
3765 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
3766 old_cookie, mem_ctx,
3770 static struct vfs_fn_pointers vfs_default_fns = {
3771 /* Disk operations */
3773 .connect_fn = vfswrap_connect,
3774 .disconnect_fn = vfswrap_disconnect,
3775 .disk_free_fn = vfswrap_disk_free,
3776 .get_quota_fn = vfswrap_get_quota,
3777 .set_quota_fn = vfswrap_set_quota,
3778 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3779 .statvfs_fn = vfswrap_statvfs,
3780 .fs_capabilities_fn = vfswrap_fs_capabilities,
3781 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3782 .create_dfs_pathat_fn = vfswrap_create_dfs_pathat,
3783 .read_dfs_pathat_fn = vfswrap_read_dfs_pathat,
3784 .snap_check_path_fn = vfswrap_snap_check_path,
3785 .snap_create_fn = vfswrap_snap_create,
3786 .snap_delete_fn = vfswrap_snap_delete,
3788 /* Directory operations */
3790 .fdopendir_fn = vfswrap_fdopendir,
3791 .readdir_fn = vfswrap_readdir,
3792 .readdir_attr_fn = vfswrap_readdir_attr,
3793 .seekdir_fn = vfswrap_seekdir,
3794 .telldir_fn = vfswrap_telldir,
3795 .rewind_dir_fn = vfswrap_rewinddir,
3796 .mkdirat_fn = vfswrap_mkdirat,
3797 .closedir_fn = vfswrap_closedir,
3799 /* File operations */
3801 .openat_fn = vfswrap_openat,
3802 .create_file_fn = vfswrap_create_file,
3803 .close_fn = vfswrap_close,
3804 .pread_fn = vfswrap_pread,
3805 .pread_send_fn = vfswrap_pread_send,
3806 .pread_recv_fn = vfswrap_pread_recv,
3807 .pwrite_fn = vfswrap_pwrite,
3808 .pwrite_send_fn = vfswrap_pwrite_send,
3809 .pwrite_recv_fn = vfswrap_pwrite_recv,
3810 .lseek_fn = vfswrap_lseek,
3811 .sendfile_fn = vfswrap_sendfile,
3812 .recvfile_fn = vfswrap_recvfile,
3813 .renameat_fn = vfswrap_renameat,
3814 .fsync_send_fn = vfswrap_fsync_send,
3815 .fsync_recv_fn = vfswrap_fsync_recv,
3816 .stat_fn = vfswrap_stat,
3817 .fstat_fn = vfswrap_fstat,
3818 .lstat_fn = vfswrap_lstat,
3819 .get_alloc_size_fn = vfswrap_get_alloc_size,
3820 .unlinkat_fn = vfswrap_unlinkat,
3821 .chmod_fn = vfswrap_chmod,
3822 .fchmod_fn = vfswrap_fchmod,
3823 .fchown_fn = vfswrap_fchown,
3824 .lchown_fn = vfswrap_lchown,
3825 .chdir_fn = vfswrap_chdir,
3826 .getwd_fn = vfswrap_getwd,
3827 .ntimes_fn = vfswrap_ntimes,
3828 .ftruncate_fn = vfswrap_ftruncate,
3829 .fallocate_fn = vfswrap_fallocate,
3830 .lock_fn = vfswrap_lock,
3831 .kernel_flock_fn = vfswrap_kernel_flock,
3832 .fcntl_fn = vfswrap_fcntl,
3833 .linux_setlease_fn = vfswrap_linux_setlease,
3834 .getlock_fn = vfswrap_getlock,
3835 .symlinkat_fn = vfswrap_symlinkat,
3836 .readlinkat_fn = vfswrap_readlinkat,
3837 .linkat_fn = vfswrap_linkat,
3838 .mknodat_fn = vfswrap_mknodat,
3839 .realpath_fn = vfswrap_realpath,
3840 .chflags_fn = vfswrap_chflags,
3841 .file_id_create_fn = vfswrap_file_id_create,
3842 .fs_file_id_fn = vfswrap_fs_file_id,
3843 .streaminfo_fn = vfswrap_streaminfo,
3844 .get_real_filename_fn = vfswrap_get_real_filename,
3845 .connectpath_fn = vfswrap_connectpath,
3846 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
3847 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3848 .strict_lock_check_fn = vfswrap_strict_lock_check,
3849 .translate_name_fn = vfswrap_translate_name,
3850 .fsctl_fn = vfswrap_fsctl,
3851 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
3852 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
3853 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
3854 .get_dos_attributes_send_fn = vfswrap_get_dos_attributes_send,
3855 .get_dos_attributes_recv_fn = vfswrap_get_dos_attributes_recv,
3856 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
3857 .offload_read_send_fn = vfswrap_offload_read_send,
3858 .offload_read_recv_fn = vfswrap_offload_read_recv,
3859 .offload_write_send_fn = vfswrap_offload_write_send,
3860 .offload_write_recv_fn = vfswrap_offload_write_recv,
3861 .get_compression_fn = vfswrap_get_compression,
3862 .set_compression_fn = vfswrap_set_compression,
3864 /* NT ACL operations. */
3866 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
3867 .get_nt_acl_at_fn = vfswrap_get_nt_acl_at,
3868 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
3869 .audit_file_fn = vfswrap_audit_file,
3871 /* POSIX ACL operations. */
3873 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
3874 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3875 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
3876 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3877 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
3878 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3879 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
3881 /* EA operations. */
3882 .getxattr_fn = vfswrap_getxattr,
3883 .getxattrat_send_fn = vfswrap_getxattrat_send,
3884 .getxattrat_recv_fn = vfswrap_getxattrat_recv,
3885 .fgetxattr_fn = vfswrap_fgetxattr,
3886 .listxattr_fn = vfswrap_listxattr,
3887 .flistxattr_fn = vfswrap_flistxattr,
3888 .removexattr_fn = vfswrap_removexattr,
3889 .fremovexattr_fn = vfswrap_fremovexattr,
3890 .setxattr_fn = vfswrap_setxattr,
3891 .fsetxattr_fn = vfswrap_fsetxattr,
3893 /* aio operations */
3894 .aio_force_fn = vfswrap_aio_force,
3896 /* durable handle operations */
3897 .durable_cookie_fn = vfswrap_durable_cookie,
3898 .durable_disconnect_fn = vfswrap_durable_disconnect,
3899 .durable_reconnect_fn = vfswrap_durable_reconnect,
3903 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3906 * Here we need to implement every call!
3908 * As this is the end of the vfs module chain.
3910 smb_vfs_assert_all_fns(&vfs_default_fns, DEFAULT_VFS_MODULE_NAME);
3911 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3912 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);