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 if (is_named_stream(smb_fname)) {
441 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
445 if (ppreflist == NULL && preferral_count == NULL) {
447 * We're only checking if this is a DFS
448 * redirect. We don't need to return data.
450 bufsize = sizeof(link_target_buf);
451 link_target = link_target_buf;
454 link_target = talloc_array(mem_ctx, char, bufsize);
460 referral_len = readlinkat(fsp_get_pathref_fd(dirfsp),
461 smb_fname->base_name,
464 if (referral_len == -1) {
465 if (errno == EINVAL) {
467 * If the path isn't a link, readlinkat
468 * returns EINVAL. Allow the caller to
471 DBG_INFO("%s is not a link.\n", smb_fname->base_name);
472 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
474 status = map_nt_error_from_unix(errno);
475 if (errno == ENOENT) {
476 DBG_NOTICE("Error reading "
477 "msdfs link %s: %s\n",
478 smb_fname->base_name,
481 DBG_ERR("Error reading "
482 "msdfs link %s: %s\n",
483 smb_fname->base_name,
489 link_target[referral_len] = '\0';
491 DBG_INFO("%s -> %s\n",
492 smb_fname->base_name,
495 if (!strnequal(link_target, "msdfs:", 6)) {
496 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
500 ret = sys_fstatat(fsp_get_pathref_fd(dirfsp),
501 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 atname, 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_nostream(frame, smb_fname_in);
1344 if (parent == NULL) {
1346 return NT_STATUS_NO_MEMORY;
1348 SET_STAT_INVALID(parent->st);
1350 p = strrchr_m(parent->base_name, '/'); /* Find final '/', if any */
1352 TALLOC_FREE(parent->base_name);
1353 parent->base_name = talloc_strdup(parent, ".");
1354 if (parent->base_name == NULL) {
1356 return NT_STATUS_NO_MEMORY;
1358 p = smb_fname_in->base_name;
1364 if (atname_out == NULL) {
1365 *parent_dir_out = talloc_move(mem_ctx, &parent);
1367 return NT_STATUS_OK;
1370 name = cp_smb_filename(frame, smb_fname_in);
1373 return NT_STATUS_NO_MEMORY;
1375 TALLOC_FREE(name->base_name);
1377 name->base_name = talloc_strdup(name, p);
1378 if (name->base_name == NULL) {
1380 return NT_STATUS_NO_MEMORY;
1383 *parent_dir_out = talloc_move(mem_ctx, &parent);
1384 *atname_out = talloc_move(*parent_dir_out, &name);
1386 return NT_STATUS_OK;
1390 * Implement the default fsctl operation.
1392 static bool vfswrap_logged_ioctl_message = false;
1394 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1395 struct files_struct *fsp,
1398 uint16_t req_flags, /* Needed for UNICODE ... */
1399 const uint8_t *_in_data,
1401 uint8_t **_out_data,
1402 uint32_t max_out_len,
1405 const char *in_data = (const char *)_in_data;
1406 char **out_data = (char **)_out_data;
1410 case FSCTL_SET_SPARSE:
1412 bool set_sparse = true;
1414 if (in_len >= 1 && in_data[0] == 0) {
1418 status = file_set_sparse(handle->conn, fsp, set_sparse);
1420 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1421 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1422 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1423 nt_errstr(status)));
1428 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1430 unsigned char objid[16];
1431 char *return_data = NULL;
1433 /* This should return the object-id on this file.
1434 * I think I'll make this be the inode+dev. JRA.
1437 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1438 fsp_fnum_dbg(fsp)));
1440 *out_len = MIN(max_out_len, 64);
1442 /* Hmmm, will this cause problems if less data asked for? */
1443 return_data = talloc_array(ctx, char, 64);
1444 if (return_data == NULL) {
1445 return NT_STATUS_NO_MEMORY;
1448 /* For backwards compatibility only store the dev/inode. */
1449 push_file_id_16(return_data, &fsp->file_id);
1450 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1451 push_file_id_16(return_data+32, &fsp->file_id);
1452 memset(return_data+48, 0, 16);
1453 *out_data = return_data;
1454 return NT_STATUS_OK;
1457 case FSCTL_GET_REPARSE_POINT:
1459 status = fsctl_get_reparse_point(
1460 fsp, ctx, out_data, max_out_len, out_len);
1464 case FSCTL_SET_REPARSE_POINT:
1466 status = fsctl_set_reparse_point(fsp, ctx, _in_data, in_len);
1470 case FSCTL_DELETE_REPARSE_POINT:
1472 status = fsctl_del_reparse_point(fsp, ctx, _in_data, in_len);
1476 case FSCTL_GET_SHADOW_COPY_DATA:
1479 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1480 * and return their volume names. If max_data_count is 16, then it is just
1481 * asking for the number of volumes and length of the combined names.
1483 * pdata is the data allocated by our caller, but that uses
1484 * total_data_count (which is 0 in our case) rather than max_data_count.
1485 * Allocate the correct amount and return the pointer to let
1486 * it be deallocated when we return.
1488 struct shadow_copy_data *shadow_data = NULL;
1489 bool labels = False;
1490 uint32_t labels_data_count = 0;
1492 char *cur_pdata = NULL;
1494 if (max_out_len < 16) {
1495 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1497 return NT_STATUS_INVALID_PARAMETER;
1500 if (max_out_len > 16) {
1504 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1505 if (shadow_data == NULL) {
1506 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1507 return NT_STATUS_NO_MEMORY;
1511 * Call the VFS routine to actually do the work.
1513 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1516 /* broken module didn't set errno on error */
1517 status = NT_STATUS_UNSUCCESSFUL;
1519 status = map_nt_error_from_unix(errno);
1520 if (NT_STATUS_EQUAL(status,
1521 NT_STATUS_NOT_SUPPORTED)) {
1525 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1526 "connectpath %s, failed - %s.\n",
1527 fsp->conn->connectpath,
1528 nt_errstr(status)));
1529 TALLOC_FREE(shadow_data);
1533 labels_data_count = (shadow_data->num_volumes * 2 *
1534 sizeof(SHADOW_COPY_LABEL)) + 2;
1539 *out_len = 12 + labels_data_count;
1542 if (max_out_len < *out_len) {
1543 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1544 max_out_len, *out_len));
1545 TALLOC_FREE(shadow_data);
1546 return NT_STATUS_BUFFER_TOO_SMALL;
1549 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1550 if (cur_pdata == NULL) {
1551 TALLOC_FREE(shadow_data);
1552 return NT_STATUS_NO_MEMORY;
1555 *out_data = cur_pdata;
1557 /* num_volumes 4 bytes */
1558 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1561 /* num_labels 4 bytes */
1562 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1565 /* needed_data_count 4 bytes */
1566 SIVAL(cur_pdata, 8, labels_data_count);
1570 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1571 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1572 if (labels && shadow_data->labels) {
1573 for (i=0; i<shadow_data->num_volumes; i++) {
1575 status = srvstr_push(cur_pdata, req_flags,
1576 cur_pdata, shadow_data->labels[i],
1577 2 * sizeof(SHADOW_COPY_LABEL),
1578 STR_UNICODE|STR_TERMINATE, &len);
1579 if (!NT_STATUS_IS_OK(status)) {
1580 TALLOC_FREE(*out_data);
1581 TALLOC_FREE(shadow_data);
1584 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1585 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1589 TALLOC_FREE(shadow_data);
1591 return NT_STATUS_OK;
1594 case FSCTL_FIND_FILES_BY_SID:
1596 /* pretend this succeeded -
1598 * we have to send back a list with all files owned by this SID
1600 * but I have to check that --metze
1604 struct dom_sid_buf buf;
1608 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1609 fsp_fnum_dbg(fsp)));
1612 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1613 return NT_STATUS_INVALID_PARAMETER;
1616 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1618 /* unknown 4 bytes: this is not the length of the sid :-( */
1619 /*unknown = IVAL(pdata,0);*/
1621 ret = sid_parse(_in_data + 4, sid_len, &sid);
1623 return NT_STATUS_INVALID_PARAMETER;
1625 DEBUGADD(10, ("for SID: %s\n",
1626 dom_sid_str_buf(&sid, &buf)));
1628 if (!sid_to_uid(&sid, &uid)) {
1629 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1630 dom_sid_str_buf(&sid, &buf),
1631 (unsigned long)sid_len));
1635 /* we can take a look at the find source :-)
1637 * find ./ -uid $uid -name '*' is what we need here
1640 * and send 4bytes len and then NULL terminated unicode strings
1643 * but I don't know how to deal with the paged results
1644 * (maybe we can hang the result anywhere in the fsp struct)
1646 * but I don't know how to deal with the paged results
1647 * (maybe we can hang the result anywhere in the fsp struct)
1649 * we don't send all files at once
1650 * and at the next we should *not* start from the beginning,
1651 * so we have to cache the result
1656 /* this works for now... */
1657 return NT_STATUS_OK;
1660 case FSCTL_QUERY_ALLOCATED_RANGES:
1662 /* FIXME: This is just a dummy reply, telling that all of the
1663 * file is allocated. MKS cp needs that.
1664 * Adding the real allocated ranges via FIEMAP on Linux
1665 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1666 * this FSCTL correct for sparse files.
1668 uint64_t offset, length;
1669 char *out_data_tmp = NULL;
1672 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1674 return NT_STATUS_INVALID_PARAMETER;
1677 if (max_out_len < 16) {
1678 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1680 return NT_STATUS_INVALID_PARAMETER;
1683 offset = BVAL(in_data,0);
1684 length = BVAL(in_data,8);
1686 if (offset + length < offset) {
1687 /* No 64-bit integer wrap. */
1688 return NT_STATUS_INVALID_PARAMETER;
1691 /* Shouldn't this be SMB_VFS_STAT ... ? */
1692 status = vfs_stat_fsp(fsp);
1693 if (!NT_STATUS_IS_OK(status)) {
1698 out_data_tmp = talloc_array(ctx, char, *out_len);
1699 if (out_data_tmp == NULL) {
1700 DEBUG(10, ("unable to allocate memory for response\n"));
1701 return NT_STATUS_NO_MEMORY;
1704 if (offset > fsp->fsp_name->st.st_ex_size ||
1705 fsp->fsp_name->st.st_ex_size == 0 ||
1707 memset(out_data_tmp, 0, *out_len);
1709 uint64_t end = offset + length;
1710 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1711 SBVAL(out_data_tmp, 0, 0);
1712 SBVAL(out_data_tmp, 8, end);
1715 *out_data = out_data_tmp;
1717 return NT_STATUS_OK;
1720 case FSCTL_IS_VOLUME_DIRTY:
1722 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1723 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1725 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1726 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1728 return NT_STATUS_INVALID_PARAMETER;
1733 * Only print once ... unfortunately there could be lots of
1734 * different FSCTLs that are called.
1736 if (!vfswrap_logged_ioctl_message) {
1737 vfswrap_logged_ioctl_message = true;
1738 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1739 __func__, function));
1743 return NT_STATUS_NOT_SUPPORTED;
1746 static bool vfswrap_is_offline(struct connection_struct *conn,
1747 const struct smb_filename *fname);
1749 struct vfswrap_get_dos_attributes_state {
1750 struct vfs_aio_state aio_state;
1751 connection_struct *conn;
1752 TALLOC_CTX *mem_ctx;
1753 struct tevent_context *ev;
1754 files_struct *dir_fsp;
1755 struct smb_filename *smb_fname;
1760 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq);
1762 static struct tevent_req *vfswrap_get_dos_attributes_send(
1763 TALLOC_CTX *mem_ctx,
1764 struct tevent_context *ev,
1765 struct vfs_handle_struct *handle,
1766 files_struct *dir_fsp,
1767 struct smb_filename *smb_fname)
1769 struct tevent_req *req = NULL;
1770 struct tevent_req *subreq = NULL;
1771 struct vfswrap_get_dos_attributes_state *state = NULL;
1773 req = tevent_req_create(mem_ctx, &state,
1774 struct vfswrap_get_dos_attributes_state);
1779 *state = (struct vfswrap_get_dos_attributes_state) {
1780 .conn = dir_fsp->conn,
1784 .smb_fname = smb_fname,
1787 if (!lp_store_dos_attributes(SNUM(dir_fsp->conn))) {
1788 DBG_ERR("%s: \"smbd async dosmode\" enabled, but "
1789 "\"store dos attributes\" is disabled\n",
1790 dir_fsp->conn->connectpath);
1791 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
1792 return tevent_req_post(req, ev);
1795 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1799 SAMBA_XATTR_DOS_ATTRIB,
1801 if (tevent_req_nomem(subreq, req)) {
1802 return tevent_req_post(req, ev);
1804 tevent_req_set_callback(subreq,
1805 vfswrap_get_dos_attributes_getxattr_done,
1811 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq)
1813 struct tevent_req *req =
1814 tevent_req_callback_data(subreq,
1816 struct vfswrap_get_dos_attributes_state *state =
1817 tevent_req_data(req,
1818 struct vfswrap_get_dos_attributes_state);
1820 DATA_BLOB blob = {0};
1822 char *tofree = NULL;
1823 char pathbuf[PATH_MAX+1];
1825 struct smb_filename smb_fname;
1829 xattr_size = SMB_VFS_GETXATTRAT_RECV(subreq,
1833 TALLOC_FREE(subreq);
1834 if (xattr_size == -1) {
1835 status = map_nt_error_from_unix(state->aio_state.error);
1837 if (state->as_root) {
1838 tevent_req_nterror(req, status);
1841 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1842 tevent_req_nterror(req, status);
1846 state->as_root = true;
1849 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1853 SAMBA_XATTR_DOS_ATTRIB,
1856 if (tevent_req_nomem(subreq, req)) {
1859 tevent_req_set_callback(subreq,
1860 vfswrap_get_dos_attributes_getxattr_done,
1865 blob.length = xattr_size;
1867 status = parse_dos_attribute_blob(state->smb_fname,
1870 if (!NT_STATUS_IS_OK(status)) {
1871 tevent_req_nterror(req, status);
1875 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
1876 state->smb_fname->base_name,
1881 if (pathlen == -1) {
1882 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1886 smb_fname = (struct smb_filename) {
1888 .st = state->smb_fname->st,
1889 .flags = state->smb_fname->flags,
1890 .twrp = state->smb_fname->twrp,
1893 offline = vfswrap_is_offline(state->conn, &smb_fname);
1895 state->dosmode |= FILE_ATTRIBUTE_OFFLINE;
1897 TALLOC_FREE(tofree);
1899 tevent_req_done(req);
1903 static NTSTATUS vfswrap_get_dos_attributes_recv(struct tevent_req *req,
1904 struct vfs_aio_state *aio_state,
1907 struct vfswrap_get_dos_attributes_state *state =
1908 tevent_req_data(req,
1909 struct vfswrap_get_dos_attributes_state);
1912 if (tevent_req_is_nterror(req, &status)) {
1913 tevent_req_received(req);
1917 *aio_state = state->aio_state;
1918 *dosmode = state->dosmode;
1919 tevent_req_received(req);
1920 return NT_STATUS_OK;
1923 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1924 struct files_struct *fsp,
1929 offline = vfswrap_is_offline(handle->conn, fsp->fsp_name);
1931 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1934 return fget_ea_dos_attribute(fsp, dosmode);
1937 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1938 struct files_struct *fsp,
1941 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1944 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1946 struct vfswrap_offload_read_state {
1950 static struct tevent_req *vfswrap_offload_read_send(
1951 TALLOC_CTX *mem_ctx,
1952 struct tevent_context *ev,
1953 struct vfs_handle_struct *handle,
1954 struct files_struct *fsp,
1960 struct tevent_req *req = NULL;
1961 struct vfswrap_offload_read_state *state = NULL;
1964 req = tevent_req_create(mem_ctx, &state,
1965 struct vfswrap_offload_read_state);
1970 status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1971 &vfswrap_offload_ctx);
1972 if (tevent_req_nterror(req, status)) {
1973 return tevent_req_post(req, ev);
1976 if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1977 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1978 return tevent_req_post(req, ev);
1981 status = vfs_offload_token_create_blob(state, fsp, fsctl,
1983 if (tevent_req_nterror(req, status)) {
1984 return tevent_req_post(req, ev);
1987 status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1989 if (tevent_req_nterror(req, status)) {
1990 return tevent_req_post(req, ev);
1993 tevent_req_done(req);
1994 return tevent_req_post(req, ev);
1997 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
1998 struct vfs_handle_struct *handle,
1999 TALLOC_CTX *mem_ctx,
2004 struct vfswrap_offload_read_state *state = tevent_req_data(
2005 req, struct vfswrap_offload_read_state);
2008 if (tevent_req_is_nterror(req, &status)) {
2009 tevent_req_received(req);
2015 token->length = state->token.length;
2016 token->data = talloc_move(mem_ctx, &state->token.data);
2018 tevent_req_received(req);
2019 return NT_STATUS_OK;
2022 struct vfswrap_offload_write_state {
2024 bool read_lck_locked;
2025 bool write_lck_locked;
2027 struct tevent_context *src_ev;
2028 struct files_struct *src_fsp;
2030 struct tevent_context *dst_ev;
2031 struct files_struct *dst_fsp;
2036 size_t next_io_size;
2039 static void vfswrap_offload_write_cleanup(struct tevent_req *req,
2040 enum tevent_req_state req_state)
2042 struct vfswrap_offload_write_state *state = tevent_req_data(
2043 req, struct vfswrap_offload_write_state);
2046 if (state->dst_fsp == NULL) {
2050 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2052 state->dst_fsp = NULL;
2055 static NTSTATUS vfswrap_offload_copy_file_range(struct tevent_req *req);
2056 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
2058 static struct tevent_req *vfswrap_offload_write_send(
2059 struct vfs_handle_struct *handle,
2060 TALLOC_CTX *mem_ctx,
2061 struct tevent_context *ev,
2064 off_t transfer_offset,
2065 struct files_struct *dest_fsp,
2069 struct tevent_req *req;
2070 struct vfswrap_offload_write_state *state = NULL;
2071 /* off_t is signed! */
2072 off_t max_offset = INT64_MAX - to_copy;
2073 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
2074 files_struct *src_fsp = NULL;
2078 req = tevent_req_create(mem_ctx, &state,
2079 struct vfswrap_offload_write_state);
2084 *state = (struct vfswrap_offload_write_state) {
2086 .src_off = transfer_offset,
2088 .dst_fsp = dest_fsp,
2089 .dst_off = dest_off,
2091 .remaining = to_copy,
2094 tevent_req_set_cleanup_fn(req, vfswrap_offload_write_cleanup);
2097 case FSCTL_SRV_COPYCHUNK:
2098 case FSCTL_SRV_COPYCHUNK_WRITE:
2101 case FSCTL_OFFLOAD_WRITE:
2102 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
2103 return tevent_req_post(req, ev);
2105 case FSCTL_DUP_EXTENTS_TO_FILE:
2106 DBG_DEBUG("COW clones not supported by vfs_default\n");
2107 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2108 return tevent_req_post(req, ev);
2111 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2112 return tevent_req_post(req, ev);
2116 * From here on we assume a copy-chunk fsctl
2120 tevent_req_done(req);
2121 return tevent_req_post(req, ev);
2124 if (state->src_off > max_offset) {
2126 * Protect integer checks below.
2128 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2129 return tevent_req_post(req, ev);
2131 if (state->src_off < 0) {
2133 * Protect integer checks below.
2135 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2136 return tevent_req_post(req, ev);
2138 if (state->dst_off > max_offset) {
2140 * Protect integer checks below.
2142 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2143 return tevent_req_post(req, ev);
2145 if (state->dst_off < 0) {
2147 * Protect integer checks below.
2149 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2150 return tevent_req_post(req, ev);
2153 status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
2155 if (tevent_req_nterror(req, status)) {
2156 return tevent_req_post(req, ev);
2159 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
2161 status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
2162 if (!NT_STATUS_IS_OK(status)) {
2163 tevent_req_nterror(req, status);
2164 return tevent_req_post(req, ev);
2167 ok = change_to_user_and_service_by_fsp(src_fsp);
2169 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2170 return tevent_req_post(req, ev);
2173 state->src_ev = src_fsp->conn->sconn->ev_ctx;
2174 state->src_fsp = src_fsp;
2176 status = vfs_stat_fsp(src_fsp);
2177 if (tevent_req_nterror(req, status)) {
2178 return tevent_req_post(req, ev);
2181 if (src_fsp->fsp_name->st.st_ex_size < state->src_off + to_copy) {
2183 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
2184 * If the SourceOffset or SourceOffset + Length extends beyond
2185 * the end of file, the server SHOULD<240> treat this as a
2186 * STATUS_END_OF_FILE error.
2188 * <240> Section 3.3.5.15.6: Windows servers will return
2189 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
2191 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
2192 return tevent_req_post(req, ev);
2195 status = vfswrap_offload_copy_file_range(req);
2196 if (NT_STATUS_IS_OK(status)) {
2197 tevent_req_done(req);
2198 return tevent_req_post(req, ev);
2200 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2201 tevent_req_nterror(req, status);
2202 return tevent_req_post(req, ev);
2205 state->buf = talloc_array(state, uint8_t, num);
2206 if (tevent_req_nomem(state->buf, req)) {
2207 return tevent_req_post(req, ev);
2210 status = vfswrap_offload_write_loop(req);
2211 if (!NT_STATUS_IS_OK(status)) {
2212 tevent_req_nterror(req, status);
2213 return tevent_req_post(req, ev);
2219 static NTSTATUS vfswrap_offload_copy_file_range(struct tevent_req *req)
2221 struct vfswrap_offload_write_state *state = tevent_req_data(
2222 req, struct vfswrap_offload_write_state);
2223 struct lock_struct lck;
2228 static bool try_copy_file_range = true;
2230 if (!try_copy_file_range) {
2231 return NT_STATUS_MORE_PROCESSING_REQUIRED;
2234 same_file = file_id_equal(&state->src_fsp->file_id,
2235 &state->dst_fsp->file_id);
2237 sys_io_ranges_overlap(state->remaining,
2242 return NT_STATUS_MORE_PROCESSING_REQUIRED;
2245 if (fsp_is_alternate_stream(state->src_fsp) ||
2246 fsp_is_alternate_stream(state->dst_fsp))
2248 return NT_STATUS_MORE_PROCESSING_REQUIRED;
2251 init_strict_lock_struct(state->src_fsp,
2252 state->src_fsp->op->global->open_persistent_id,
2256 lp_posix_cifsu_locktype(state->src_fsp),
2259 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
2263 return NT_STATUS_FILE_LOCK_CONFLICT;
2266 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2268 return NT_STATUS_INTERNAL_ERROR;
2271 init_strict_lock_struct(state->dst_fsp,
2272 state->dst_fsp->op->global->open_persistent_id,
2276 lp_posix_cifsu_locktype(state->dst_fsp),
2279 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
2283 return NT_STATUS_FILE_LOCK_CONFLICT;
2286 while (state->remaining > 0) {
2287 nwritten = copy_file_range(fsp_get_io_fd(state->src_fsp),
2289 fsp_get_io_fd(state->dst_fsp),
2293 if (nwritten == -1) {
2294 DBG_DEBUG("copy_file_range src [%s]:[%jd] dst [%s]:[%jd] "
2295 "n [%jd] failed: %s\n",
2296 fsp_str_dbg(state->src_fsp),
2297 (intmax_t)state->src_off,
2298 fsp_str_dbg(state->dst_fsp),
2299 (intmax_t)state->dst_off,
2300 (intmax_t)state->remaining,
2305 try_copy_file_range = false;
2306 status = NT_STATUS_MORE_PROCESSING_REQUIRED;
2309 status = NT_STATUS_MORE_PROCESSING_REQUIRED;
2312 status = map_nt_error_from_unix(errno);
2313 if (NT_STATUS_EQUAL(
2315 NT_STATUS_MORE_PROCESSING_REQUIRED))
2317 /* Avoid triggering the fallback */
2318 status = NT_STATUS_INTERNAL_ERROR;
2325 if (state->remaining < nwritten) {
2326 DBG_DEBUG("copy_file_range src [%s] dst [%s] "
2327 "n [%jd] remaining [%jd]\n",
2328 fsp_str_dbg(state->src_fsp),
2329 fsp_str_dbg(state->dst_fsp),
2331 (intmax_t)state->remaining);
2332 return NT_STATUS_INTERNAL_ERROR;
2335 if (nwritten == 0) {
2338 state->copied += nwritten;
2339 state->remaining -= nwritten;
2343 * Tell the req cleanup function there's no need to call
2344 * change_to_user_and_service_by_fsp() on the dst handle.
2346 state->dst_fsp = NULL;
2347 return NT_STATUS_OK;
2350 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
2352 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
2354 struct vfswrap_offload_write_state *state = tevent_req_data(
2355 req, struct vfswrap_offload_write_state);
2356 struct tevent_req *subreq = NULL;
2357 struct lock_struct read_lck;
2361 * This is called under the context of state->src_fsp.
2364 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
2366 init_strict_lock_struct(state->src_fsp,
2367 state->src_fsp->op->global->open_persistent_id,
2369 state->next_io_size,
2371 lp_posix_cifsu_locktype(state->src_fsp),
2374 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
2378 return NT_STATUS_FILE_LOCK_CONFLICT;
2381 subreq = SMB_VFS_PREAD_SEND(state,
2385 state->next_io_size,
2387 if (subreq == NULL) {
2388 return NT_STATUS_NO_MEMORY;
2390 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
2392 return NT_STATUS_OK;
2395 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
2397 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
2399 struct tevent_req *req = tevent_req_callback_data(
2400 subreq, struct tevent_req);
2401 struct vfswrap_offload_write_state *state = tevent_req_data(
2402 req, struct vfswrap_offload_write_state);
2403 struct vfs_aio_state aio_state;
2404 struct lock_struct write_lck;
2408 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
2409 TALLOC_FREE(subreq);
2411 DBG_ERR("read failed: %s\n", strerror(aio_state.error));
2412 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2415 if (nread != state->next_io_size) {
2416 DBG_ERR("Short read, only %zd of %zu\n",
2417 nread, state->next_io_size);
2418 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2422 state->src_off += nread;
2424 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2426 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2430 init_strict_lock_struct(state->dst_fsp,
2431 state->dst_fsp->op->global->open_persistent_id,
2433 state->next_io_size,
2435 lp_posix_cifsu_locktype(state->dst_fsp),
2438 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
2442 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
2446 subreq = SMB_VFS_PWRITE_SEND(state,
2450 state->next_io_size,
2452 if (subreq == NULL) {
2453 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2456 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
2459 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
2461 struct tevent_req *req = tevent_req_callback_data(
2462 subreq, struct tevent_req);
2463 struct vfswrap_offload_write_state *state = tevent_req_data(
2464 req, struct vfswrap_offload_write_state);
2465 struct vfs_aio_state aio_state;
2470 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
2471 TALLOC_FREE(subreq);
2472 if (nwritten == -1) {
2473 DBG_ERR("write failed: %s\n", strerror(aio_state.error));
2474 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2477 if (nwritten != state->next_io_size) {
2478 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
2479 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2483 state->dst_off += nwritten;
2485 if (state->remaining < nwritten) {
2486 /* Paranoia check */
2487 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2490 state->copied += nwritten;
2491 state->remaining -= nwritten;
2492 if (state->remaining == 0) {
2493 tevent_req_done(req);
2497 ok = change_to_user_and_service_by_fsp(state->src_fsp);
2499 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2503 status = vfswrap_offload_write_loop(req);
2504 if (!NT_STATUS_IS_OK(status)) {
2505 tevent_req_nterror(req, status);
2512 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
2513 struct tevent_req *req,
2516 struct vfswrap_offload_write_state *state = tevent_req_data(
2517 req, struct vfswrap_offload_write_state);
2520 if (tevent_req_is_nterror(req, &status)) {
2521 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
2523 tevent_req_received(req);
2527 *copied = state->copied;
2528 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
2529 tevent_req_received(req);
2531 return NT_STATUS_OK;
2534 static NTSTATUS vfswrap_fget_compression(struct vfs_handle_struct *handle,
2535 TALLOC_CTX *mem_ctx,
2536 struct files_struct *fsp,
2537 uint16_t *_compression_fmt)
2539 return NT_STATUS_INVALID_DEVICE_REQUEST;
2542 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
2543 TALLOC_CTX *mem_ctx,
2544 struct files_struct *fsp,
2545 uint16_t compression_fmt)
2547 return NT_STATUS_INVALID_DEVICE_REQUEST;
2550 /********************************************************************
2551 Given a stat buffer return the allocated size on disk, taking into
2552 account sparse files.
2553 ********************************************************************/
2554 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
2555 struct files_struct *fsp,
2556 const SMB_STRUCT_STAT *sbuf)
2560 START_PROFILE(syscall_get_alloc_size);
2562 if(S_ISDIR(sbuf->st_ex_mode)) {
2567 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2568 /* The type of st_blocksize is blkcnt_t which *MUST* be
2569 signed (according to POSIX) and can be less than 64-bits.
2570 Ensure when we're converting to 64 bits wide we don't
2572 #if defined(SIZEOF_BLKCNT_T_8)
2573 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2574 #elif defined(SIZEOF_BLKCNT_T_4)
2576 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2577 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2580 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2584 * Some file systems do not allocate a block for very
2585 * small files. But for non-empty file should report a
2589 uint64_t filesize = get_file_size_stat(sbuf);
2591 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2595 result = get_file_size_stat(sbuf);
2598 if (fsp && fsp->initial_allocation_size)
2599 result = MAX(result,fsp->initial_allocation_size);
2601 result = smb_roundup(handle->conn, result);
2604 END_PROFILE(syscall_get_alloc_size);
2608 static int vfswrap_unlinkat(vfs_handle_struct *handle,
2609 struct files_struct *dirfsp,
2610 const struct smb_filename *smb_fname,
2615 START_PROFILE(syscall_unlinkat);
2617 if (is_named_stream(smb_fname)) {
2621 result = unlinkat(fsp_get_pathref_fd(dirfsp),
2622 smb_fname->base_name,
2626 END_PROFILE(syscall_unlinkat);
2630 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2634 START_PROFILE(syscall_fchmod);
2636 if (!fsp->fsp_flags.is_pathref) {
2637 result = fchmod(fsp_get_io_fd(fsp), mode);
2638 END_PROFILE(syscall_fchmod);
2642 if (fsp->fsp_flags.have_proc_fds) {
2643 int fd = fsp_get_pathref_fd(fsp);
2644 const char *p = NULL;
2647 p = sys_proc_fd_path(fd, buf, sizeof(buf));
2649 result = chmod(p, mode);
2653 END_PROFILE(syscall_fchmod);
2658 * This is no longer a handle based call.
2660 result = chmod(fsp->fsp_name->base_name, mode);
2662 END_PROFILE(syscall_fchmod);
2666 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2671 START_PROFILE(syscall_fchown);
2672 if (!fsp->fsp_flags.is_pathref) {
2673 result = fchown(fsp_get_io_fd(fsp), uid, gid);
2674 END_PROFILE(syscall_fchown);
2678 if (fsp->fsp_flags.have_proc_fds) {
2679 int fd = fsp_get_pathref_fd(fsp);
2680 const char *p = NULL;
2683 p = sys_proc_fd_path(fd, buf, sizeof(buf));
2685 result = chown(p, uid, gid);
2689 END_PROFILE(syscall_fchown);
2694 * This is no longer a handle based call.
2696 result = chown(fsp->fsp_name->base_name, uid, gid);
2697 END_PROFILE(syscall_fchown);
2705 static int vfswrap_lchown(vfs_handle_struct *handle,
2706 const struct smb_filename *smb_fname,
2712 START_PROFILE(syscall_lchown);
2713 result = lchown(smb_fname->base_name, uid, gid);
2714 END_PROFILE(syscall_lchown);
2718 static int vfswrap_chdir(vfs_handle_struct *handle,
2719 const struct smb_filename *smb_fname)
2723 START_PROFILE(syscall_chdir);
2724 result = chdir(smb_fname->base_name);
2725 END_PROFILE(syscall_chdir);
2729 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2733 struct smb_filename *smb_fname = NULL;
2735 START_PROFILE(syscall_getwd);
2736 result = sys_getwd();
2737 END_PROFILE(syscall_getwd);
2739 if (result == NULL) {
2742 smb_fname = synthetic_smb_fname(ctx,
2749 * sys_getwd() *always* returns malloced memory.
2750 * We must free here to avoid leaks:
2751 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2757 /*********************************************************************
2758 nsec timestamp resolution call. Convert down to whatever the underlying
2759 system will support.
2760 **********************************************************************/
2762 static int vfswrap_fntimes(vfs_handle_struct *handle,
2764 struct smb_file_time *ft)
2767 struct timespec ts[2];
2768 struct timespec *times = NULL;
2770 START_PROFILE(syscall_fntimes);
2772 if (fsp_is_alternate_stream(fsp)) {
2778 if (is_omit_timespec(&ft->atime)) {
2779 ft->atime = fsp->fsp_name->st.st_ex_atime;
2782 if (is_omit_timespec(&ft->mtime)) {
2783 ft->mtime = fsp->fsp_name->st.st_ex_mtime;
2786 if (!is_omit_timespec(&ft->create_time)) {
2787 set_create_timespec_ea(fsp,
2791 if ((timespec_compare(&ft->atime,
2792 &fsp->fsp_name->st.st_ex_atime) == 0) &&
2793 (timespec_compare(&ft->mtime,
2794 &fsp->fsp_name->st.st_ex_mtime) == 0)) {
2806 if (!fsp->fsp_flags.is_pathref) {
2807 result = futimens(fsp_get_io_fd(fsp), times);
2811 if (fsp->fsp_flags.have_proc_fds) {
2812 int fd = fsp_get_pathref_fd(fsp);
2813 const char *p = NULL;
2816 p = sys_proc_fd_path(fd, buf, sizeof(buf));
2819 * The dirfd argument of utimensat is ignored when
2820 * pathname is an absolute path
2822 result = utimensat(AT_FDCWD, p, times, 0);
2831 * The fd is a pathref (opened with O_PATH) and there isn't fd to
2832 * path translation mechanism. Fallback to path based call.
2834 result = utimensat(AT_FDCWD, fsp->fsp_name->base_name, times, 0);
2837 END_PROFILE(syscall_fntimes);
2843 /*********************************************************************
2844 A version of ftruncate that will write the space on disk if strict
2846 **********************************************************************/
2848 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2850 off_t space_to_write;
2851 uint64_t space_avail;
2852 uint64_t bsize,dfree,dsize;
2855 SMB_STRUCT_STAT *pst;
2858 ok = vfs_valid_pwrite_range(len, 0);
2864 status = vfs_stat_fsp(fsp);
2865 if (!NT_STATUS_IS_OK(status)) {
2868 pst = &fsp->fsp_name->st;
2871 if (S_ISFIFO(pst->st_ex_mode))
2875 if (pst->st_ex_size == len)
2878 /* Shrink - just ftruncate. */
2879 if (pst->st_ex_size > len)
2880 return ftruncate(fsp_get_io_fd(fsp), len);
2882 space_to_write = len - pst->st_ex_size;
2884 /* for allocation try fallocate first. This can fail on some
2885 platforms e.g. when the filesystem doesn't support it and no
2886 emulation is being done by the libc (like on AIX with JFS1). In that
2887 case we do our own emulation. fallocate implementations can
2888 return ENOTSUP or EINVAL in cases like that. */
2889 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2890 if (ret == -1 && errno == ENOSPC) {
2896 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2897 "error %d. Falling back to slow manual allocation\n", errno));
2899 /* available disk space is enough or not? */
2901 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2902 /* space_avail is 1k blocks */
2903 if (space_avail == (uint64_t)-1 ||
2904 ((uint64_t)space_to_write/1024 > space_avail) ) {
2909 /* Write out the real space on disk. */
2910 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2918 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2921 SMB_STRUCT_STAT *pst;
2925 START_PROFILE(syscall_ftruncate);
2927 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->fsp_flags.is_sparse) {
2928 result = strict_allocate_ftruncate(handle, fsp, len);
2929 END_PROFILE(syscall_ftruncate);
2933 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2934 ftruncate if the system supports it. Then I discovered that
2935 you can have some filesystems that support ftruncate
2936 expansion and some that don't! On Linux fat can't do
2937 ftruncate extend but ext2 can. */
2939 result = ftruncate(fsp_get_io_fd(fsp), len);
2941 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2942 extend a file with ftruncate. Provide alternate implementation
2945 /* Do an fstat to see if the file is longer than the requested
2946 size in which case the ftruncate above should have
2947 succeeded or shorter, in which case seek to len - 1 and
2948 write 1 byte of zero */
2949 status = vfs_stat_fsp(fsp);
2950 if (!NT_STATUS_IS_OK(status)) {
2954 /* We need to update the files_struct after successful ftruncate */
2959 pst = &fsp->fsp_name->st;
2962 if (S_ISFIFO(pst->st_ex_mode)) {
2968 if (pst->st_ex_size == len) {
2973 if (pst->st_ex_size > len) {
2974 /* the ftruncate should have worked */
2978 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2986 END_PROFILE(syscall_ftruncate);
2990 static int vfswrap_fallocate(vfs_handle_struct *handle,
2998 START_PROFILE(syscall_fallocate);
3000 result = sys_posix_fallocate(fsp_get_io_fd(fsp), offset, len);
3002 * posix_fallocate returns 0 on success, errno on error
3003 * and doesn't set errno. Make it behave like fallocate()
3004 * which returns -1, and sets errno on failure.
3011 /* sys_fallocate handles filtering of unsupported mode flags */
3012 result = sys_fallocate(fsp_get_io_fd(fsp), mode, offset, len);
3014 END_PROFILE(syscall_fallocate);
3018 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
3022 START_PROFILE(syscall_fcntl_lock);
3024 if (fsp->fsp_flags.use_ofd_locks) {
3025 op = map_process_lock_to_ofd_lock(op);
3028 result = fcntl_lock(fsp_get_io_fd(fsp), op, offset, count, type);
3029 END_PROFILE(syscall_fcntl_lock);
3033 static int vfswrap_filesystem_sharemode(vfs_handle_struct *handle,
3035 uint32_t share_access,
3036 uint32_t access_mask)
3042 static int vfswrap_fcntl(vfs_handle_struct *handle, files_struct *fsp, int cmd,
3046 va_list dup_cmd_arg;
3050 START_PROFILE(syscall_fcntl);
3052 va_copy(dup_cmd_arg, cmd_arg);
3058 #if defined(HAVE_OFD_LOCKS)
3063 #if defined(HAVE_F_OWNER_EX)
3067 #if defined(HAVE_RW_HINTS)
3070 case F_GET_FILE_RW_HINT:
3071 case F_SET_FILE_RW_HINT:
3073 argp = va_arg(dup_cmd_arg, void *);
3074 result = sys_fcntl_ptr(fsp_get_io_fd(fsp), cmd, argp);
3077 val = va_arg(dup_cmd_arg, int);
3078 result = sys_fcntl_int(fsp_get_io_fd(fsp), cmd, val);
3081 va_end(dup_cmd_arg);
3083 END_PROFILE(syscall_fcntl);
3087 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
3092 START_PROFILE(syscall_fcntl_getlock);
3094 if (fsp->fsp_flags.use_ofd_locks) {
3095 op = map_process_lock_to_ofd_lock(op);
3098 result = fcntl_getlock(fsp_get_io_fd(fsp), op, poffset, pcount, ptype, ppid);
3099 END_PROFILE(syscall_fcntl_getlock);
3103 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
3108 START_PROFILE(syscall_linux_setlease);
3110 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
3111 result = linux_setlease(fsp_get_io_fd(fsp), leasetype);
3115 END_PROFILE(syscall_linux_setlease);
3119 static int vfswrap_symlinkat(vfs_handle_struct *handle,
3120 const struct smb_filename *link_target,
3121 struct files_struct *dirfsp,
3122 const struct smb_filename *new_smb_fname)
3126 START_PROFILE(syscall_symlinkat);
3128 result = symlinkat(link_target->base_name,
3129 fsp_get_pathref_fd(dirfsp),
3130 new_smb_fname->base_name);
3131 END_PROFILE(syscall_symlinkat);
3135 static int vfswrap_readlinkat(vfs_handle_struct *handle,
3136 const struct files_struct *dirfsp,
3137 const struct smb_filename *smb_fname,
3143 START_PROFILE(syscall_readlinkat);
3145 result = readlinkat(fsp_get_pathref_fd(dirfsp),
3146 smb_fname->base_name,
3150 END_PROFILE(syscall_readlinkat);
3154 static int vfswrap_linkat(vfs_handle_struct *handle,
3155 files_struct *srcfsp,
3156 const struct smb_filename *old_smb_fname,
3157 files_struct *dstfsp,
3158 const struct smb_filename *new_smb_fname,
3163 START_PROFILE(syscall_linkat);
3165 result = linkat(fsp_get_pathref_fd(srcfsp),
3166 old_smb_fname->base_name,
3167 fsp_get_pathref_fd(dstfsp),
3168 new_smb_fname->base_name,
3171 END_PROFILE(syscall_linkat);
3175 static int vfswrap_mknodat(vfs_handle_struct *handle,
3176 files_struct *dirfsp,
3177 const struct smb_filename *smb_fname,
3183 START_PROFILE(syscall_mknodat);
3185 result = sys_mknodat(fsp_get_pathref_fd(dirfsp),
3186 smb_fname->base_name,
3190 END_PROFILE(syscall_mknodat);
3194 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
3196 const struct smb_filename *smb_fname)
3199 struct smb_filename *result_fname = NULL;
3201 START_PROFILE(syscall_realpath);
3202 result = sys_realpath(smb_fname->base_name);
3203 END_PROFILE(syscall_realpath);
3205 result_fname = synthetic_smb_fname(ctx,
3213 return result_fname;
3216 static int vfswrap_fchflags(vfs_handle_struct *handle,
3217 struct files_struct *fsp,
3220 #ifdef HAVE_FCHFLAGS
3221 int fd = fsp_get_pathref_fd(fsp);
3223 if (!fsp->fsp_flags.is_pathref) {
3224 return fchflags(fd, flags);
3227 if (fsp->fsp_flags.have_proc_fds) {
3228 const char *p = NULL;
3231 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3236 return chflags(p, flags);
3240 * This is no longer a handle based call.
3242 return chflags(fsp->fsp_name->base_name, flags);
3249 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
3250 const SMB_STRUCT_STAT *sbuf)
3254 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
3258 key.devid = sbuf->st_ex_dev;
3259 key.inode = sbuf->st_ex_ino;
3260 /* key.extid is unused by default. */
3265 static uint64_t vfswrap_fs_file_id(struct vfs_handle_struct *handle,
3266 const SMB_STRUCT_STAT *psbuf)
3270 if (!(psbuf->st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)) {
3271 return psbuf->st_ex_file_id;
3274 if (handle->conn->base_share_dev == psbuf->st_ex_dev) {
3275 return (uint64_t)psbuf->st_ex_ino;
3279 file_id = ((psbuf->st_ex_ino) & UINT32_MAX);
3282 file_id |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32;
3287 static NTSTATUS vfswrap_fstreaminfo(vfs_handle_struct *handle,
3288 struct files_struct *fsp,
3289 TALLOC_CTX *mem_ctx,
3290 unsigned int *pnum_streams,
3291 struct stream_struct **pstreams)
3293 struct stream_struct *tmp_streams = NULL;
3294 unsigned int num_streams = *pnum_streams;
3295 struct stream_struct *streams = *pstreams;
3298 if (fsp->fsp_flags.is_directory) {
3300 * No default streams on directories
3304 status = vfs_stat_fsp(fsp);
3305 if (!NT_STATUS_IS_OK(status)) {
3309 if (num_streams + 1 < 1) {
3311 return NT_STATUS_INVALID_PARAMETER;
3314 tmp_streams = talloc_realloc(mem_ctx,
3316 struct stream_struct,
3318 if (tmp_streams == NULL) {
3319 return NT_STATUS_NO_MEMORY;
3321 tmp_streams[num_streams].name = talloc_strdup(tmp_streams, "::$DATA");
3322 if (tmp_streams[num_streams].name == NULL) {
3323 return NT_STATUS_NO_MEMORY;
3325 tmp_streams[num_streams].size = fsp->fsp_name->st.st_ex_size;
3326 tmp_streams[num_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(
3329 &fsp->fsp_name->st);
3332 *pnum_streams = num_streams;
3333 *pstreams = tmp_streams;
3335 return NT_STATUS_OK;
3338 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
3339 const struct smb_filename *path,
3341 TALLOC_CTX *mem_ctx,
3345 * Don't fall back to get_real_filename so callers can differentiate
3346 * between a full directory scan and an actual case-insensitive stat.
3352 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
3353 const struct smb_filename *smb_fname)
3355 return handle->conn->connectpath;
3358 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
3359 struct byte_range_lock *br_lck,
3360 struct lock_struct *plock)
3362 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3364 /* Note: blr is not used in the default implementation. */
3365 return brl_lock_windows_default(br_lck, plock);
3368 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
3369 struct byte_range_lock *br_lck,
3370 const struct lock_struct *plock)
3372 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3374 return brl_unlock_windows_default(br_lck, plock);
3377 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
3379 struct lock_struct *plock)
3381 SMB_ASSERT(plock->lock_type == READ_LOCK ||
3382 plock->lock_type == WRITE_LOCK);
3384 return strict_lock_check_default(fsp, plock);
3387 /* NT ACL operations. */
3389 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
3391 uint32_t security_info,
3392 TALLOC_CTX *mem_ctx,
3393 struct security_descriptor **ppdesc)
3397 START_PROFILE(fget_nt_acl);
3398 result = posix_fget_nt_acl(fsp, security_info,
3400 END_PROFILE(fget_nt_acl);
3404 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
3408 START_PROFILE(fset_nt_acl);
3409 result = set_nt_acl(fsp, security_info_sent, psd);
3410 END_PROFILE(fset_nt_acl);
3414 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
3415 struct smb_filename *file,
3416 struct security_acl *sacl,
3417 uint32_t access_requested,
3418 uint32_t access_denied)
3420 return NT_STATUS_OK; /* Nothing to do here ... */
3423 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
3425 SMB_ACL_TYPE_T type,
3426 TALLOC_CTX *mem_ctx)
3428 return sys_acl_get_fd(handle, fsp, type, mem_ctx);
3431 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle,
3433 SMB_ACL_TYPE_T type,
3436 return sys_acl_set_fd(handle, fsp, type, theacl);
3439 static int vfswrap_sys_acl_delete_def_fd(vfs_handle_struct *handle,
3442 return sys_acl_delete_def_fd(handle, fsp);
3445 /****************************************************************
3446 Extended attribute operations.
3447 *****************************************************************/
3449 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle,
3450 struct files_struct *fsp,
3455 int fd = fsp_get_pathref_fd(fsp);
3457 if (!fsp->fsp_flags.is_pathref) {
3458 return fgetxattr(fd, name, value, size);
3461 if (fsp->fsp_flags.have_proc_fds) {
3462 const char *p = NULL;
3465 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3470 return getxattr(p, name, value, size);
3474 * This is no longer a handle based call.
3476 return getxattr(fsp->fsp_name->base_name, name, value, size);
3479 struct vfswrap_getxattrat_state {
3480 struct tevent_context *ev;
3481 struct vfs_handle_struct *handle;
3482 files_struct *dir_fsp;
3483 const struct smb_filename *smb_fname;
3486 * The following variables are talloced off "state" which is protected
3487 * by a destructor and thus are guaranteed to be safe to be used in the
3488 * job function in the worker thread.
3491 const char *xattr_name;
3492 uint8_t *xattr_value;
3493 struct security_unix_token *token;
3496 struct vfs_aio_state vfs_aio_state;
3497 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
3500 static int vfswrap_getxattrat_state_destructor(
3501 struct vfswrap_getxattrat_state *state)
3506 static void vfswrap_getxattrat_do_sync(struct tevent_req *req);
3507 static void vfswrap_getxattrat_do_async(void *private_data);
3508 static void vfswrap_getxattrat_done(struct tevent_req *subreq);
3510 static struct tevent_req *vfswrap_getxattrat_send(
3511 TALLOC_CTX *mem_ctx,
3512 struct tevent_context *ev,
3513 struct vfs_handle_struct *handle,
3514 files_struct *dir_fsp,
3515 const struct smb_filename *smb_fname,
3516 const char *xattr_name,
3519 struct tevent_req *req = NULL;
3520 struct tevent_req *subreq = NULL;
3521 struct vfswrap_getxattrat_state *state = NULL;
3522 size_t max_threads = 0;
3523 bool have_per_thread_cwd = false;
3524 bool have_per_thread_creds = false;
3525 bool do_async = false;
3527 req = tevent_req_create(mem_ctx, &state,
3528 struct vfswrap_getxattrat_state);
3532 *state = (struct vfswrap_getxattrat_state) {
3536 .smb_fname = smb_fname,
3539 max_threads = pthreadpool_tevent_max_threads(dir_fsp->conn->sconn->pool);
3540 if (max_threads >= 1) {
3542 * We need a non sync threadpool!
3544 have_per_thread_cwd = per_thread_cwd_supported();
3546 #ifdef HAVE_LINUX_THREAD_CREDENTIALS
3547 have_per_thread_creds = true;
3549 if (have_per_thread_cwd && have_per_thread_creds) {
3553 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat, profile_p,
3554 state->profile_bytes, 0);
3556 if (fsp_get_pathref_fd(dir_fsp) == -1) {
3557 DBG_ERR("Need a valid directory fd\n");
3558 tevent_req_error(req, EINVAL);
3559 return tevent_req_post(req, ev);
3562 if (alloc_hint > 0) {
3563 state->xattr_value = talloc_zero_array(state,
3566 if (tevent_req_nomem(state->xattr_value, req)) {
3567 return tevent_req_post(req, ev);
3572 vfswrap_getxattrat_do_sync(req);
3573 return tevent_req_post(req, ev);
3577 * Now allocate all parameters from a memory context that won't go away
3578 * no matter what. These paremeters will get used in threads and we
3579 * can't reliably cancel threads, so all buffers passed to the threads
3580 * must not be freed before all referencing threads terminate.
3583 state->name = talloc_strdup(state, smb_fname->base_name);
3584 if (tevent_req_nomem(state->name, req)) {
3585 return tevent_req_post(req, ev);
3588 state->xattr_name = talloc_strdup(state, xattr_name);
3589 if (tevent_req_nomem(state->xattr_name, req)) {
3590 return tevent_req_post(req, ev);
3594 * This is a hot codepath so at first glance one might think we should
3595 * somehow optimize away the token allocation and do a
3596 * talloc_reference() or similar black magic instead. But due to the
3597 * talloc_stackframe pool per SMB2 request this should be a simple copy
3598 * without a malloc in most cases.
3600 if (geteuid() == sec_initial_uid()) {
3601 state->token = root_unix_token(state);
3603 state->token = copy_unix_token(
3605 dir_fsp->conn->session_info->unix_token);
3607 if (tevent_req_nomem(state->token, req)) {
3608 return tevent_req_post(req, ev);
3611 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3613 subreq = pthreadpool_tevent_job_send(
3616 dir_fsp->conn->sconn->pool,
3617 vfswrap_getxattrat_do_async,
3619 if (tevent_req_nomem(subreq, req)) {
3620 return tevent_req_post(req, ev);
3622 tevent_req_set_callback(subreq, vfswrap_getxattrat_done, req);
3624 talloc_set_destructor(state, vfswrap_getxattrat_state_destructor);
3629 static void vfswrap_getxattrat_do_sync(struct tevent_req *req)
3631 struct vfswrap_getxattrat_state *state = tevent_req_data(
3632 req, struct vfswrap_getxattrat_state);
3633 struct files_struct *fsp = metadata_fsp(state->smb_fname->fsp);
3635 state->xattr_size = vfswrap_fgetxattr(state->handle,
3639 talloc_array_length(state->xattr_value));
3640 if (state->xattr_size == -1) {
3641 tevent_req_error(req, errno);
3645 tevent_req_done(req);
3649 static void vfswrap_getxattrat_do_async(void *private_data)
3651 struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3652 private_data, struct vfswrap_getxattrat_state);
3653 struct timespec start_time;
3654 struct timespec end_time;
3656 struct files_struct *fsp = metadata_fsp(state->smb_fname->fsp);
3658 PROFILE_TIMESTAMP(&start_time);
3659 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
3662 * Here we simulate a getxattrat()
3663 * call using fchdir();getxattr()
3666 per_thread_cwd_activate();
3668 /* Become the correct credential on this thread. */
3669 ret = set_thread_credentials(state->token->uid,
3671 (size_t)state->token->ngroups,
3672 state->token->groups);
3674 state->xattr_size = -1;
3675 state->vfs_aio_state.error = errno;
3679 state->xattr_size = vfswrap_fgetxattr(state->handle,
3683 talloc_array_length(state->xattr_value));
3684 if (state->xattr_size == -1) {
3685 state->vfs_aio_state.error = errno;
3689 PROFILE_TIMESTAMP(&end_time);
3690 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
3691 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3694 static void vfswrap_getxattrat_done(struct tevent_req *subreq)
3696 struct tevent_req *req = tevent_req_callback_data(
3697 subreq, struct tevent_req);
3698 struct vfswrap_getxattrat_state *state = tevent_req_data(
3699 req, struct vfswrap_getxattrat_state);
3704 * Make sure we run as the user again
3706 ok = change_to_user_and_service_by_fsp(state->dir_fsp);
3709 ret = pthreadpool_tevent_job_recv(subreq);
3710 TALLOC_FREE(subreq);
3711 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
3712 talloc_set_destructor(state, NULL);
3714 if (ret != EAGAIN) {
3715 tevent_req_error(req, ret);
3719 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
3720 * means the lower level pthreadpool failed to create a new
3721 * thread. Fallback to sync processing in that case to allow
3722 * some progress for the client.
3724 vfswrap_getxattrat_do_sync(req);
3728 if (state->xattr_size == -1) {
3729 tevent_req_error(req, state->vfs_aio_state.error);
3733 if (state->xattr_value == NULL) {
3735 * The caller only wanted the size.
3737 tevent_req_done(req);
3742 * shrink the buffer to the returned size.
3743 * (can't fail). It means NULL if size is 0.
3745 state->xattr_value = talloc_realloc(state,
3750 tevent_req_done(req);
3753 static ssize_t vfswrap_getxattrat_recv(struct tevent_req *req,
3754 struct vfs_aio_state *aio_state,
3755 TALLOC_CTX *mem_ctx,
3756 uint8_t **xattr_value)
3758 struct vfswrap_getxattrat_state *state = tevent_req_data(
3759 req, struct vfswrap_getxattrat_state);
3762 if (tevent_req_is_unix_error(req, &aio_state->error)) {
3763 tevent_req_received(req);
3767 *aio_state = state->vfs_aio_state;
3768 xattr_size = state->xattr_size;
3769 if (xattr_value != NULL) {
3770 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
3773 tevent_req_received(req);
3777 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
3779 int fd = fsp_get_pathref_fd(fsp);
3781 if (!fsp->fsp_flags.is_pathref) {
3782 return flistxattr(fd, list, size);
3785 if (fsp->fsp_flags.have_proc_fds) {
3786 const char *p = NULL;
3789 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3794 return listxattr(p, list, size);
3798 * This is no longer a handle based call.
3800 return listxattr(fsp->fsp_name->base_name, list, size);
3803 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
3805 int fd = fsp_get_pathref_fd(fsp);
3807 if (!fsp->fsp_flags.is_pathref) {
3808 return fremovexattr(fd, name);
3811 if (fsp->fsp_flags.have_proc_fds) {
3812 const char *p = NULL;
3815 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3820 return removexattr(p, name);
3824 * This is no longer a handle based call.
3826 return removexattr(fsp->fsp_name->base_name, name);
3829 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
3831 int fd = fsp_get_pathref_fd(fsp);
3833 if (!fsp->fsp_flags.is_pathref) {
3834 return fsetxattr(fd, name, value, size, flags);
3837 if (fsp->fsp_flags.have_proc_fds) {
3838 const char *p = NULL;
3841 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3846 return setxattr(p, name, value, size, flags);
3850 * This is no longer a handle based call.
3852 return setxattr(fsp->fsp_name->base_name, name, value, size, flags);
3855 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
3860 static bool vfswrap_is_offline(struct connection_struct *conn,
3861 const struct smb_filename *fname)
3865 bool offline = false;
3867 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
3871 if (!lp_dmapi_support(SNUM(conn)) || !dmapi_have_session()) {
3872 #if defined(ENOTSUP)
3878 status = get_full_smb_filename(talloc_tos(), fname, &path);
3879 if (!NT_STATUS_IS_OK(status)) {
3880 errno = map_errno_from_nt_status(status);
3884 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
3891 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
3892 struct files_struct *fsp,
3893 TALLOC_CTX *mem_ctx,
3896 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
3899 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
3900 struct files_struct *fsp,
3901 const DATA_BLOB old_cookie,
3902 TALLOC_CTX *mem_ctx,
3903 DATA_BLOB *new_cookie)
3905 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
3909 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
3910 struct smb_request *smb1req,
3911 struct smbXsrv_open *op,
3912 const DATA_BLOB old_cookie,
3913 TALLOC_CTX *mem_ctx,
3914 struct files_struct **fsp,
3915 DATA_BLOB *new_cookie)
3917 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
3918 old_cookie, mem_ctx,
3922 static struct vfs_fn_pointers vfs_default_fns = {
3923 /* Disk operations */
3925 .connect_fn = vfswrap_connect,
3926 .disconnect_fn = vfswrap_disconnect,
3927 .disk_free_fn = vfswrap_disk_free,
3928 .get_quota_fn = vfswrap_get_quota,
3929 .set_quota_fn = vfswrap_set_quota,
3930 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3931 .statvfs_fn = vfswrap_statvfs,
3932 .fs_capabilities_fn = vfswrap_fs_capabilities,
3933 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3934 .create_dfs_pathat_fn = vfswrap_create_dfs_pathat,
3935 .read_dfs_pathat_fn = vfswrap_read_dfs_pathat,
3936 .snap_check_path_fn = vfswrap_snap_check_path,
3937 .snap_create_fn = vfswrap_snap_create,
3938 .snap_delete_fn = vfswrap_snap_delete,
3940 /* Directory operations */
3942 .fdopendir_fn = vfswrap_fdopendir,
3943 .readdir_fn = vfswrap_readdir,
3944 .freaddir_attr_fn = vfswrap_freaddir_attr,
3945 .seekdir_fn = vfswrap_seekdir,
3946 .telldir_fn = vfswrap_telldir,
3947 .rewind_dir_fn = vfswrap_rewinddir,
3948 .mkdirat_fn = vfswrap_mkdirat,
3949 .closedir_fn = vfswrap_closedir,
3951 /* File operations */
3953 .openat_fn = vfswrap_openat,
3954 .create_file_fn = vfswrap_create_file,
3955 .close_fn = vfswrap_close,
3956 .pread_fn = vfswrap_pread,
3957 .pread_send_fn = vfswrap_pread_send,
3958 .pread_recv_fn = vfswrap_pread_recv,
3959 .pwrite_fn = vfswrap_pwrite,
3960 .pwrite_send_fn = vfswrap_pwrite_send,
3961 .pwrite_recv_fn = vfswrap_pwrite_recv,
3962 .lseek_fn = vfswrap_lseek,
3963 .sendfile_fn = vfswrap_sendfile,
3964 .recvfile_fn = vfswrap_recvfile,
3965 .renameat_fn = vfswrap_renameat,
3966 .fsync_send_fn = vfswrap_fsync_send,
3967 .fsync_recv_fn = vfswrap_fsync_recv,
3968 .stat_fn = vfswrap_stat,
3969 .fstat_fn = vfswrap_fstat,
3970 .lstat_fn = vfswrap_lstat,
3971 .get_alloc_size_fn = vfswrap_get_alloc_size,
3972 .unlinkat_fn = vfswrap_unlinkat,
3973 .fchmod_fn = vfswrap_fchmod,
3974 .fchown_fn = vfswrap_fchown,
3975 .lchown_fn = vfswrap_lchown,
3976 .chdir_fn = vfswrap_chdir,
3977 .getwd_fn = vfswrap_getwd,
3978 .fntimes_fn = vfswrap_fntimes,
3979 .ftruncate_fn = vfswrap_ftruncate,
3980 .fallocate_fn = vfswrap_fallocate,
3981 .lock_fn = vfswrap_lock,
3982 .filesystem_sharemode_fn = vfswrap_filesystem_sharemode,
3983 .fcntl_fn = vfswrap_fcntl,
3984 .linux_setlease_fn = vfswrap_linux_setlease,
3985 .getlock_fn = vfswrap_getlock,
3986 .symlinkat_fn = vfswrap_symlinkat,
3987 .readlinkat_fn = vfswrap_readlinkat,
3988 .linkat_fn = vfswrap_linkat,
3989 .mknodat_fn = vfswrap_mknodat,
3990 .realpath_fn = vfswrap_realpath,
3991 .fchflags_fn = vfswrap_fchflags,
3992 .file_id_create_fn = vfswrap_file_id_create,
3993 .fs_file_id_fn = vfswrap_fs_file_id,
3994 .fstreaminfo_fn = vfswrap_fstreaminfo,
3995 .get_real_filename_fn = vfswrap_get_real_filename,
3996 .connectpath_fn = vfswrap_connectpath,
3997 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
3998 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3999 .strict_lock_check_fn = vfswrap_strict_lock_check,
4000 .translate_name_fn = vfswrap_translate_name,
4001 .parent_pathname_fn = vfswrap_parent_pathname,
4002 .fsctl_fn = vfswrap_fsctl,
4003 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
4004 .get_dos_attributes_send_fn = vfswrap_get_dos_attributes_send,
4005 .get_dos_attributes_recv_fn = vfswrap_get_dos_attributes_recv,
4006 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
4007 .offload_read_send_fn = vfswrap_offload_read_send,
4008 .offload_read_recv_fn = vfswrap_offload_read_recv,
4009 .offload_write_send_fn = vfswrap_offload_write_send,
4010 .offload_write_recv_fn = vfswrap_offload_write_recv,
4011 .fget_compression_fn = vfswrap_fget_compression,
4012 .set_compression_fn = vfswrap_set_compression,
4014 /* NT ACL operations. */
4016 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
4017 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
4018 .audit_file_fn = vfswrap_audit_file,
4020 /* POSIX ACL operations. */
4022 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
4023 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
4024 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
4025 .sys_acl_delete_def_fd_fn = vfswrap_sys_acl_delete_def_fd,
4027 /* EA operations. */
4028 .getxattrat_send_fn = vfswrap_getxattrat_send,
4029 .getxattrat_recv_fn = vfswrap_getxattrat_recv,
4030 .fgetxattr_fn = vfswrap_fgetxattr,
4031 .flistxattr_fn = vfswrap_flistxattr,
4032 .fremovexattr_fn = vfswrap_fremovexattr,
4033 .fsetxattr_fn = vfswrap_fsetxattr,
4035 /* aio operations */
4036 .aio_force_fn = vfswrap_aio_force,
4038 /* durable handle operations */
4039 .durable_cookie_fn = vfswrap_durable_cookie,
4040 .durable_disconnect_fn = vfswrap_durable_disconnect,
4041 .durable_reconnect_fn = vfswrap_durable_reconnect,
4045 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
4048 * Here we need to implement every call!
4050 * As this is the end of the vfs module chain.
4052 smb_vfs_assert_all_fns(&vfs_default_fns, DEFAULT_VFS_MODULE_NAME);
4053 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
4054 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);