2 Unix SMB/CIFS implementation.
3 Wrap disk only vfs functions to sidestep dodgy compilers.
4 Copyright (C) Tim Potter 1998
5 Copyright (C) Jeremy Allison 2007
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "system/time.h"
23 #include "system/filesys.h"
24 #include "smbd/smbd.h"
25 #include "smbd/globals.h"
27 #include "smbprofile.h"
28 #include "../libcli/security/security.h"
29 #include "passdb/lookup_sid.h"
30 #include "source3/include/msdfs.h"
31 #include "librpc/gen_ndr/ndr_dfsblobs.h"
32 #include "lib/util/tevent_unix.h"
33 #include "lib/util/tevent_ntstatus.h"
34 #include "lib/util/sys_rw.h"
35 #include "lib/pthreadpool/pthreadpool_tevent.h"
36 #include "librpc/gen_ndr/ndr_ioctl.h"
37 #include "offload_token.h"
38 #include "util_reparse.h"
39 #include "lib/util/string_wrappers.h"
42 #define DBGC_CLASS DBGC_VFS
44 /* Check for NULL pointer parameters in vfswrap_* functions */
46 /* We don't want to have NULL function pointers lying around. Someone
47 is sure to try and execute them. These stubs are used to prevent
50 static int vfswrap_connect(vfs_handle_struct *handle, const char *service, const char *user)
52 handle->conn->have_proc_fds = sys_have_proc_fds();
53 return 0; /* Return >= 0 for success */
56 static void vfswrap_disconnect(vfs_handle_struct *handle)
62 static uint64_t vfswrap_disk_free(vfs_handle_struct *handle,
63 const struct smb_filename *smb_fname,
68 if (sys_fsusage(smb_fname->base_name, dfree, dsize) != 0) {
76 static int vfswrap_get_quota(struct vfs_handle_struct *handle,
77 const struct smb_filename *smb_fname,
78 enum SMB_QUOTA_TYPE qtype,
82 #ifdef HAVE_SYS_QUOTAS
85 START_PROFILE(syscall_get_quota);
86 result = sys_get_quota(smb_fname->base_name, qtype, id, qt);
87 END_PROFILE(syscall_get_quota);
95 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
97 #ifdef HAVE_SYS_QUOTAS
100 START_PROFILE(syscall_set_quota);
101 result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
102 END_PROFILE(syscall_set_quota);
110 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
111 struct files_struct *fsp,
112 struct shadow_copy_data *shadow_copy_data,
116 return -1; /* Not implemented. */
119 static int vfswrap_statvfs(struct vfs_handle_struct *handle,
120 const struct smb_filename *smb_fname,
121 vfs_statvfs_struct *statbuf)
123 return sys_statvfs(smb_fname->base_name, statbuf);
126 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
127 enum timestamp_set_resolution *p_ts_res)
129 const struct loadparm_substitution *lp_sub =
130 loadparm_s3_global_substitution();
131 connection_struct *conn = handle->conn;
132 uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
133 struct smb_filename *smb_fname_cpath = NULL;
134 struct vfs_statvfs_struct statbuf;
137 smb_fname_cpath = synthetic_smb_fname(talloc_tos(),
143 if (smb_fname_cpath == NULL) {
147 ZERO_STRUCT(statbuf);
148 ret = SMB_VFS_STATVFS(conn, smb_fname_cpath, &statbuf);
150 caps = statbuf.FsCapabilities;
153 *p_ts_res = TIMESTAMP_SET_SECONDS;
155 /* Work out what timestamp resolution we can
156 * use when setting a timestamp. */
158 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
160 TALLOC_FREE(smb_fname_cpath);
164 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
165 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
166 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
167 /* If any of the normal UNIX directory timestamps
168 * have a non-zero tv_nsec component assume
169 * we might be able to set sub-second timestamps.
170 * See what filetime set primitives we have.
172 #if defined(HAVE_UTIMENSAT)
173 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
174 #elif defined(HAVE_UTIMES)
175 /* utimes allows msec timestamps to be set. */
176 *p_ts_res = TIMESTAMP_SET_MSEC;
177 #elif defined(HAVE_UTIME)
178 /* utime only allows sec timestamps to be set. */
179 *p_ts_res = TIMESTAMP_SET_SECONDS;
182 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
184 "available on share %s, directory %s\n",
185 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
186 lp_servicename(talloc_tos(), lp_sub, conn->params->service),
187 conn->connectpath ));
189 TALLOC_FREE(smb_fname_cpath);
193 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
194 struct dfs_GetDFSReferral *r)
196 struct junction_map *junction = NULL;
198 bool self_referral = false;
199 char *pathnamep = NULL;
200 char *local_dfs_path = NULL;
203 uint16_t max_referral_level = r->in.req.max_referral_level;
206 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
209 /* get the junction entry */
210 if (r->in.req.servername == NULL) {
211 return NT_STATUS_NOT_FOUND;
215 * Trim pathname sent by client so it begins with only one backslash.
216 * Two backslashes confuse some dfs clients
219 local_dfs_path = talloc_strdup(r, r->in.req.servername);
220 if (local_dfs_path == NULL) {
221 return NT_STATUS_NO_MEMORY;
223 pathnamep = local_dfs_path;
224 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
225 IS_DIRECTORY_SEP(pathnamep[1])) {
229 junction = talloc_zero(r, struct junction_map);
230 if (junction == NULL) {
231 return NT_STATUS_NO_MEMORY;
234 /* The following call can change cwd. */
235 status = get_referred_path(r,
236 handle->conn->session_info,
238 handle->conn->sconn->remote_address,
239 handle->conn->sconn->local_address,
240 !handle->conn->sconn->using_smb2,
241 junction, &consumedcnt, &self_referral);
242 if (!NT_STATUS_IS_OK(status)) {
243 struct smb_filename connectpath_fname = {
244 .base_name = handle->conn->connectpath
246 vfs_ChDir(handle->conn, &connectpath_fname);
250 struct smb_filename connectpath_fname = {
251 .base_name = handle->conn->connectpath
253 vfs_ChDir(handle->conn, &connectpath_fname);
256 if (!self_referral) {
257 pathnamep[consumedcnt] = '\0';
260 dbgtext("Path %s to alternate path(s):",
262 for (i=0; i < junction->referral_count; i++) {
264 junction->referral_list[i].alternate_path);
270 if (r->in.req.max_referral_level <= 2) {
271 max_referral_level = 2;
273 if (r->in.req.max_referral_level >= 3) {
274 max_referral_level = 3;
277 r->out.resp = talloc_zero(r, struct dfs_referral_resp);
278 if (r->out.resp == NULL) {
279 return NT_STATUS_NO_MEMORY;
282 r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
283 r->out.resp->nb_referrals = junction->referral_count;
285 r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
287 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
290 r->out.resp->referral_entries = talloc_zero_array(r,
291 struct dfs_referral_type,
292 r->out.resp->nb_referrals);
293 if (r->out.resp->referral_entries == NULL) {
294 return NT_STATUS_NO_MEMORY;
297 switch (max_referral_level) {
299 for(i=0; i < junction->referral_count; i++) {
300 struct referral *ref = &junction->referral_list[i];
301 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
302 struct dfs_referral_type *t =
303 &r->out.resp->referral_entries[i];
304 struct dfs_referral_v2 *v2 = &t->referral.v2;
307 v2->size = VERSION2_REFERRAL_SIZE;
309 v2->server_type = DFS_SERVER_ROOT;
311 v2->server_type = DFS_SERVER_NON_ROOT;
314 v2->proximity = ref->proximity;
316 v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
317 if (v2->DFS_path == NULL) {
318 return NT_STATUS_NO_MEMORY;
320 v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
321 if (v2->DFS_alt_path == NULL) {
322 return NT_STATUS_NO_MEMORY;
324 v2->netw_address = talloc_strdup(mem_ctx,
325 ref->alternate_path);
326 if (v2->netw_address == NULL) {
327 return NT_STATUS_NO_MEMORY;
333 for(i=0; i < junction->referral_count; i++) {
334 struct referral *ref = &junction->referral_list[i];
335 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
336 struct dfs_referral_type *t =
337 &r->out.resp->referral_entries[i];
338 struct dfs_referral_v3 *v3 = &t->referral.v3;
339 struct dfs_normal_referral *r1 = &v3->referrals.r1;
342 v3->size = VERSION3_REFERRAL_SIZE;
344 v3->server_type = DFS_SERVER_ROOT;
346 v3->server_type = DFS_SERVER_NON_ROOT;
350 r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
351 if (r1->DFS_path == NULL) {
352 return NT_STATUS_NO_MEMORY;
354 r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
355 if (r1->DFS_alt_path == NULL) {
356 return NT_STATUS_NO_MEMORY;
358 r1->netw_address = talloc_strdup(mem_ctx,
359 ref->alternate_path);
360 if (r1->netw_address == NULL) {
361 return NT_STATUS_NO_MEMORY;
366 DEBUG(0,("Invalid dfs referral version: %d\n",
367 max_referral_level));
368 return NT_STATUS_INVALID_LEVEL;
372 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
378 static NTSTATUS vfswrap_create_dfs_pathat(struct vfs_handle_struct *handle,
379 struct files_struct *dirfsp,
380 const struct smb_filename *smb_fname,
381 const struct referral *reflist,
382 size_t referral_count)
384 TALLOC_CTX *frame = talloc_stackframe();
385 NTSTATUS status = NT_STATUS_NO_MEMORY;
387 char *msdfs_link = NULL;
389 /* Form the msdfs_link contents */
390 msdfs_link = msdfs_link_string(frame,
393 if (msdfs_link == NULL) {
397 ret = symlinkat(msdfs_link,
398 fsp_get_pathref_fd(dirfsp),
399 smb_fname->base_name);
401 status = NT_STATUS_OK;
403 status = map_nt_error_from_unix(errno);
413 * Read and return the contents of a DFS redirect given a
414 * pathname. A caller can pass in NULL for ppreflist and
415 * preferral_count but still determine if this was a
416 * DFS redirect point by getting NT_STATUS_OK back
417 * without incurring the overhead of reading and parsing
418 * the referral contents.
421 static NTSTATUS vfswrap_read_dfs_pathat(struct vfs_handle_struct *handle,
423 struct files_struct *dirfsp,
424 struct smb_filename *smb_fname,
425 struct referral **ppreflist,
426 size_t *preferral_count)
428 NTSTATUS status = NT_STATUS_NO_MEMORY;
430 char *link_target = NULL;
433 #if defined(HAVE_BROKEN_READLINK)
434 char link_target_buf[PATH_MAX];
436 char link_target_buf[7];
440 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
442 if (is_named_stream(smb_fname)) {
443 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
447 if (ppreflist == NULL && preferral_count == NULL) {
449 * We're only checking if this is a DFS
450 * redirect. We don't need to return data.
452 bufsize = sizeof(link_target_buf);
453 link_target = link_target_buf;
456 link_target = talloc_array(mem_ctx, char, bufsize);
462 referral_len = readlinkat(fsp_get_io_fd(dirfsp),
463 smb_fname->base_name,
466 if (referral_len == -1) {
467 if (errno == EINVAL) {
469 * If the path isn't a link, readlinkat
470 * returns EINVAL. Allow the caller to
473 DBG_INFO("%s is not a link.\n", smb_fname->base_name);
474 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
476 status = map_nt_error_from_unix(errno);
477 if (errno == ENOENT) {
478 DBG_NOTICE("Error reading "
479 "msdfs link %s: %s\n",
480 smb_fname->base_name,
483 DBG_ERR("Error reading "
484 "msdfs link %s: %s\n",
485 smb_fname->base_name,
491 link_target[referral_len] = '\0';
493 DBG_INFO("%s -> %s\n",
494 smb_fname->base_name,
497 if (!strnequal(link_target, "msdfs:", 6)) {
498 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
502 ret = sys_lstat(smb_fname->base_name,
504 lp_fake_directory_create_times(SNUM(handle->conn)));
506 status = map_nt_error_from_unix(errno);
510 if (ppreflist == NULL && preferral_count == NULL) {
511 /* Early return for checking if this is a DFS link. */
515 ok = parse_msdfs_symlink(mem_ctx,
516 lp_msdfs_shuffle_referrals(SNUM(handle->conn)),
522 status = NT_STATUS_OK;
524 status = NT_STATUS_NO_MEMORY;
529 if (link_target != link_target_buf) {
530 TALLOC_FREE(link_target);
535 static NTSTATUS vfswrap_snap_check_path(struct vfs_handle_struct *handle,
537 const char *service_path,
540 return NT_STATUS_NOT_SUPPORTED;
543 static NTSTATUS vfswrap_snap_create(struct vfs_handle_struct *handle,
545 const char *base_volume,
551 return NT_STATUS_NOT_SUPPORTED;
554 static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle,
559 return NT_STATUS_NOT_SUPPORTED;
562 /* Directory operations */
564 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
571 START_PROFILE(syscall_fdopendir);
572 result = sys_fdopendir(fsp_get_io_fd(fsp));
573 END_PROFILE(syscall_fdopendir);
578 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
579 struct files_struct *dirfsp,
581 SMB_STRUCT_STAT *sbuf)
583 struct dirent *result;
584 bool fake_ctime = lp_fake_directory_create_times(SNUM(handle->conn));
585 int flags = AT_SYMLINK_NOFOLLOW;
589 START_PROFILE(syscall_readdir);
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 ret = sys_fstatat(dirfd(dirp),
617 * As this is an optimization, ignore it if we stat'ed a
618 * symlink for non-POSIX context. Make the caller do it again
619 * as we don't know if they wanted the link info, or its
622 if (S_ISLNK(st.st_ex_mode) &&
623 !(dirfsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH))
632 static NTSTATUS vfswrap_freaddir_attr(struct vfs_handle_struct *handle,
633 struct files_struct *fsp,
635 struct readdir_attr_data **attr_data)
637 return NT_STATUS_NOT_SUPPORTED;
640 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
642 START_PROFILE(syscall_seekdir);
643 seekdir(dirp, offset);
644 END_PROFILE(syscall_seekdir);
647 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
650 START_PROFILE(syscall_telldir);
651 result = telldir(dirp);
652 END_PROFILE(syscall_telldir);
656 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
658 START_PROFILE(syscall_rewinddir);
660 END_PROFILE(syscall_rewinddir);
663 static int vfswrap_mkdirat(vfs_handle_struct *handle,
664 struct files_struct *dirfsp,
665 const struct smb_filename *smb_fname,
670 START_PROFILE(syscall_mkdirat);
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 * Return allocated parent directory and basename of path
1329 * Note: if requesting name, it is returned as talloc child of the
1330 * parent. Freeing the parent is thus sufficient to free both.
1332 static NTSTATUS vfswrap_parent_pathname(struct vfs_handle_struct *handle,
1333 TALLOC_CTX *mem_ctx,
1334 const struct smb_filename *smb_fname_in,
1335 struct smb_filename **parent_dir_out,
1336 struct smb_filename **atname_out)
1338 TALLOC_CTX *frame = talloc_stackframe();
1339 struct smb_filename *parent = NULL;
1340 struct smb_filename *name = NULL;
1343 parent = cp_smb_filename(frame, smb_fname_in);
1344 if (parent == NULL) {
1346 return NT_STATUS_NO_MEMORY;
1348 TALLOC_FREE(parent->stream_name);
1349 SET_STAT_INVALID(parent->st);
1351 p = strrchr_m(parent->base_name, '/'); /* Find final '/', if any */
1353 TALLOC_FREE(parent->base_name);
1354 parent->base_name = talloc_strdup(parent, ".");
1355 if (parent->base_name == NULL) {
1357 return NT_STATUS_NO_MEMORY;
1359 p = smb_fname_in->base_name;
1365 if (atname_out == NULL) {
1366 *parent_dir_out = talloc_move(mem_ctx, &parent);
1368 return NT_STATUS_OK;
1371 name = cp_smb_filename(frame, smb_fname_in);
1374 return NT_STATUS_NO_MEMORY;
1376 TALLOC_FREE(name->base_name);
1378 name->base_name = talloc_strdup(name, p);
1379 if (name->base_name == NULL) {
1381 return NT_STATUS_NO_MEMORY;
1384 *parent_dir_out = talloc_move(mem_ctx, &parent);
1385 *atname_out = talloc_move(*parent_dir_out, &name);
1387 return NT_STATUS_OK;
1391 * Implement the default fsctl operation.
1393 static bool vfswrap_logged_ioctl_message = false;
1395 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1396 struct files_struct *fsp,
1399 uint16_t req_flags, /* Needed for UNICODE ... */
1400 const uint8_t *_in_data,
1402 uint8_t **_out_data,
1403 uint32_t max_out_len,
1406 const char *in_data = (const char *)_in_data;
1407 char **out_data = (char **)_out_data;
1411 case FSCTL_SET_SPARSE:
1413 bool set_sparse = true;
1415 if (in_len >= 1 && in_data[0] == 0) {
1419 status = file_set_sparse(handle->conn, fsp, set_sparse);
1421 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1422 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1423 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1424 nt_errstr(status)));
1429 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1431 unsigned char objid[16];
1432 char *return_data = NULL;
1434 /* This should return the object-id on this file.
1435 * I think I'll make this be the inode+dev. JRA.
1438 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1439 fsp_fnum_dbg(fsp)));
1441 *out_len = MIN(max_out_len, 64);
1443 /* Hmmm, will this cause problems if less data asked for? */
1444 return_data = talloc_array(ctx, char, 64);
1445 if (return_data == NULL) {
1446 return NT_STATUS_NO_MEMORY;
1449 /* For backwards compatibility only store the dev/inode. */
1450 push_file_id_16(return_data, &fsp->file_id);
1451 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1452 push_file_id_16(return_data+32, &fsp->file_id);
1453 memset(return_data+48, 0, 16);
1454 *out_data = return_data;
1455 return NT_STATUS_OK;
1458 case FSCTL_GET_REPARSE_POINT:
1460 status = fsctl_get_reparse_point(
1461 fsp, ctx, out_data, max_out_len, out_len);
1465 case FSCTL_SET_REPARSE_POINT:
1467 status = fsctl_set_reparse_point(fsp, ctx, _in_data, in_len);
1471 case FSCTL_DELETE_REPARSE_POINT:
1473 status = fsctl_del_reparse_point(fsp, ctx, _in_data, in_len);
1477 case FSCTL_GET_SHADOW_COPY_DATA:
1480 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1481 * and return their volume names. If max_data_count is 16, then it is just
1482 * asking for the number of volumes and length of the combined names.
1484 * pdata is the data allocated by our caller, but that uses
1485 * total_data_count (which is 0 in our case) rather than max_data_count.
1486 * Allocate the correct amount and return the pointer to let
1487 * it be deallocated when we return.
1489 struct shadow_copy_data *shadow_data = NULL;
1490 bool labels = False;
1491 uint32_t labels_data_count = 0;
1493 char *cur_pdata = NULL;
1495 if (max_out_len < 16) {
1496 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1498 return NT_STATUS_INVALID_PARAMETER;
1501 if (max_out_len > 16) {
1505 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1506 if (shadow_data == NULL) {
1507 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1508 return NT_STATUS_NO_MEMORY;
1512 * Call the VFS routine to actually do the work.
1514 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1517 /* broken module didn't set errno on error */
1518 status = NT_STATUS_UNSUCCESSFUL;
1520 status = map_nt_error_from_unix(errno);
1521 if (NT_STATUS_EQUAL(status,
1522 NT_STATUS_NOT_SUPPORTED)) {
1526 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1527 "connectpath %s, failed - %s.\n",
1528 fsp->conn->connectpath,
1529 nt_errstr(status)));
1530 TALLOC_FREE(shadow_data);
1534 labels_data_count = (shadow_data->num_volumes * 2 *
1535 sizeof(SHADOW_COPY_LABEL)) + 2;
1540 *out_len = 12 + labels_data_count;
1543 if (max_out_len < *out_len) {
1544 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1545 max_out_len, *out_len));
1546 TALLOC_FREE(shadow_data);
1547 return NT_STATUS_BUFFER_TOO_SMALL;
1550 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1551 if (cur_pdata == NULL) {
1552 TALLOC_FREE(shadow_data);
1553 return NT_STATUS_NO_MEMORY;
1556 *out_data = cur_pdata;
1558 /* num_volumes 4 bytes */
1559 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1562 /* num_labels 4 bytes */
1563 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1566 /* needed_data_count 4 bytes */
1567 SIVAL(cur_pdata, 8, labels_data_count);
1571 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1572 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1573 if (labels && shadow_data->labels) {
1574 for (i=0; i<shadow_data->num_volumes; i++) {
1576 status = srvstr_push(cur_pdata, req_flags,
1577 cur_pdata, shadow_data->labels[i],
1578 2 * sizeof(SHADOW_COPY_LABEL),
1579 STR_UNICODE|STR_TERMINATE, &len);
1580 if (!NT_STATUS_IS_OK(status)) {
1581 TALLOC_FREE(*out_data);
1582 TALLOC_FREE(shadow_data);
1585 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1586 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1590 TALLOC_FREE(shadow_data);
1592 return NT_STATUS_OK;
1595 case FSCTL_FIND_FILES_BY_SID:
1597 /* pretend this succeeded -
1599 * we have to send back a list with all files owned by this SID
1601 * but I have to check that --metze
1605 struct dom_sid_buf buf;
1609 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1610 fsp_fnum_dbg(fsp)));
1613 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1614 return NT_STATUS_INVALID_PARAMETER;
1617 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1619 /* unknown 4 bytes: this is not the length of the sid :-( */
1620 /*unknown = IVAL(pdata,0);*/
1622 ret = sid_parse(_in_data + 4, sid_len, &sid);
1624 return NT_STATUS_INVALID_PARAMETER;
1626 DEBUGADD(10, ("for SID: %s\n",
1627 dom_sid_str_buf(&sid, &buf)));
1629 if (!sid_to_uid(&sid, &uid)) {
1630 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1631 dom_sid_str_buf(&sid, &buf),
1632 (unsigned long)sid_len));
1636 /* we can take a look at the find source :-)
1638 * find ./ -uid $uid -name '*' is what we need here
1641 * and send 4bytes len and then NULL terminated unicode strings
1644 * but I don't know how to deal with the paged results
1645 * (maybe we can hang the result anywhere in the fsp struct)
1647 * but I don't know how to deal with the paged results
1648 * (maybe we can hang the result anywhere in the fsp struct)
1650 * we don't send all files at once
1651 * and at the next we should *not* start from the beginning,
1652 * so we have to cache the result
1657 /* this works for now... */
1658 return NT_STATUS_OK;
1661 case FSCTL_QUERY_ALLOCATED_RANGES:
1663 /* FIXME: This is just a dummy reply, telling that all of the
1664 * file is allocated. MKS cp needs that.
1665 * Adding the real allocated ranges via FIEMAP on Linux
1666 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1667 * this FSCTL correct for sparse files.
1669 uint64_t offset, length;
1670 char *out_data_tmp = NULL;
1673 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1675 return NT_STATUS_INVALID_PARAMETER;
1678 if (max_out_len < 16) {
1679 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1681 return NT_STATUS_INVALID_PARAMETER;
1684 offset = BVAL(in_data,0);
1685 length = BVAL(in_data,8);
1687 if (offset + length < offset) {
1688 /* No 64-bit integer wrap. */
1689 return NT_STATUS_INVALID_PARAMETER;
1692 /* Shouldn't this be SMB_VFS_STAT ... ? */
1693 status = vfs_stat_fsp(fsp);
1694 if (!NT_STATUS_IS_OK(status)) {
1699 out_data_tmp = talloc_array(ctx, char, *out_len);
1700 if (out_data_tmp == NULL) {
1701 DEBUG(10, ("unable to allocate memory for response\n"));
1702 return NT_STATUS_NO_MEMORY;
1705 if (offset > fsp->fsp_name->st.st_ex_size ||
1706 fsp->fsp_name->st.st_ex_size == 0 ||
1708 memset(out_data_tmp, 0, *out_len);
1710 uint64_t end = offset + length;
1711 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1712 SBVAL(out_data_tmp, 0, 0);
1713 SBVAL(out_data_tmp, 8, end);
1716 *out_data = out_data_tmp;
1718 return NT_STATUS_OK;
1721 case FSCTL_IS_VOLUME_DIRTY:
1723 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1724 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1726 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1727 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1729 return NT_STATUS_INVALID_PARAMETER;
1734 * Only print once ... unfortunately there could be lots of
1735 * different FSCTLs that are called.
1737 if (!vfswrap_logged_ioctl_message) {
1738 vfswrap_logged_ioctl_message = true;
1739 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1740 __func__, function));
1744 return NT_STATUS_NOT_SUPPORTED;
1747 static bool vfswrap_is_offline(struct connection_struct *conn,
1748 const struct smb_filename *fname);
1750 struct vfswrap_get_dos_attributes_state {
1751 struct vfs_aio_state aio_state;
1752 connection_struct *conn;
1753 TALLOC_CTX *mem_ctx;
1754 struct tevent_context *ev;
1755 files_struct *dir_fsp;
1756 struct smb_filename *smb_fname;
1761 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq);
1763 static struct tevent_req *vfswrap_get_dos_attributes_send(
1764 TALLOC_CTX *mem_ctx,
1765 struct tevent_context *ev,
1766 struct vfs_handle_struct *handle,
1767 files_struct *dir_fsp,
1768 struct smb_filename *smb_fname)
1770 struct tevent_req *req = NULL;
1771 struct tevent_req *subreq = NULL;
1772 struct vfswrap_get_dos_attributes_state *state = NULL;
1774 req = tevent_req_create(mem_ctx, &state,
1775 struct vfswrap_get_dos_attributes_state);
1780 *state = (struct vfswrap_get_dos_attributes_state) {
1781 .conn = dir_fsp->conn,
1785 .smb_fname = smb_fname,
1788 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1792 SAMBA_XATTR_DOS_ATTRIB,
1794 if (tevent_req_nomem(subreq, req)) {
1795 return tevent_req_post(req, ev);
1797 tevent_req_set_callback(subreq,
1798 vfswrap_get_dos_attributes_getxattr_done,
1804 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq)
1806 struct tevent_req *req =
1807 tevent_req_callback_data(subreq,
1809 struct vfswrap_get_dos_attributes_state *state =
1810 tevent_req_data(req,
1811 struct vfswrap_get_dos_attributes_state);
1813 DATA_BLOB blob = {0};
1815 char *tofree = NULL;
1816 char pathbuf[PATH_MAX+1];
1818 struct smb_filename smb_fname;
1822 xattr_size = SMB_VFS_GETXATTRAT_RECV(subreq,
1826 TALLOC_FREE(subreq);
1827 if (xattr_size == -1) {
1828 status = map_nt_error_from_unix(state->aio_state.error);
1830 if (state->as_root) {
1831 tevent_req_nterror(req, status);
1834 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1835 tevent_req_nterror(req, status);
1839 state->as_root = true;
1842 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1846 SAMBA_XATTR_DOS_ATTRIB,
1849 if (tevent_req_nomem(subreq, req)) {
1852 tevent_req_set_callback(subreq,
1853 vfswrap_get_dos_attributes_getxattr_done,
1858 blob.length = xattr_size;
1860 status = parse_dos_attribute_blob(state->smb_fname,
1863 if (!NT_STATUS_IS_OK(status)) {
1864 tevent_req_nterror(req, status);
1868 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
1869 state->smb_fname->base_name,
1874 if (pathlen == -1) {
1875 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1879 smb_fname = (struct smb_filename) {
1881 .st = state->smb_fname->st,
1882 .flags = state->smb_fname->flags,
1883 .twrp = state->smb_fname->twrp,
1886 offline = vfswrap_is_offline(state->conn, &smb_fname);
1888 state->dosmode |= FILE_ATTRIBUTE_OFFLINE;
1890 TALLOC_FREE(tofree);
1892 tevent_req_done(req);
1896 static NTSTATUS vfswrap_get_dos_attributes_recv(struct tevent_req *req,
1897 struct vfs_aio_state *aio_state,
1900 struct vfswrap_get_dos_attributes_state *state =
1901 tevent_req_data(req,
1902 struct vfswrap_get_dos_attributes_state);
1905 if (tevent_req_is_nterror(req, &status)) {
1906 tevent_req_received(req);
1910 *aio_state = state->aio_state;
1911 *dosmode = state->dosmode;
1912 tevent_req_received(req);
1913 return NT_STATUS_OK;
1916 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1917 struct files_struct *fsp,
1922 offline = vfswrap_is_offline(handle->conn, fsp->fsp_name);
1924 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1927 return fget_ea_dos_attribute(fsp, dosmode);
1930 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1931 struct files_struct *fsp,
1934 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1937 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1939 struct vfswrap_offload_read_state {
1943 static struct tevent_req *vfswrap_offload_read_send(
1944 TALLOC_CTX *mem_ctx,
1945 struct tevent_context *ev,
1946 struct vfs_handle_struct *handle,
1947 struct files_struct *fsp,
1953 struct tevent_req *req = NULL;
1954 struct vfswrap_offload_read_state *state = NULL;
1957 req = tevent_req_create(mem_ctx, &state,
1958 struct vfswrap_offload_read_state);
1963 status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1964 &vfswrap_offload_ctx);
1965 if (tevent_req_nterror(req, status)) {
1966 return tevent_req_post(req, ev);
1969 if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1970 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1971 return tevent_req_post(req, ev);
1974 status = vfs_offload_token_create_blob(state, fsp, fsctl,
1976 if (tevent_req_nterror(req, status)) {
1977 return tevent_req_post(req, ev);
1980 status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1982 if (tevent_req_nterror(req, status)) {
1983 return tevent_req_post(req, ev);
1986 tevent_req_done(req);
1987 return tevent_req_post(req, ev);
1990 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
1991 struct vfs_handle_struct *handle,
1992 TALLOC_CTX *mem_ctx,
1995 struct vfswrap_offload_read_state *state = tevent_req_data(
1996 req, struct vfswrap_offload_read_state);
1999 if (tevent_req_is_nterror(req, &status)) {
2000 tevent_req_received(req);
2004 token->length = state->token.length;
2005 token->data = talloc_move(mem_ctx, &state->token.data);
2007 tevent_req_received(req);
2008 return NT_STATUS_OK;
2011 struct vfswrap_offload_write_state {
2013 bool read_lck_locked;
2014 bool write_lck_locked;
2016 struct tevent_context *src_ev;
2017 struct files_struct *src_fsp;
2019 struct tevent_context *dst_ev;
2020 struct files_struct *dst_fsp;
2025 size_t next_io_size;
2028 static void vfswrap_offload_write_cleanup(struct tevent_req *req,
2029 enum tevent_req_state req_state)
2031 struct vfswrap_offload_write_state *state = tevent_req_data(
2032 req, struct vfswrap_offload_write_state);
2035 if (state->dst_fsp == NULL) {
2039 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2041 state->dst_fsp = NULL;
2044 static NTSTATUS vfswrap_offload_copy_file_range(struct tevent_req *req);
2045 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
2047 static struct tevent_req *vfswrap_offload_write_send(
2048 struct vfs_handle_struct *handle,
2049 TALLOC_CTX *mem_ctx,
2050 struct tevent_context *ev,
2053 off_t transfer_offset,
2054 struct files_struct *dest_fsp,
2058 struct tevent_req *req;
2059 struct vfswrap_offload_write_state *state = NULL;
2060 /* off_t is signed! */
2061 off_t max_offset = INT64_MAX - to_copy;
2062 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
2063 files_struct *src_fsp = NULL;
2067 req = tevent_req_create(mem_ctx, &state,
2068 struct vfswrap_offload_write_state);
2073 *state = (struct vfswrap_offload_write_state) {
2075 .src_off = transfer_offset,
2077 .dst_fsp = dest_fsp,
2078 .dst_off = dest_off,
2080 .remaining = to_copy,
2083 tevent_req_set_cleanup_fn(req, vfswrap_offload_write_cleanup);
2086 case FSCTL_SRV_COPYCHUNK:
2087 case FSCTL_SRV_COPYCHUNK_WRITE:
2090 case FSCTL_OFFLOAD_WRITE:
2091 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
2092 return tevent_req_post(req, ev);
2094 case FSCTL_DUP_EXTENTS_TO_FILE:
2095 DBG_DEBUG("COW clones not supported by vfs_default\n");
2096 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2097 return tevent_req_post(req, ev);
2100 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2101 return tevent_req_post(req, ev);
2105 * From here on we assume a copy-chunk fsctl
2109 tevent_req_done(req);
2110 return tevent_req_post(req, ev);
2113 if (state->src_off > max_offset) {
2115 * Protect integer checks below.
2117 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2118 return tevent_req_post(req, ev);
2120 if (state->src_off < 0) {
2122 * Protect integer checks below.
2124 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2125 return tevent_req_post(req, ev);
2127 if (state->dst_off > max_offset) {
2129 * Protect integer checks below.
2131 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2132 return tevent_req_post(req, ev);
2134 if (state->dst_off < 0) {
2136 * Protect integer checks below.
2138 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2139 return tevent_req_post(req, ev);
2142 status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
2144 if (tevent_req_nterror(req, status)) {
2145 return tevent_req_post(req, ev);
2148 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
2150 status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
2151 if (!NT_STATUS_IS_OK(status)) {
2152 tevent_req_nterror(req, status);
2153 return tevent_req_post(req, ev);
2156 ok = change_to_user_and_service_by_fsp(src_fsp);
2158 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2159 return tevent_req_post(req, ev);
2162 state->src_ev = src_fsp->conn->sconn->ev_ctx;
2163 state->src_fsp = src_fsp;
2165 status = vfs_stat_fsp(src_fsp);
2166 if (tevent_req_nterror(req, status)) {
2167 return tevent_req_post(req, ev);
2170 if (src_fsp->fsp_name->st.st_ex_size < state->src_off + to_copy) {
2172 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
2173 * If the SourceOffset or SourceOffset + Length extends beyond
2174 * the end of file, the server SHOULD<240> treat this as a
2175 * STATUS_END_OF_FILE error.
2177 * <240> Section 3.3.5.15.6: Windows servers will return
2178 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
2180 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
2181 return tevent_req_post(req, ev);
2184 status = vfswrap_offload_copy_file_range(req);
2185 if (NT_STATUS_IS_OK(status)) {
2186 tevent_req_done(req);
2187 return tevent_req_post(req, ev);
2189 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2190 tevent_req_nterror(req, status);
2191 return tevent_req_post(req, ev);
2194 state->buf = talloc_array(state, uint8_t, num);
2195 if (tevent_req_nomem(state->buf, req)) {
2196 return tevent_req_post(req, ev);
2199 status = vfswrap_offload_write_loop(req);
2200 if (!NT_STATUS_IS_OK(status)) {
2201 tevent_req_nterror(req, status);
2202 return tevent_req_post(req, ev);
2208 static NTSTATUS vfswrap_offload_copy_file_range(struct tevent_req *req)
2210 struct vfswrap_offload_write_state *state = tevent_req_data(
2211 req, struct vfswrap_offload_write_state);
2212 struct lock_struct lck;
2218 #ifndef USE_COPY_FILE_RANGE
2219 return NT_STATUS_MORE_PROCESSING_REQUIRED;
2222 same_file = file_id_equal(&state->src_fsp->file_id,
2223 &state->dst_fsp->file_id);
2225 sys_io_ranges_overlap(state->remaining,
2230 return NT_STATUS_MORE_PROCESSING_REQUIRED;
2233 if (is_named_stream(state->src_fsp->fsp_name) ||
2234 is_named_stream(state->dst_fsp->fsp_name))
2236 return NT_STATUS_MORE_PROCESSING_REQUIRED;
2239 init_strict_lock_struct(state->src_fsp,
2240 state->src_fsp->op->global->open_persistent_id,
2246 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
2250 return NT_STATUS_FILE_LOCK_CONFLICT;
2253 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2255 return NT_STATUS_INTERNAL_ERROR;
2258 init_strict_lock_struct(state->dst_fsp,
2259 state->dst_fsp->op->global->open_persistent_id,
2265 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
2269 return NT_STATUS_FILE_LOCK_CONFLICT;
2272 while (state->remaining > 0) {
2273 nwritten = copy_file_range(fsp_get_io_fd(state->src_fsp),
2275 fsp_get_io_fd(state->dst_fsp),
2279 if (nwritten == -1) {
2280 DBG_DEBUG("copy_file_range src [%s]:[%jd] dst [%s]:[%jd] "
2281 "n [%jd] failed: %s\n",
2282 fsp_str_dbg(state->src_fsp),
2283 (intmax_t)state->src_off,
2284 fsp_str_dbg(state->dst_fsp),
2285 (intmax_t)state->dst_off,
2286 (intmax_t)state->remaining,
2290 status = NT_STATUS_MORE_PROCESSING_REQUIRED;
2293 status = map_nt_error_from_unix(errno);
2294 if (NT_STATUS_EQUAL(
2296 NT_STATUS_MORE_PROCESSING_REQUIRED))
2298 /* Avoid triggering the fallback */
2299 status = NT_STATUS_INTERNAL_ERROR;
2306 if (state->remaining < nwritten) {
2307 DBG_DEBUG("copy_file_range src [%s] dst [%s] "
2308 "n [%jd] remaining [%jd]\n",
2309 fsp_str_dbg(state->src_fsp),
2310 fsp_str_dbg(state->dst_fsp),
2312 (intmax_t)state->remaining);
2313 return NT_STATUS_INTERNAL_ERROR;
2316 if (nwritten == 0) {
2319 state->copied += nwritten;
2320 state->remaining -= nwritten;
2324 * Tell the req cleanup function there's no need to call
2325 * change_to_user_and_service_by_fsp() on the dst handle.
2327 state->dst_fsp = NULL;
2328 return NT_STATUS_OK;
2331 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
2333 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
2335 struct vfswrap_offload_write_state *state = tevent_req_data(
2336 req, struct vfswrap_offload_write_state);
2337 struct tevent_req *subreq = NULL;
2338 struct lock_struct read_lck;
2342 * This is called under the context of state->src_fsp.
2345 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
2347 init_strict_lock_struct(state->src_fsp,
2348 state->src_fsp->op->global->open_persistent_id,
2350 state->next_io_size,
2354 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
2358 return NT_STATUS_FILE_LOCK_CONFLICT;
2361 subreq = SMB_VFS_PREAD_SEND(state,
2365 state->next_io_size,
2367 if (subreq == NULL) {
2368 return NT_STATUS_NO_MEMORY;
2370 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
2372 return NT_STATUS_OK;
2375 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
2377 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
2379 struct tevent_req *req = tevent_req_callback_data(
2380 subreq, struct tevent_req);
2381 struct vfswrap_offload_write_state *state = tevent_req_data(
2382 req, struct vfswrap_offload_write_state);
2383 struct vfs_aio_state aio_state;
2384 struct lock_struct write_lck;
2388 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
2389 TALLOC_FREE(subreq);
2391 DBG_ERR("read failed: %s\n", strerror(aio_state.error));
2392 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2395 if (nread != state->next_io_size) {
2396 DBG_ERR("Short read, only %zd of %zu\n",
2397 nread, state->next_io_size);
2398 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2402 state->src_off += nread;
2404 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2406 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2410 init_strict_lock_struct(state->dst_fsp,
2411 state->dst_fsp->op->global->open_persistent_id,
2413 state->next_io_size,
2417 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
2421 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
2425 subreq = SMB_VFS_PWRITE_SEND(state,
2429 state->next_io_size,
2431 if (subreq == NULL) {
2432 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2435 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
2438 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
2440 struct tevent_req *req = tevent_req_callback_data(
2441 subreq, struct tevent_req);
2442 struct vfswrap_offload_write_state *state = tevent_req_data(
2443 req, struct vfswrap_offload_write_state);
2444 struct vfs_aio_state aio_state;
2449 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
2450 TALLOC_FREE(subreq);
2451 if (nwritten == -1) {
2452 DBG_ERR("write failed: %s\n", strerror(aio_state.error));
2453 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2456 if (nwritten != state->next_io_size) {
2457 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
2458 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2462 state->dst_off += nwritten;
2464 if (state->remaining < nwritten) {
2465 /* Paranoia check */
2466 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2469 state->copied += nwritten;
2470 state->remaining -= nwritten;
2471 if (state->remaining == 0) {
2472 tevent_req_done(req);
2476 ok = change_to_user_and_service_by_fsp(state->src_fsp);
2478 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2482 status = vfswrap_offload_write_loop(req);
2483 if (!NT_STATUS_IS_OK(status)) {
2484 tevent_req_nterror(req, status);
2491 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
2492 struct tevent_req *req,
2495 struct vfswrap_offload_write_state *state = tevent_req_data(
2496 req, struct vfswrap_offload_write_state);
2499 if (tevent_req_is_nterror(req, &status)) {
2500 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
2502 tevent_req_received(req);
2506 *copied = state->copied;
2507 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
2508 tevent_req_received(req);
2510 return NT_STATUS_OK;
2513 static NTSTATUS vfswrap_fget_compression(struct vfs_handle_struct *handle,
2514 TALLOC_CTX *mem_ctx,
2515 struct files_struct *fsp,
2516 uint16_t *_compression_fmt)
2518 return NT_STATUS_INVALID_DEVICE_REQUEST;
2521 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
2522 TALLOC_CTX *mem_ctx,
2523 struct files_struct *fsp,
2524 uint16_t compression_fmt)
2526 return NT_STATUS_INVALID_DEVICE_REQUEST;
2529 /********************************************************************
2530 Given a stat buffer return the allocated size on disk, taking into
2531 account sparse files.
2532 ********************************************************************/
2533 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
2534 struct files_struct *fsp,
2535 const SMB_STRUCT_STAT *sbuf)
2539 START_PROFILE(syscall_get_alloc_size);
2541 if(S_ISDIR(sbuf->st_ex_mode)) {
2546 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2547 /* The type of st_blocksize is blkcnt_t which *MUST* be
2548 signed (according to POSIX) and can be less than 64-bits.
2549 Ensure when we're converting to 64 bits wide we don't
2551 #if defined(SIZEOF_BLKCNT_T_8)
2552 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2553 #elif defined(SIZEOF_BLKCNT_T_4)
2555 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2556 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2559 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2563 * Some file systems do not allocate a block for very
2564 * small files. But for non-empty file should report a
2568 uint64_t filesize = get_file_size_stat(sbuf);
2570 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2574 result = get_file_size_stat(sbuf);
2577 if (fsp && fsp->initial_allocation_size)
2578 result = MAX(result,fsp->initial_allocation_size);
2580 result = smb_roundup(handle->conn, result);
2583 END_PROFILE(syscall_get_alloc_size);
2587 static int vfswrap_unlinkat(vfs_handle_struct *handle,
2588 struct files_struct *dirfsp,
2589 const struct smb_filename *smb_fname,
2594 START_PROFILE(syscall_unlinkat);
2596 if (is_named_stream(smb_fname)) {
2600 result = unlinkat(fsp_get_pathref_fd(dirfsp),
2601 smb_fname->base_name,
2605 END_PROFILE(syscall_unlinkat);
2609 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2613 START_PROFILE(syscall_fchmod);
2615 if (!fsp->fsp_flags.is_pathref) {
2616 result = fchmod(fsp_get_io_fd(fsp), mode);
2617 END_PROFILE(syscall_fchmod);
2621 if (fsp->fsp_flags.have_proc_fds) {
2622 int fd = fsp_get_pathref_fd(fsp);
2623 const char *p = NULL;
2626 p = sys_proc_fd_path(fd, buf, sizeof(buf));
2628 result = chmod(p, mode);
2632 END_PROFILE(syscall_fchmod);
2637 * This is no longer a handle based call.
2639 result = chmod(fsp->fsp_name->base_name, mode);
2641 END_PROFILE(syscall_fchmod);
2645 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2650 START_PROFILE(syscall_fchown);
2651 if (!fsp->fsp_flags.is_pathref) {
2652 result = fchown(fsp_get_io_fd(fsp), uid, gid);
2653 END_PROFILE(syscall_fchown);
2657 if (fsp->fsp_flags.have_proc_fds) {
2658 int fd = fsp_get_pathref_fd(fsp);
2659 const char *p = NULL;
2662 p = sys_proc_fd_path(fd, buf, sizeof(buf));
2664 result = chown(p, uid, gid);
2668 END_PROFILE(syscall_fchown);
2673 * This is no longer a handle based call.
2675 result = chown(fsp->fsp_name->base_name, uid, gid);
2676 END_PROFILE(syscall_fchown);
2684 static int vfswrap_lchown(vfs_handle_struct *handle,
2685 const struct smb_filename *smb_fname,
2691 START_PROFILE(syscall_lchown);
2692 result = lchown(smb_fname->base_name, uid, gid);
2693 END_PROFILE(syscall_lchown);
2697 static int vfswrap_chdir(vfs_handle_struct *handle,
2698 const struct smb_filename *smb_fname)
2702 START_PROFILE(syscall_chdir);
2703 result = chdir(smb_fname->base_name);
2704 END_PROFILE(syscall_chdir);
2708 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2712 struct smb_filename *smb_fname = NULL;
2714 START_PROFILE(syscall_getwd);
2715 result = sys_getwd();
2716 END_PROFILE(syscall_getwd);
2718 if (result == NULL) {
2721 smb_fname = synthetic_smb_fname(ctx,
2728 * sys_getwd() *always* returns malloced memory.
2729 * We must free here to avoid leaks:
2730 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2736 /*********************************************************************
2737 nsec timestamp resolution call. Convert down to whatever the underlying
2738 system will support.
2739 **********************************************************************/
2741 static int vfswrap_fntimes(vfs_handle_struct *handle,
2743 struct smb_file_time *ft)
2746 struct timespec ts[2];
2747 struct timespec *times = NULL;
2749 START_PROFILE(syscall_fntimes);
2751 if (is_named_stream(fsp->fsp_name)) {
2757 if (is_omit_timespec(&ft->atime)) {
2758 ft->atime = fsp->fsp_name->st.st_ex_atime;
2761 if (is_omit_timespec(&ft->mtime)) {
2762 ft->mtime = fsp->fsp_name->st.st_ex_mtime;
2765 if (!is_omit_timespec(&ft->create_time)) {
2766 set_create_timespec_ea(fsp,
2770 if ((timespec_compare(&ft->atime,
2771 &fsp->fsp_name->st.st_ex_atime) == 0) &&
2772 (timespec_compare(&ft->mtime,
2773 &fsp->fsp_name->st.st_ex_mtime) == 0)) {
2785 if (!fsp->fsp_flags.is_pathref) {
2786 result = futimens(fsp_get_io_fd(fsp), times);
2790 if (fsp->fsp_flags.have_proc_fds) {
2791 int fd = fsp_get_pathref_fd(fsp);
2792 const char *p = NULL;
2795 p = sys_proc_fd_path(fd, buf, sizeof(buf));
2798 * The dirfd argument of utimensat is ignored when
2799 * pathname is an absolute path
2801 result = utimensat(AT_FDCWD, p, times, 0);
2810 * The fd is a pathref (opened with O_PATH) and there isn't fd to
2811 * path translation mechanism. Fallback to path based call.
2813 result = utimensat(AT_FDCWD, fsp->fsp_name->base_name, times, 0);
2816 END_PROFILE(syscall_fntimes);
2822 /*********************************************************************
2823 A version of ftruncate that will write the space on disk if strict
2825 **********************************************************************/
2827 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2829 off_t space_to_write;
2830 uint64_t space_avail;
2831 uint64_t bsize,dfree,dsize;
2834 SMB_STRUCT_STAT *pst;
2837 ok = vfs_valid_pwrite_range(len, 0);
2843 status = vfs_stat_fsp(fsp);
2844 if (!NT_STATUS_IS_OK(status)) {
2847 pst = &fsp->fsp_name->st;
2850 if (S_ISFIFO(pst->st_ex_mode))
2854 if (pst->st_ex_size == len)
2857 /* Shrink - just ftruncate. */
2858 if (pst->st_ex_size > len)
2859 return ftruncate(fsp_get_io_fd(fsp), len);
2861 space_to_write = len - pst->st_ex_size;
2863 /* for allocation try fallocate first. This can fail on some
2864 platforms e.g. when the filesystem doesn't support it and no
2865 emulation is being done by the libc (like on AIX with JFS1). In that
2866 case we do our own emulation. fallocate implementations can
2867 return ENOTSUP or EINVAL in cases like that. */
2868 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2869 if (ret == -1 && errno == ENOSPC) {
2875 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2876 "error %d. Falling back to slow manual allocation\n", errno));
2878 /* available disk space is enough or not? */
2880 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2881 /* space_avail is 1k blocks */
2882 if (space_avail == (uint64_t)-1 ||
2883 ((uint64_t)space_to_write/1024 > space_avail) ) {
2888 /* Write out the real space on disk. */
2889 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2897 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2900 SMB_STRUCT_STAT *pst;
2904 START_PROFILE(syscall_ftruncate);
2906 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->fsp_flags.is_sparse) {
2907 result = strict_allocate_ftruncate(handle, fsp, len);
2908 END_PROFILE(syscall_ftruncate);
2912 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2913 ftruncate if the system supports it. Then I discovered that
2914 you can have some filesystems that support ftruncate
2915 expansion and some that don't! On Linux fat can't do
2916 ftruncate extend but ext2 can. */
2918 result = ftruncate(fsp_get_io_fd(fsp), len);
2920 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2921 extend a file with ftruncate. Provide alternate implementation
2924 /* Do an fstat to see if the file is longer than the requested
2925 size in which case the ftruncate above should have
2926 succeeded or shorter, in which case seek to len - 1 and
2927 write 1 byte of zero */
2928 status = vfs_stat_fsp(fsp);
2929 if (!NT_STATUS_IS_OK(status)) {
2933 /* We need to update the files_struct after successful ftruncate */
2938 pst = &fsp->fsp_name->st;
2941 if (S_ISFIFO(pst->st_ex_mode)) {
2947 if (pst->st_ex_size == len) {
2952 if (pst->st_ex_size > len) {
2953 /* the ftruncate should have worked */
2957 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2965 END_PROFILE(syscall_ftruncate);
2969 static int vfswrap_fallocate(vfs_handle_struct *handle,
2977 START_PROFILE(syscall_fallocate);
2979 result = sys_posix_fallocate(fsp_get_io_fd(fsp), offset, len);
2981 * posix_fallocate returns 0 on success, errno on error
2982 * and doesn't set errno. Make it behave like fallocate()
2983 * which returns -1, and sets errno on failure.
2990 /* sys_fallocate handles filtering of unsupported mode flags */
2991 result = sys_fallocate(fsp_get_io_fd(fsp), mode, offset, len);
2993 END_PROFILE(syscall_fallocate);
2997 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
3001 START_PROFILE(syscall_fcntl_lock);
3003 if (fsp->fsp_flags.use_ofd_locks) {
3004 op = map_process_lock_to_ofd_lock(op);
3007 result = fcntl_lock(fsp_get_io_fd(fsp), op, offset, count, type);
3008 END_PROFILE(syscall_fcntl_lock);
3012 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
3013 uint32_t share_access, uint32_t access_mask)
3015 START_PROFILE(syscall_kernel_flock);
3016 kernel_flock(fsp_get_io_fd(fsp), share_access, access_mask);
3017 END_PROFILE(syscall_kernel_flock);
3021 static int vfswrap_fcntl(vfs_handle_struct *handle, files_struct *fsp, int cmd,
3025 va_list dup_cmd_arg;
3029 START_PROFILE(syscall_fcntl);
3031 va_copy(dup_cmd_arg, cmd_arg);
3037 #if defined(HAVE_OFD_LOCKS)
3042 #if defined(HAVE_F_OWNER_EX)
3046 #if defined(HAVE_RW_HINTS)
3049 case F_GET_FILE_RW_HINT:
3050 case F_SET_FILE_RW_HINT:
3052 argp = va_arg(dup_cmd_arg, void *);
3053 result = sys_fcntl_ptr(fsp_get_io_fd(fsp), cmd, argp);
3056 val = va_arg(dup_cmd_arg, int);
3057 result = sys_fcntl_int(fsp_get_io_fd(fsp), cmd, val);
3060 va_end(dup_cmd_arg);
3062 END_PROFILE(syscall_fcntl);
3066 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
3071 START_PROFILE(syscall_fcntl_getlock);
3073 if (fsp->fsp_flags.use_ofd_locks) {
3074 op = map_process_lock_to_ofd_lock(op);
3077 result = fcntl_getlock(fsp_get_io_fd(fsp), op, poffset, pcount, ptype, ppid);
3078 END_PROFILE(syscall_fcntl_getlock);
3082 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
3087 START_PROFILE(syscall_linux_setlease);
3089 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
3090 result = linux_setlease(fsp_get_io_fd(fsp), leasetype);
3094 END_PROFILE(syscall_linux_setlease);
3098 static int vfswrap_symlinkat(vfs_handle_struct *handle,
3099 const struct smb_filename *link_target,
3100 struct files_struct *dirfsp,
3101 const struct smb_filename *new_smb_fname)
3105 START_PROFILE(syscall_symlinkat);
3107 result = symlinkat(link_target->base_name,
3108 fsp_get_pathref_fd(dirfsp),
3109 new_smb_fname->base_name);
3110 END_PROFILE(syscall_symlinkat);
3114 static int vfswrap_readlinkat(vfs_handle_struct *handle,
3115 const struct files_struct *dirfsp,
3116 const struct smb_filename *smb_fname,
3122 START_PROFILE(syscall_readlinkat);
3124 result = readlinkat(fsp_get_pathref_fd(dirfsp),
3125 smb_fname->base_name,
3129 END_PROFILE(syscall_readlinkat);
3133 static int vfswrap_linkat(vfs_handle_struct *handle,
3134 files_struct *srcfsp,
3135 const struct smb_filename *old_smb_fname,
3136 files_struct *dstfsp,
3137 const struct smb_filename *new_smb_fname,
3142 START_PROFILE(syscall_linkat);
3144 result = linkat(fsp_get_pathref_fd(srcfsp),
3145 old_smb_fname->base_name,
3146 fsp_get_pathref_fd(dstfsp),
3147 new_smb_fname->base_name,
3150 END_PROFILE(syscall_linkat);
3154 static int vfswrap_mknodat(vfs_handle_struct *handle,
3155 files_struct *dirfsp,
3156 const struct smb_filename *smb_fname,
3162 START_PROFILE(syscall_mknodat);
3164 result = sys_mknodat(fsp_get_pathref_fd(dirfsp),
3165 smb_fname->base_name,
3169 END_PROFILE(syscall_mknodat);
3173 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
3175 const struct smb_filename *smb_fname)
3178 struct smb_filename *result_fname = NULL;
3180 START_PROFILE(syscall_realpath);
3181 result = sys_realpath(smb_fname->base_name);
3182 END_PROFILE(syscall_realpath);
3184 result_fname = synthetic_smb_fname(ctx,
3192 return result_fname;
3195 static int vfswrap_fchflags(vfs_handle_struct *handle,
3196 struct files_struct *fsp,
3199 #ifdef HAVE_FCHFLAGS
3200 int fd = fsp_get_pathref_fd(fsp);
3202 if (!fsp->fsp_flags.is_pathref) {
3203 return fchflags(fd, flags);
3206 if (fsp->fsp_flags.have_proc_fds) {
3207 const char *p = NULL;
3210 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3215 return chflags(p, flags);
3219 * This is no longer a handle based call.
3221 return chflags(fsp->fsp_name->base_name, flags);
3228 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
3229 const SMB_STRUCT_STAT *sbuf)
3233 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
3237 key.devid = sbuf->st_ex_dev;
3238 key.inode = sbuf->st_ex_ino;
3239 /* key.extid is unused by default. */
3244 static uint64_t vfswrap_fs_file_id(struct vfs_handle_struct *handle,
3245 const SMB_STRUCT_STAT *psbuf)
3249 if (!(psbuf->st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)) {
3250 return psbuf->st_ex_file_id;
3253 if (handle->conn->base_share_dev == psbuf->st_ex_dev) {
3254 return (uint64_t)psbuf->st_ex_ino;
3258 file_id = ((psbuf->st_ex_ino) & UINT32_MAX);
3261 file_id |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32;
3266 static NTSTATUS vfswrap_fstreaminfo(vfs_handle_struct *handle,
3267 struct files_struct *fsp,
3268 TALLOC_CTX *mem_ctx,
3269 unsigned int *pnum_streams,
3270 struct stream_struct **pstreams)
3272 struct stream_struct *tmp_streams = NULL;
3273 unsigned int num_streams = *pnum_streams;
3274 struct stream_struct *streams = *pstreams;
3277 if (fsp->fsp_flags.is_directory) {
3279 * No default streams on directories
3283 status = vfs_stat_fsp(fsp);
3284 if (!NT_STATUS_IS_OK(status)) {
3288 if (num_streams + 1 < 1) {
3290 return NT_STATUS_INVALID_PARAMETER;
3293 tmp_streams = talloc_realloc(mem_ctx,
3295 struct stream_struct,
3297 if (tmp_streams == NULL) {
3298 return NT_STATUS_NO_MEMORY;
3300 tmp_streams[num_streams].name = talloc_strdup(tmp_streams, "::$DATA");
3301 if (tmp_streams[num_streams].name == NULL) {
3302 return NT_STATUS_NO_MEMORY;
3304 tmp_streams[num_streams].size = fsp->fsp_name->st.st_ex_size;
3305 tmp_streams[num_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(
3308 &fsp->fsp_name->st);
3311 *pnum_streams = num_streams;
3312 *pstreams = tmp_streams;
3314 return NT_STATUS_OK;
3317 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
3318 const struct smb_filename *path,
3320 TALLOC_CTX *mem_ctx,
3324 * Don't fall back to get_real_filename so callers can differentiate
3325 * between a full directory scan and an actual case-insensitive stat.
3331 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
3332 const struct smb_filename *smb_fname)
3334 return handle->conn->connectpath;
3337 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
3338 struct byte_range_lock *br_lck,
3339 struct lock_struct *plock)
3341 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3343 /* Note: blr is not used in the default implementation. */
3344 return brl_lock_windows_default(br_lck, plock);
3347 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
3348 struct byte_range_lock *br_lck,
3349 const struct lock_struct *plock)
3351 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3353 return brl_unlock_windows_default(br_lck, plock);
3356 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
3358 struct lock_struct *plock)
3360 SMB_ASSERT(plock->lock_type == READ_LOCK ||
3361 plock->lock_type == WRITE_LOCK);
3363 return strict_lock_check_default(fsp, plock);
3366 /* NT ACL operations. */
3368 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
3370 uint32_t security_info,
3371 TALLOC_CTX *mem_ctx,
3372 struct security_descriptor **ppdesc)
3376 START_PROFILE(fget_nt_acl);
3377 result = posix_fget_nt_acl(fsp, security_info,
3379 END_PROFILE(fget_nt_acl);
3383 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
3387 START_PROFILE(fset_nt_acl);
3388 result = set_nt_acl(fsp, security_info_sent, psd);
3389 END_PROFILE(fset_nt_acl);
3393 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
3394 struct smb_filename *file,
3395 struct security_acl *sacl,
3396 uint32_t access_requested,
3397 uint32_t access_denied)
3399 return NT_STATUS_OK; /* Nothing to do here ... */
3402 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
3404 SMB_ACL_TYPE_T type,
3405 TALLOC_CTX *mem_ctx)
3407 return sys_acl_get_fd(handle, fsp, type, mem_ctx);
3410 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle,
3412 SMB_ACL_TYPE_T type,
3415 return sys_acl_set_fd(handle, fsp, type, theacl);
3418 static int vfswrap_sys_acl_delete_def_fd(vfs_handle_struct *handle,
3421 return sys_acl_delete_def_fd(handle, fsp);
3424 /****************************************************************
3425 Extended attribute operations.
3426 *****************************************************************/
3428 struct vfswrap_getxattrat_state {
3429 struct tevent_context *ev;
3430 files_struct *dir_fsp;
3431 const struct smb_filename *smb_fname;
3434 * The following variables are talloced off "state" which is protected
3435 * by a destructor and thus are guaranteed to be safe to be used in the
3436 * job function in the worker thread.
3439 const char *xattr_name;
3440 uint8_t *xattr_value;
3441 struct security_unix_token *token;
3444 struct vfs_aio_state vfs_aio_state;
3445 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
3448 static int vfswrap_getxattrat_state_destructor(
3449 struct vfswrap_getxattrat_state *state)
3454 static void vfswrap_getxattrat_do_sync(struct tevent_req *req);
3455 static void vfswrap_getxattrat_do_async(void *private_data);
3456 static void vfswrap_getxattrat_done(struct tevent_req *subreq);
3458 static struct tevent_req *vfswrap_getxattrat_send(
3459 TALLOC_CTX *mem_ctx,
3460 struct tevent_context *ev,
3461 struct vfs_handle_struct *handle,
3462 files_struct *dir_fsp,
3463 const struct smb_filename *smb_fname,
3464 const char *xattr_name,
3467 struct tevent_req *req = NULL;
3468 struct tevent_req *subreq = NULL;
3469 struct vfswrap_getxattrat_state *state = NULL;
3470 size_t max_threads = 0;
3471 bool have_per_thread_cwd = false;
3472 bool have_per_thread_creds = false;
3473 bool do_async = false;
3475 req = tevent_req_create(mem_ctx, &state,
3476 struct vfswrap_getxattrat_state);
3480 *state = (struct vfswrap_getxattrat_state) {
3483 .smb_fname = smb_fname,
3486 max_threads = pthreadpool_tevent_max_threads(dir_fsp->conn->sconn->pool);
3487 if (max_threads >= 1) {
3489 * We need a non sync threadpool!
3491 have_per_thread_cwd = per_thread_cwd_supported();
3493 #ifdef HAVE_LINUX_THREAD_CREDENTIALS
3494 have_per_thread_creds = true;
3496 if (have_per_thread_cwd && have_per_thread_creds) {
3500 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat, profile_p,
3501 state->profile_bytes, 0);
3503 if (fsp_get_pathref_fd(dir_fsp) == -1) {
3504 DBG_ERR("Need a valid directory fd\n");
3505 tevent_req_error(req, EINVAL);
3506 return tevent_req_post(req, ev);
3509 if (alloc_hint > 0) {
3510 state->xattr_value = talloc_zero_array(state,
3513 if (tevent_req_nomem(state->xattr_value, req)) {
3514 return tevent_req_post(req, ev);
3519 vfswrap_getxattrat_do_sync(req);
3520 return tevent_req_post(req, ev);
3524 * Now allocate all parameters from a memory context that won't go away
3525 * no matter what. These paremeters will get used in threads and we
3526 * can't reliably cancel threads, so all buffers passed to the threads
3527 * must not be freed before all referencing threads terminate.
3530 state->name = talloc_strdup(state, smb_fname->base_name);
3531 if (tevent_req_nomem(state->name, req)) {
3532 return tevent_req_post(req, ev);
3535 state->xattr_name = talloc_strdup(state, xattr_name);
3536 if (tevent_req_nomem(state->xattr_name, req)) {
3537 return tevent_req_post(req, ev);
3541 * This is a hot codepath so at first glance one might think we should
3542 * somehow optimize away the token allocation and do a
3543 * talloc_reference() or similar black magic instead. But due to the
3544 * talloc_stackframe pool per SMB2 request this should be a simple copy
3545 * without a malloc in most cases.
3547 if (geteuid() == sec_initial_uid()) {
3548 state->token = root_unix_token(state);
3550 state->token = copy_unix_token(
3552 dir_fsp->conn->session_info->unix_token);
3554 if (tevent_req_nomem(state->token, req)) {
3555 return tevent_req_post(req, ev);
3558 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3560 subreq = pthreadpool_tevent_job_send(
3563 dir_fsp->conn->sconn->pool,
3564 vfswrap_getxattrat_do_async,
3566 if (tevent_req_nomem(subreq, req)) {
3567 return tevent_req_post(req, ev);
3569 tevent_req_set_callback(subreq, vfswrap_getxattrat_done, req);
3571 talloc_set_destructor(state, vfswrap_getxattrat_state_destructor);
3576 static void vfswrap_getxattrat_do_sync(struct tevent_req *req)
3578 struct vfswrap_getxattrat_state *state = tevent_req_data(
3579 req, struct vfswrap_getxattrat_state);
3581 char *tofree = NULL;
3582 char pathbuf[PATH_MAX+1];
3586 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
3587 state->smb_fname->base_name,
3592 if (pathlen == -1) {
3593 tevent_req_error(req, ENOMEM);
3597 state->xattr_size = getxattr(path,
3600 talloc_array_length(state->xattr_value));
3602 TALLOC_FREE(tofree);
3603 if (state->xattr_size == -1) {
3604 tevent_req_error(req, err);
3608 tevent_req_done(req);
3612 static void vfswrap_getxattrat_do_async(void *private_data)
3614 struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3615 private_data, struct vfswrap_getxattrat_state);
3616 struct timespec start_time;
3617 struct timespec end_time;
3620 PROFILE_TIMESTAMP(&start_time);
3621 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
3624 * Here we simulate a getxattrat()
3625 * call using fchdir();getxattr()
3628 per_thread_cwd_activate();
3630 /* Become the correct credential on this thread. */
3631 ret = set_thread_credentials(state->token->uid,
3633 (size_t)state->token->ngroups,
3634 state->token->groups);
3636 state->xattr_size = -1;
3637 state->vfs_aio_state.error = errno;
3641 ret = fchdir(fsp_get_pathref_fd(state->dir_fsp));
3643 state->xattr_size = -1;
3644 state->vfs_aio_state.error = errno;
3648 state->xattr_size = getxattr(state->name,
3651 talloc_array_length(state->xattr_value));
3652 if (state->xattr_size == -1) {
3653 state->vfs_aio_state.error = errno;
3657 PROFILE_TIMESTAMP(&end_time);
3658 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
3659 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3662 static void vfswrap_getxattrat_done(struct tevent_req *subreq)
3664 struct tevent_req *req = tevent_req_callback_data(
3665 subreq, struct tevent_req);
3666 struct vfswrap_getxattrat_state *state = tevent_req_data(
3667 req, struct vfswrap_getxattrat_state);
3672 * Make sure we run as the user again
3674 ok = change_to_user_and_service_by_fsp(state->dir_fsp);
3677 ret = pthreadpool_tevent_job_recv(subreq);
3678 TALLOC_FREE(subreq);
3679 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
3680 talloc_set_destructor(state, NULL);
3682 if (ret != EAGAIN) {
3683 tevent_req_error(req, ret);
3687 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
3688 * means the lower level pthreadpool failed to create a new
3689 * thread. Fallback to sync processing in that case to allow
3690 * some progress for the client.
3692 vfswrap_getxattrat_do_sync(req);
3696 if (state->xattr_size == -1) {
3697 tevent_req_error(req, state->vfs_aio_state.error);
3701 if (state->xattr_value == NULL) {
3703 * The caller only wanted the size.
3705 tevent_req_done(req);
3710 * shrink the buffer to the returned size.
3711 * (can't fail). It means NULL if size is 0.
3713 state->xattr_value = talloc_realloc(state,
3718 tevent_req_done(req);
3721 static ssize_t vfswrap_getxattrat_recv(struct tevent_req *req,
3722 struct vfs_aio_state *aio_state,
3723 TALLOC_CTX *mem_ctx,
3724 uint8_t **xattr_value)
3726 struct vfswrap_getxattrat_state *state = tevent_req_data(
3727 req, struct vfswrap_getxattrat_state);
3730 if (tevent_req_is_unix_error(req, &aio_state->error)) {
3731 tevent_req_received(req);
3735 *aio_state = state->vfs_aio_state;
3736 xattr_size = state->xattr_size;
3737 if (xattr_value != NULL) {
3738 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
3741 tevent_req_received(req);
3745 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle,
3746 struct files_struct *fsp,
3751 int fd = fsp_get_pathref_fd(fsp);
3753 if (!fsp->fsp_flags.is_pathref) {
3754 return fgetxattr(fd, name, value, size);
3757 if (fsp->fsp_flags.have_proc_fds) {
3758 const char *p = NULL;
3761 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3766 return getxattr(p, name, value, size);
3770 * This is no longer a handle based call.
3772 return getxattr(fsp->fsp_name->base_name, name, value, size);
3775 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
3777 int fd = fsp_get_pathref_fd(fsp);
3779 if (!fsp->fsp_flags.is_pathref) {
3780 return flistxattr(fd, list, size);
3783 if (fsp->fsp_flags.have_proc_fds) {
3784 const char *p = NULL;
3787 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3792 return listxattr(p, list, size);
3796 * This is no longer a handle based call.
3798 return listxattr(fsp->fsp_name->base_name, list, size);
3801 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
3803 int fd = fsp_get_pathref_fd(fsp);
3805 if (!fsp->fsp_flags.is_pathref) {
3806 return fremovexattr(fd, name);
3809 if (fsp->fsp_flags.have_proc_fds) {
3810 const char *p = NULL;
3813 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3818 return removexattr(p, name);
3822 * This is no longer a handle based call.
3824 return removexattr(fsp->fsp_name->base_name, name);
3827 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
3829 int fd = fsp_get_pathref_fd(fsp);
3831 if (!fsp->fsp_flags.is_pathref) {
3832 return fsetxattr(fd, name, value, size, flags);
3835 if (fsp->fsp_flags.have_proc_fds) {
3836 const char *p = NULL;
3839 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3844 return setxattr(p, name, value, size, flags);
3848 * This is no longer a handle based call.
3850 return setxattr(fsp->fsp_name->base_name, name, value, size, flags);
3853 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
3858 static bool vfswrap_is_offline(struct connection_struct *conn,
3859 const struct smb_filename *fname)
3863 bool offline = false;
3865 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
3869 if (!lp_dmapi_support(SNUM(conn)) || !dmapi_have_session()) {
3870 #if defined(ENOTSUP)
3876 status = get_full_smb_filename(talloc_tos(), fname, &path);
3877 if (!NT_STATUS_IS_OK(status)) {
3878 errno = map_errno_from_nt_status(status);
3882 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
3889 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
3890 struct files_struct *fsp,
3891 TALLOC_CTX *mem_ctx,
3894 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
3897 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
3898 struct files_struct *fsp,
3899 const DATA_BLOB old_cookie,
3900 TALLOC_CTX *mem_ctx,
3901 DATA_BLOB *new_cookie)
3903 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
3907 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
3908 struct smb_request *smb1req,
3909 struct smbXsrv_open *op,
3910 const DATA_BLOB old_cookie,
3911 TALLOC_CTX *mem_ctx,
3912 struct files_struct **fsp,
3913 DATA_BLOB *new_cookie)
3915 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
3916 old_cookie, mem_ctx,
3920 static struct vfs_fn_pointers vfs_default_fns = {
3921 /* Disk operations */
3923 .connect_fn = vfswrap_connect,
3924 .disconnect_fn = vfswrap_disconnect,
3925 .disk_free_fn = vfswrap_disk_free,
3926 .get_quota_fn = vfswrap_get_quota,
3927 .set_quota_fn = vfswrap_set_quota,
3928 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3929 .statvfs_fn = vfswrap_statvfs,
3930 .fs_capabilities_fn = vfswrap_fs_capabilities,
3931 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3932 .create_dfs_pathat_fn = vfswrap_create_dfs_pathat,
3933 .read_dfs_pathat_fn = vfswrap_read_dfs_pathat,
3934 .snap_check_path_fn = vfswrap_snap_check_path,
3935 .snap_create_fn = vfswrap_snap_create,
3936 .snap_delete_fn = vfswrap_snap_delete,
3938 /* Directory operations */
3940 .fdopendir_fn = vfswrap_fdopendir,
3941 .readdir_fn = vfswrap_readdir,
3942 .freaddir_attr_fn = vfswrap_freaddir_attr,
3943 .seekdir_fn = vfswrap_seekdir,
3944 .telldir_fn = vfswrap_telldir,
3945 .rewind_dir_fn = vfswrap_rewinddir,
3946 .mkdirat_fn = vfswrap_mkdirat,
3947 .closedir_fn = vfswrap_closedir,
3949 /* File operations */
3951 .openat_fn = vfswrap_openat,
3952 .create_file_fn = vfswrap_create_file,
3953 .close_fn = vfswrap_close,
3954 .pread_fn = vfswrap_pread,
3955 .pread_send_fn = vfswrap_pread_send,
3956 .pread_recv_fn = vfswrap_pread_recv,
3957 .pwrite_fn = vfswrap_pwrite,
3958 .pwrite_send_fn = vfswrap_pwrite_send,
3959 .pwrite_recv_fn = vfswrap_pwrite_recv,
3960 .lseek_fn = vfswrap_lseek,
3961 .sendfile_fn = vfswrap_sendfile,
3962 .recvfile_fn = vfswrap_recvfile,
3963 .renameat_fn = vfswrap_renameat,
3964 .fsync_send_fn = vfswrap_fsync_send,
3965 .fsync_recv_fn = vfswrap_fsync_recv,
3966 .stat_fn = vfswrap_stat,
3967 .fstat_fn = vfswrap_fstat,
3968 .lstat_fn = vfswrap_lstat,
3969 .get_alloc_size_fn = vfswrap_get_alloc_size,
3970 .unlinkat_fn = vfswrap_unlinkat,
3971 .fchmod_fn = vfswrap_fchmod,
3972 .fchown_fn = vfswrap_fchown,
3973 .lchown_fn = vfswrap_lchown,
3974 .chdir_fn = vfswrap_chdir,
3975 .getwd_fn = vfswrap_getwd,
3976 .fntimes_fn = vfswrap_fntimes,
3977 .ftruncate_fn = vfswrap_ftruncate,
3978 .fallocate_fn = vfswrap_fallocate,
3979 .lock_fn = vfswrap_lock,
3980 .kernel_flock_fn = vfswrap_kernel_flock,
3981 .fcntl_fn = vfswrap_fcntl,
3982 .linux_setlease_fn = vfswrap_linux_setlease,
3983 .getlock_fn = vfswrap_getlock,
3984 .symlinkat_fn = vfswrap_symlinkat,
3985 .readlinkat_fn = vfswrap_readlinkat,
3986 .linkat_fn = vfswrap_linkat,
3987 .mknodat_fn = vfswrap_mknodat,
3988 .realpath_fn = vfswrap_realpath,
3989 .fchflags_fn = vfswrap_fchflags,
3990 .file_id_create_fn = vfswrap_file_id_create,
3991 .fs_file_id_fn = vfswrap_fs_file_id,
3992 .fstreaminfo_fn = vfswrap_fstreaminfo,
3993 .get_real_filename_fn = vfswrap_get_real_filename,
3994 .connectpath_fn = vfswrap_connectpath,
3995 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
3996 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3997 .strict_lock_check_fn = vfswrap_strict_lock_check,
3998 .translate_name_fn = vfswrap_translate_name,
3999 .parent_pathname_fn = vfswrap_parent_pathname,
4000 .fsctl_fn = vfswrap_fsctl,
4001 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
4002 .get_dos_attributes_send_fn = vfswrap_get_dos_attributes_send,
4003 .get_dos_attributes_recv_fn = vfswrap_get_dos_attributes_recv,
4004 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
4005 .offload_read_send_fn = vfswrap_offload_read_send,
4006 .offload_read_recv_fn = vfswrap_offload_read_recv,
4007 .offload_write_send_fn = vfswrap_offload_write_send,
4008 .offload_write_recv_fn = vfswrap_offload_write_recv,
4009 .fget_compression_fn = vfswrap_fget_compression,
4010 .set_compression_fn = vfswrap_set_compression,
4012 /* NT ACL operations. */
4014 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
4015 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
4016 .audit_file_fn = vfswrap_audit_file,
4018 /* POSIX ACL operations. */
4020 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
4021 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
4022 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
4023 .sys_acl_delete_def_fd_fn = vfswrap_sys_acl_delete_def_fd,
4025 /* EA operations. */
4026 .getxattrat_send_fn = vfswrap_getxattrat_send,
4027 .getxattrat_recv_fn = vfswrap_getxattrat_recv,
4028 .fgetxattr_fn = vfswrap_fgetxattr,
4029 .flistxattr_fn = vfswrap_flistxattr,
4030 .fremovexattr_fn = vfswrap_fremovexattr,
4031 .fsetxattr_fn = vfswrap_fsetxattr,
4033 /* aio operations */
4034 .aio_force_fn = vfswrap_aio_force,
4036 /* durable handle operations */
4037 .durable_cookie_fn = vfswrap_durable_cookie,
4038 .durable_disconnect_fn = vfswrap_durable_disconnect,
4039 .durable_reconnect_fn = vfswrap_durable_reconnect,
4043 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
4046 * Here we need to implement every call!
4048 * As this is the end of the vfs module chain.
4050 smb_vfs_assert_all_fns(&vfs_default_fns, DEFAULT_VFS_MODULE_NAME);
4051 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
4052 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);