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 int vfswrap_fstatat(
1318 struct vfs_handle_struct *handle,
1319 const struct files_struct *dirfsp,
1320 const struct smb_filename *smb_fname,
1321 SMB_STRUCT_STAT *sbuf,
1326 START_PROFILE(syscall_fstatat);
1328 if (is_named_stream(smb_fname)) {
1333 result = sys_fstatat(
1334 fsp_get_pathref_fd(dirfsp),
1335 smb_fname->base_name,
1338 lp_fake_directory_create_times(SNUM(handle->conn)));
1340 END_PROFILE(syscall_fstatat);
1344 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1346 enum vfs_translate_direction direction,
1347 TALLOC_CTX *mem_ctx,
1350 return NT_STATUS_NONE_MAPPED;
1354 * Return allocated parent directory and basename of path
1356 * Note: if requesting atname, it is returned as talloc child of the
1357 * parent. Freeing the parent is thus sufficient to free both.
1359 static NTSTATUS vfswrap_parent_pathname(struct vfs_handle_struct *handle,
1360 TALLOC_CTX *mem_ctx,
1361 const struct smb_filename *smb_fname_in,
1362 struct smb_filename **parent_dir_out,
1363 struct smb_filename **atname_out)
1365 TALLOC_CTX *frame = talloc_stackframe();
1366 struct smb_filename *parent = NULL;
1367 struct smb_filename *name = NULL;
1370 parent = cp_smb_filename_nostream(frame, smb_fname_in);
1371 if (parent == NULL) {
1373 return NT_STATUS_NO_MEMORY;
1375 SET_STAT_INVALID(parent->st);
1377 p = strrchr_m(parent->base_name, '/'); /* Find final '/', if any */
1379 TALLOC_FREE(parent->base_name);
1380 parent->base_name = talloc_strdup(parent, ".");
1381 if (parent->base_name == NULL) {
1383 return NT_STATUS_NO_MEMORY;
1385 p = smb_fname_in->base_name;
1391 if (atname_out == NULL) {
1392 *parent_dir_out = talloc_move(mem_ctx, &parent);
1394 return NT_STATUS_OK;
1397 name = cp_smb_filename(frame, smb_fname_in);
1400 return NT_STATUS_NO_MEMORY;
1402 TALLOC_FREE(name->base_name);
1404 name->base_name = talloc_strdup(name, p);
1405 if (name->base_name == NULL) {
1407 return NT_STATUS_NO_MEMORY;
1410 *parent_dir_out = talloc_move(mem_ctx, &parent);
1411 *atname_out = talloc_move(*parent_dir_out, &name);
1413 return NT_STATUS_OK;
1417 * Implement the default fsctl operation.
1419 static bool vfswrap_logged_ioctl_message = false;
1421 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1422 struct files_struct *fsp,
1425 uint16_t req_flags, /* Needed for UNICODE ... */
1426 const uint8_t *_in_data,
1428 uint8_t **_out_data,
1429 uint32_t max_out_len,
1432 const char *in_data = (const char *)_in_data;
1433 char **out_data = (char **)_out_data;
1437 case FSCTL_SET_SPARSE:
1439 bool set_sparse = true;
1441 if (in_len >= 1 && in_data[0] == 0) {
1445 status = file_set_sparse(handle->conn, fsp, set_sparse);
1447 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1448 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1449 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1450 nt_errstr(status)));
1455 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1457 unsigned char objid[16];
1458 char *return_data = NULL;
1460 /* This should return the object-id on this file.
1461 * I think I'll make this be the inode+dev. JRA.
1464 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1465 fsp_fnum_dbg(fsp)));
1467 *out_len = MIN(max_out_len, 64);
1469 /* Hmmm, will this cause problems if less data asked for? */
1470 return_data = talloc_array(ctx, char, 64);
1471 if (return_data == NULL) {
1472 return NT_STATUS_NO_MEMORY;
1475 /* For backwards compatibility only store the dev/inode. */
1476 push_file_id_16(return_data, &fsp->file_id);
1477 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1478 push_file_id_16(return_data+32, &fsp->file_id);
1479 memset(return_data+48, 0, 16);
1480 *out_data = return_data;
1481 return NT_STATUS_OK;
1484 case FSCTL_GET_REPARSE_POINT:
1486 status = fsctl_get_reparse_point(
1487 fsp, ctx, out_data, max_out_len, out_len);
1491 case FSCTL_SET_REPARSE_POINT:
1493 status = fsctl_set_reparse_point(fsp, ctx, _in_data, in_len);
1497 case FSCTL_DELETE_REPARSE_POINT:
1499 status = fsctl_del_reparse_point(fsp, ctx, _in_data, in_len);
1503 case FSCTL_GET_SHADOW_COPY_DATA:
1506 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1507 * and return their volume names. If max_data_count is 16, then it is just
1508 * asking for the number of volumes and length of the combined names.
1510 * pdata is the data allocated by our caller, but that uses
1511 * total_data_count (which is 0 in our case) rather than max_data_count.
1512 * Allocate the correct amount and return the pointer to let
1513 * it be deallocated when we return.
1515 struct shadow_copy_data *shadow_data = NULL;
1516 bool labels = False;
1517 uint32_t labels_data_count = 0;
1519 char *cur_pdata = NULL;
1521 if (max_out_len < 16) {
1522 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1524 return NT_STATUS_INVALID_PARAMETER;
1527 if (max_out_len > 16) {
1531 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1532 if (shadow_data == NULL) {
1533 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1534 return NT_STATUS_NO_MEMORY;
1538 * Call the VFS routine to actually do the work.
1540 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1543 /* broken module didn't set errno on error */
1544 status = NT_STATUS_UNSUCCESSFUL;
1546 status = map_nt_error_from_unix(errno);
1547 if (NT_STATUS_EQUAL(status,
1548 NT_STATUS_NOT_SUPPORTED)) {
1552 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1553 "connectpath %s, failed - %s.\n",
1554 fsp->conn->connectpath,
1555 nt_errstr(status)));
1556 TALLOC_FREE(shadow_data);
1560 labels_data_count = (shadow_data->num_volumes * 2 *
1561 sizeof(SHADOW_COPY_LABEL)) + 2;
1566 *out_len = 12 + labels_data_count;
1569 if (max_out_len < *out_len) {
1570 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1571 max_out_len, *out_len));
1572 TALLOC_FREE(shadow_data);
1573 return NT_STATUS_BUFFER_TOO_SMALL;
1576 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1577 if (cur_pdata == NULL) {
1578 TALLOC_FREE(shadow_data);
1579 return NT_STATUS_NO_MEMORY;
1582 *out_data = cur_pdata;
1584 /* num_volumes 4 bytes */
1585 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1588 /* num_labels 4 bytes */
1589 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1592 /* needed_data_count 4 bytes */
1593 SIVAL(cur_pdata, 8, labels_data_count);
1597 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1598 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1599 if (labels && shadow_data->labels) {
1600 for (i=0; i<shadow_data->num_volumes; i++) {
1602 status = srvstr_push(cur_pdata, req_flags,
1603 cur_pdata, shadow_data->labels[i],
1604 2 * sizeof(SHADOW_COPY_LABEL),
1605 STR_UNICODE|STR_TERMINATE, &len);
1606 if (!NT_STATUS_IS_OK(status)) {
1607 TALLOC_FREE(*out_data);
1608 TALLOC_FREE(shadow_data);
1611 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1612 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1616 TALLOC_FREE(shadow_data);
1618 return NT_STATUS_OK;
1621 case FSCTL_FIND_FILES_BY_SID:
1623 /* pretend this succeeded -
1625 * we have to send back a list with all files owned by this SID
1627 * but I have to check that --metze
1631 struct dom_sid_buf buf;
1635 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1636 fsp_fnum_dbg(fsp)));
1639 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1640 return NT_STATUS_INVALID_PARAMETER;
1643 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1645 /* unknown 4 bytes: this is not the length of the sid :-( */
1646 /*unknown = IVAL(pdata,0);*/
1648 ret = sid_parse(_in_data + 4, sid_len, &sid);
1650 return NT_STATUS_INVALID_PARAMETER;
1652 DEBUGADD(10, ("for SID: %s\n",
1653 dom_sid_str_buf(&sid, &buf)));
1655 if (!sid_to_uid(&sid, &uid)) {
1656 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1657 dom_sid_str_buf(&sid, &buf),
1658 (unsigned long)sid_len));
1662 /* we can take a look at the find source :-)
1664 * find ./ -uid $uid -name '*' is what we need here
1667 * and send 4bytes len and then NULL terminated unicode strings
1670 * but I don't know how to deal with the paged results
1671 * (maybe we can hang the result anywhere in the fsp struct)
1673 * but I don't know how to deal with the paged results
1674 * (maybe we can hang the result anywhere in the fsp struct)
1676 * we don't send all files at once
1677 * and at the next we should *not* start from the beginning,
1678 * so we have to cache the result
1683 /* this works for now... */
1684 return NT_STATUS_OK;
1687 case FSCTL_QUERY_ALLOCATED_RANGES:
1689 /* FIXME: This is just a dummy reply, telling that all of the
1690 * file is allocated. MKS cp needs that.
1691 * Adding the real allocated ranges via FIEMAP on Linux
1692 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1693 * this FSCTL correct for sparse files.
1695 uint64_t offset, length;
1696 char *out_data_tmp = NULL;
1699 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1701 return NT_STATUS_INVALID_PARAMETER;
1704 if (max_out_len < 16) {
1705 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1707 return NT_STATUS_INVALID_PARAMETER;
1710 offset = BVAL(in_data,0);
1711 length = BVAL(in_data,8);
1713 if (offset + length < offset) {
1714 /* No 64-bit integer wrap. */
1715 return NT_STATUS_INVALID_PARAMETER;
1718 /* Shouldn't this be SMB_VFS_STAT ... ? */
1719 status = vfs_stat_fsp(fsp);
1720 if (!NT_STATUS_IS_OK(status)) {
1725 out_data_tmp = talloc_array(ctx, char, *out_len);
1726 if (out_data_tmp == NULL) {
1727 DEBUG(10, ("unable to allocate memory for response\n"));
1728 return NT_STATUS_NO_MEMORY;
1731 if (offset > fsp->fsp_name->st.st_ex_size ||
1732 fsp->fsp_name->st.st_ex_size == 0 ||
1734 memset(out_data_tmp, 0, *out_len);
1736 uint64_t end = offset + length;
1737 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1738 SBVAL(out_data_tmp, 0, 0);
1739 SBVAL(out_data_tmp, 8, end);
1742 *out_data = out_data_tmp;
1744 return NT_STATUS_OK;
1747 case FSCTL_IS_VOLUME_DIRTY:
1749 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1750 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1752 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1753 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1755 return NT_STATUS_INVALID_PARAMETER;
1760 * Only print once ... unfortunately there could be lots of
1761 * different FSCTLs that are called.
1763 if (!vfswrap_logged_ioctl_message) {
1764 vfswrap_logged_ioctl_message = true;
1765 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1766 __func__, function));
1770 return NT_STATUS_NOT_SUPPORTED;
1773 static bool vfswrap_is_offline(struct connection_struct *conn,
1774 const struct smb_filename *fname);
1776 struct vfswrap_get_dos_attributes_state {
1777 struct vfs_aio_state aio_state;
1778 connection_struct *conn;
1779 TALLOC_CTX *mem_ctx;
1780 struct tevent_context *ev;
1781 files_struct *dir_fsp;
1782 struct smb_filename *smb_fname;
1787 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq);
1789 static struct tevent_req *vfswrap_get_dos_attributes_send(
1790 TALLOC_CTX *mem_ctx,
1791 struct tevent_context *ev,
1792 struct vfs_handle_struct *handle,
1793 files_struct *dir_fsp,
1794 struct smb_filename *smb_fname)
1796 struct tevent_req *req = NULL;
1797 struct tevent_req *subreq = NULL;
1798 struct vfswrap_get_dos_attributes_state *state = NULL;
1800 req = tevent_req_create(mem_ctx, &state,
1801 struct vfswrap_get_dos_attributes_state);
1806 *state = (struct vfswrap_get_dos_attributes_state) {
1807 .conn = dir_fsp->conn,
1811 .smb_fname = smb_fname,
1814 if (!lp_store_dos_attributes(SNUM(dir_fsp->conn))) {
1815 DBG_ERR("%s: \"smbd async dosmode\" enabled, but "
1816 "\"store dos attributes\" is disabled\n",
1817 dir_fsp->conn->connectpath);
1818 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
1819 return tevent_req_post(req, ev);
1822 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1826 SAMBA_XATTR_DOS_ATTRIB,
1828 if (tevent_req_nomem(subreq, req)) {
1829 return tevent_req_post(req, ev);
1831 tevent_req_set_callback(subreq,
1832 vfswrap_get_dos_attributes_getxattr_done,
1838 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq)
1840 struct tevent_req *req =
1841 tevent_req_callback_data(subreq,
1843 struct vfswrap_get_dos_attributes_state *state =
1844 tevent_req_data(req,
1845 struct vfswrap_get_dos_attributes_state);
1847 DATA_BLOB blob = {0};
1849 char *tofree = NULL;
1850 char pathbuf[PATH_MAX+1];
1852 struct smb_filename smb_fname;
1856 xattr_size = SMB_VFS_GETXATTRAT_RECV(subreq,
1860 TALLOC_FREE(subreq);
1861 if (xattr_size == -1) {
1862 status = map_nt_error_from_unix(state->aio_state.error);
1864 if (state->as_root) {
1865 tevent_req_nterror(req, status);
1868 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1869 tevent_req_nterror(req, status);
1873 state->as_root = true;
1876 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1880 SAMBA_XATTR_DOS_ATTRIB,
1883 if (tevent_req_nomem(subreq, req)) {
1886 tevent_req_set_callback(subreq,
1887 vfswrap_get_dos_attributes_getxattr_done,
1892 blob.length = xattr_size;
1894 status = parse_dos_attribute_blob(state->smb_fname,
1897 if (!NT_STATUS_IS_OK(status)) {
1898 tevent_req_nterror(req, status);
1902 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
1903 state->smb_fname->base_name,
1908 if (pathlen == -1) {
1909 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1913 smb_fname = (struct smb_filename) {
1915 .st = state->smb_fname->st,
1916 .flags = state->smb_fname->flags,
1917 .twrp = state->smb_fname->twrp,
1920 offline = vfswrap_is_offline(state->conn, &smb_fname);
1922 state->dosmode |= FILE_ATTRIBUTE_OFFLINE;
1924 TALLOC_FREE(tofree);
1926 tevent_req_done(req);
1930 static NTSTATUS vfswrap_get_dos_attributes_recv(struct tevent_req *req,
1931 struct vfs_aio_state *aio_state,
1934 struct vfswrap_get_dos_attributes_state *state =
1935 tevent_req_data(req,
1936 struct vfswrap_get_dos_attributes_state);
1939 if (tevent_req_is_nterror(req, &status)) {
1940 tevent_req_received(req);
1944 *aio_state = state->aio_state;
1945 *dosmode = state->dosmode;
1946 tevent_req_received(req);
1947 return NT_STATUS_OK;
1950 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1951 struct files_struct *fsp,
1956 offline = vfswrap_is_offline(handle->conn, fsp->fsp_name);
1958 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1961 return fget_ea_dos_attribute(fsp, dosmode);
1964 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1965 struct files_struct *fsp,
1968 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1971 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1973 struct vfswrap_offload_read_state {
1977 static struct tevent_req *vfswrap_offload_read_send(
1978 TALLOC_CTX *mem_ctx,
1979 struct tevent_context *ev,
1980 struct vfs_handle_struct *handle,
1981 struct files_struct *fsp,
1987 struct tevent_req *req = NULL;
1988 struct vfswrap_offload_read_state *state = NULL;
1991 req = tevent_req_create(mem_ctx, &state,
1992 struct vfswrap_offload_read_state);
1997 status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1998 &vfswrap_offload_ctx);
1999 if (tevent_req_nterror(req, status)) {
2000 return tevent_req_post(req, ev);
2003 if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
2004 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
2005 return tevent_req_post(req, ev);
2008 status = vfs_offload_token_create_blob(state, fsp, fsctl,
2010 if (tevent_req_nterror(req, status)) {
2011 return tevent_req_post(req, ev);
2014 status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
2016 if (tevent_req_nterror(req, status)) {
2017 return tevent_req_post(req, ev);
2020 tevent_req_done(req);
2021 return tevent_req_post(req, ev);
2024 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
2025 struct vfs_handle_struct *handle,
2026 TALLOC_CTX *mem_ctx,
2031 struct vfswrap_offload_read_state *state = tevent_req_data(
2032 req, struct vfswrap_offload_read_state);
2035 if (tevent_req_is_nterror(req, &status)) {
2036 tevent_req_received(req);
2042 token->length = state->token.length;
2043 token->data = talloc_move(mem_ctx, &state->token.data);
2045 tevent_req_received(req);
2046 return NT_STATUS_OK;
2049 struct vfswrap_offload_write_state {
2051 bool read_lck_locked;
2052 bool write_lck_locked;
2054 struct tevent_context *src_ev;
2055 struct files_struct *src_fsp;
2057 struct tevent_context *dst_ev;
2058 struct files_struct *dst_fsp;
2063 size_t next_io_size;
2066 static void vfswrap_offload_write_cleanup(struct tevent_req *req,
2067 enum tevent_req_state req_state)
2069 struct vfswrap_offload_write_state *state = tevent_req_data(
2070 req, struct vfswrap_offload_write_state);
2073 if (state->dst_fsp == NULL) {
2077 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2079 state->dst_fsp = NULL;
2082 static NTSTATUS vfswrap_offload_copy_file_range(struct tevent_req *req);
2083 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
2085 static struct tevent_req *vfswrap_offload_write_send(
2086 struct vfs_handle_struct *handle,
2087 TALLOC_CTX *mem_ctx,
2088 struct tevent_context *ev,
2091 off_t transfer_offset,
2092 struct files_struct *dest_fsp,
2096 struct tevent_req *req;
2097 struct vfswrap_offload_write_state *state = NULL;
2098 /* off_t is signed! */
2099 off_t max_offset = INT64_MAX - to_copy;
2100 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
2101 files_struct *src_fsp = NULL;
2105 req = tevent_req_create(mem_ctx, &state,
2106 struct vfswrap_offload_write_state);
2111 *state = (struct vfswrap_offload_write_state) {
2113 .src_off = transfer_offset,
2115 .dst_fsp = dest_fsp,
2116 .dst_off = dest_off,
2118 .remaining = to_copy,
2121 tevent_req_set_cleanup_fn(req, vfswrap_offload_write_cleanup);
2124 case FSCTL_SRV_COPYCHUNK:
2125 case FSCTL_SRV_COPYCHUNK_WRITE:
2128 case FSCTL_OFFLOAD_WRITE:
2129 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
2130 return tevent_req_post(req, ev);
2132 case FSCTL_DUP_EXTENTS_TO_FILE:
2133 DBG_DEBUG("COW clones not supported by vfs_default\n");
2134 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2135 return tevent_req_post(req, ev);
2138 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2139 return tevent_req_post(req, ev);
2143 * From here on we assume a copy-chunk fsctl
2147 tevent_req_done(req);
2148 return tevent_req_post(req, ev);
2151 if (state->src_off > max_offset) {
2153 * Protect integer checks below.
2155 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2156 return tevent_req_post(req, ev);
2158 if (state->src_off < 0) {
2160 * Protect integer checks below.
2162 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2163 return tevent_req_post(req, ev);
2165 if (state->dst_off > max_offset) {
2167 * Protect integer checks below.
2169 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2170 return tevent_req_post(req, ev);
2172 if (state->dst_off < 0) {
2174 * Protect integer checks below.
2176 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2177 return tevent_req_post(req, ev);
2180 status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
2182 if (tevent_req_nterror(req, status)) {
2183 return tevent_req_post(req, ev);
2186 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
2188 status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
2189 if (!NT_STATUS_IS_OK(status)) {
2190 tevent_req_nterror(req, status);
2191 return tevent_req_post(req, ev);
2194 ok = change_to_user_and_service_by_fsp(src_fsp);
2196 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2197 return tevent_req_post(req, ev);
2200 state->src_ev = src_fsp->conn->sconn->ev_ctx;
2201 state->src_fsp = src_fsp;
2203 status = vfs_stat_fsp(src_fsp);
2204 if (tevent_req_nterror(req, status)) {
2205 return tevent_req_post(req, ev);
2208 if (src_fsp->fsp_name->st.st_ex_size < state->src_off + to_copy) {
2210 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
2211 * If the SourceOffset or SourceOffset + Length extends beyond
2212 * the end of file, the server SHOULD<240> treat this as a
2213 * STATUS_END_OF_FILE error.
2215 * <240> Section 3.3.5.15.6: Windows servers will return
2216 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
2218 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
2219 return tevent_req_post(req, ev);
2222 status = vfswrap_offload_copy_file_range(req);
2223 if (NT_STATUS_IS_OK(status)) {
2224 tevent_req_done(req);
2225 return tevent_req_post(req, ev);
2227 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2228 tevent_req_nterror(req, status);
2229 return tevent_req_post(req, ev);
2232 state->buf = talloc_array(state, uint8_t, num);
2233 if (tevent_req_nomem(state->buf, req)) {
2234 return tevent_req_post(req, ev);
2237 status = vfswrap_offload_write_loop(req);
2238 if (!NT_STATUS_IS_OK(status)) {
2239 tevent_req_nterror(req, status);
2240 return tevent_req_post(req, ev);
2246 static NTSTATUS vfswrap_offload_copy_file_range(struct tevent_req *req)
2248 struct vfswrap_offload_write_state *state = tevent_req_data(
2249 req, struct vfswrap_offload_write_state);
2250 struct lock_struct lck;
2255 static bool try_copy_file_range = true;
2257 if (!try_copy_file_range) {
2258 return NT_STATUS_MORE_PROCESSING_REQUIRED;
2261 same_file = file_id_equal(&state->src_fsp->file_id,
2262 &state->dst_fsp->file_id);
2264 sys_io_ranges_overlap(state->remaining,
2269 return NT_STATUS_MORE_PROCESSING_REQUIRED;
2272 if (fsp_is_alternate_stream(state->src_fsp) ||
2273 fsp_is_alternate_stream(state->dst_fsp))
2275 return NT_STATUS_MORE_PROCESSING_REQUIRED;
2278 init_strict_lock_struct(state->src_fsp,
2279 state->src_fsp->op->global->open_persistent_id,
2283 lp_posix_cifsu_locktype(state->src_fsp),
2286 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
2290 return NT_STATUS_FILE_LOCK_CONFLICT;
2293 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2295 return NT_STATUS_INTERNAL_ERROR;
2298 init_strict_lock_struct(state->dst_fsp,
2299 state->dst_fsp->op->global->open_persistent_id,
2303 lp_posix_cifsu_locktype(state->dst_fsp),
2306 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
2310 return NT_STATUS_FILE_LOCK_CONFLICT;
2313 while (state->remaining > 0) {
2314 nwritten = copy_file_range(fsp_get_io_fd(state->src_fsp),
2316 fsp_get_io_fd(state->dst_fsp),
2320 if (nwritten == -1) {
2321 DBG_DEBUG("copy_file_range src [%s]:[%jd] dst [%s]:[%jd] "
2322 "n [%jd] failed: %s\n",
2323 fsp_str_dbg(state->src_fsp),
2324 (intmax_t)state->src_off,
2325 fsp_str_dbg(state->dst_fsp),
2326 (intmax_t)state->dst_off,
2327 (intmax_t)state->remaining,
2332 try_copy_file_range = false;
2333 status = NT_STATUS_MORE_PROCESSING_REQUIRED;
2336 status = NT_STATUS_MORE_PROCESSING_REQUIRED;
2339 status = map_nt_error_from_unix(errno);
2340 if (NT_STATUS_EQUAL(
2342 NT_STATUS_MORE_PROCESSING_REQUIRED))
2344 /* Avoid triggering the fallback */
2345 status = NT_STATUS_INTERNAL_ERROR;
2352 if (state->remaining < nwritten) {
2353 DBG_DEBUG("copy_file_range src [%s] dst [%s] "
2354 "n [%jd] remaining [%jd]\n",
2355 fsp_str_dbg(state->src_fsp),
2356 fsp_str_dbg(state->dst_fsp),
2358 (intmax_t)state->remaining);
2359 return NT_STATUS_INTERNAL_ERROR;
2362 if (nwritten == 0) {
2365 state->copied += nwritten;
2366 state->remaining -= nwritten;
2370 * Tell the req cleanup function there's no need to call
2371 * change_to_user_and_service_by_fsp() on the dst handle.
2373 state->dst_fsp = NULL;
2374 return NT_STATUS_OK;
2377 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
2379 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
2381 struct vfswrap_offload_write_state *state = tevent_req_data(
2382 req, struct vfswrap_offload_write_state);
2383 struct tevent_req *subreq = NULL;
2384 struct lock_struct read_lck;
2388 * This is called under the context of state->src_fsp.
2391 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
2393 init_strict_lock_struct(state->src_fsp,
2394 state->src_fsp->op->global->open_persistent_id,
2396 state->next_io_size,
2398 lp_posix_cifsu_locktype(state->src_fsp),
2401 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
2405 return NT_STATUS_FILE_LOCK_CONFLICT;
2408 subreq = SMB_VFS_PREAD_SEND(state,
2412 state->next_io_size,
2414 if (subreq == NULL) {
2415 return NT_STATUS_NO_MEMORY;
2417 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
2419 return NT_STATUS_OK;
2422 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
2424 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
2426 struct tevent_req *req = tevent_req_callback_data(
2427 subreq, struct tevent_req);
2428 struct vfswrap_offload_write_state *state = tevent_req_data(
2429 req, struct vfswrap_offload_write_state);
2430 struct vfs_aio_state aio_state;
2431 struct lock_struct write_lck;
2435 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
2436 TALLOC_FREE(subreq);
2438 DBG_ERR("read failed: %s\n", strerror(aio_state.error));
2439 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2442 if (nread != state->next_io_size) {
2443 DBG_ERR("Short read, only %zd of %zu\n",
2444 nread, state->next_io_size);
2445 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2449 state->src_off += nread;
2451 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2453 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2457 init_strict_lock_struct(state->dst_fsp,
2458 state->dst_fsp->op->global->open_persistent_id,
2460 state->next_io_size,
2462 lp_posix_cifsu_locktype(state->dst_fsp),
2465 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
2469 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
2473 subreq = SMB_VFS_PWRITE_SEND(state,
2477 state->next_io_size,
2479 if (subreq == NULL) {
2480 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2483 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
2486 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
2488 struct tevent_req *req = tevent_req_callback_data(
2489 subreq, struct tevent_req);
2490 struct vfswrap_offload_write_state *state = tevent_req_data(
2491 req, struct vfswrap_offload_write_state);
2492 struct vfs_aio_state aio_state;
2497 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
2498 TALLOC_FREE(subreq);
2499 if (nwritten == -1) {
2500 DBG_ERR("write failed: %s\n", strerror(aio_state.error));
2501 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2504 if (nwritten != state->next_io_size) {
2505 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
2506 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2510 state->dst_off += nwritten;
2512 if (state->remaining < nwritten) {
2513 /* Paranoia check */
2514 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2517 state->copied += nwritten;
2518 state->remaining -= nwritten;
2519 if (state->remaining == 0) {
2520 tevent_req_done(req);
2524 ok = change_to_user_and_service_by_fsp(state->src_fsp);
2526 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2530 status = vfswrap_offload_write_loop(req);
2531 if (!NT_STATUS_IS_OK(status)) {
2532 tevent_req_nterror(req, status);
2539 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
2540 struct tevent_req *req,
2543 struct vfswrap_offload_write_state *state = tevent_req_data(
2544 req, struct vfswrap_offload_write_state);
2547 if (tevent_req_is_nterror(req, &status)) {
2548 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
2550 tevent_req_received(req);
2554 *copied = state->copied;
2555 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
2556 tevent_req_received(req);
2558 return NT_STATUS_OK;
2561 static NTSTATUS vfswrap_fget_compression(struct vfs_handle_struct *handle,
2562 TALLOC_CTX *mem_ctx,
2563 struct files_struct *fsp,
2564 uint16_t *_compression_fmt)
2566 return NT_STATUS_INVALID_DEVICE_REQUEST;
2569 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
2570 TALLOC_CTX *mem_ctx,
2571 struct files_struct *fsp,
2572 uint16_t compression_fmt)
2574 return NT_STATUS_INVALID_DEVICE_REQUEST;
2577 /********************************************************************
2578 Given a stat buffer return the allocated size on disk, taking into
2579 account sparse files.
2580 ********************************************************************/
2581 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
2582 struct files_struct *fsp,
2583 const SMB_STRUCT_STAT *sbuf)
2587 START_PROFILE(syscall_get_alloc_size);
2589 if(S_ISDIR(sbuf->st_ex_mode)) {
2594 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2595 /* The type of st_blocksize is blkcnt_t which *MUST* be
2596 signed (according to POSIX) and can be less than 64-bits.
2597 Ensure when we're converting to 64 bits wide we don't
2599 #if defined(SIZEOF_BLKCNT_T_8)
2600 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2601 #elif defined(SIZEOF_BLKCNT_T_4)
2603 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2604 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2607 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2611 * Some file systems do not allocate a block for very
2612 * small files. But for non-empty file should report a
2616 uint64_t filesize = get_file_size_stat(sbuf);
2618 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2622 result = get_file_size_stat(sbuf);
2625 if (fsp && fsp->initial_allocation_size)
2626 result = MAX(result,fsp->initial_allocation_size);
2628 result = smb_roundup(handle->conn, result);
2631 END_PROFILE(syscall_get_alloc_size);
2635 static int vfswrap_unlinkat(vfs_handle_struct *handle,
2636 struct files_struct *dirfsp,
2637 const struct smb_filename *smb_fname,
2642 START_PROFILE(syscall_unlinkat);
2644 if (is_named_stream(smb_fname)) {
2648 result = unlinkat(fsp_get_pathref_fd(dirfsp),
2649 smb_fname->base_name,
2653 END_PROFILE(syscall_unlinkat);
2657 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2661 START_PROFILE(syscall_fchmod);
2663 if (!fsp->fsp_flags.is_pathref) {
2664 result = fchmod(fsp_get_io_fd(fsp), mode);
2665 END_PROFILE(syscall_fchmod);
2669 if (fsp->fsp_flags.have_proc_fds) {
2670 int fd = fsp_get_pathref_fd(fsp);
2671 const char *p = NULL;
2674 p = sys_proc_fd_path(fd, buf, sizeof(buf));
2676 result = chmod(p, mode);
2680 END_PROFILE(syscall_fchmod);
2685 * This is no longer a handle based call.
2687 result = chmod(fsp->fsp_name->base_name, mode);
2689 END_PROFILE(syscall_fchmod);
2693 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2698 START_PROFILE(syscall_fchown);
2699 if (!fsp->fsp_flags.is_pathref) {
2700 result = fchown(fsp_get_io_fd(fsp), uid, gid);
2701 END_PROFILE(syscall_fchown);
2705 if (fsp->fsp_flags.have_proc_fds) {
2706 int fd = fsp_get_pathref_fd(fsp);
2707 const char *p = NULL;
2710 p = sys_proc_fd_path(fd, buf, sizeof(buf));
2712 result = chown(p, uid, gid);
2716 END_PROFILE(syscall_fchown);
2721 * This is no longer a handle based call.
2723 result = chown(fsp->fsp_name->base_name, uid, gid);
2724 END_PROFILE(syscall_fchown);
2732 static int vfswrap_lchown(vfs_handle_struct *handle,
2733 const struct smb_filename *smb_fname,
2739 START_PROFILE(syscall_lchown);
2740 result = lchown(smb_fname->base_name, uid, gid);
2741 END_PROFILE(syscall_lchown);
2745 static int vfswrap_chdir(vfs_handle_struct *handle,
2746 const struct smb_filename *smb_fname)
2750 START_PROFILE(syscall_chdir);
2751 result = chdir(smb_fname->base_name);
2752 END_PROFILE(syscall_chdir);
2756 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2760 struct smb_filename *smb_fname = NULL;
2762 START_PROFILE(syscall_getwd);
2763 result = sys_getwd();
2764 END_PROFILE(syscall_getwd);
2766 if (result == NULL) {
2769 smb_fname = synthetic_smb_fname(ctx,
2776 * sys_getwd() *always* returns malloced memory.
2777 * We must free here to avoid leaks:
2778 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2784 /*********************************************************************
2785 nsec timestamp resolution call. Convert down to whatever the underlying
2786 system will support.
2787 **********************************************************************/
2789 static int vfswrap_fntimes(vfs_handle_struct *handle,
2791 struct smb_file_time *ft)
2794 struct timespec ts[2];
2795 struct timespec *times = NULL;
2797 START_PROFILE(syscall_fntimes);
2799 if (fsp_is_alternate_stream(fsp)) {
2805 if (is_omit_timespec(&ft->atime)) {
2806 ft->atime = fsp->fsp_name->st.st_ex_atime;
2809 if (is_omit_timespec(&ft->mtime)) {
2810 ft->mtime = fsp->fsp_name->st.st_ex_mtime;
2813 if (!is_omit_timespec(&ft->create_time)) {
2814 set_create_timespec_ea(fsp,
2818 if ((timespec_compare(&ft->atime,
2819 &fsp->fsp_name->st.st_ex_atime) == 0) &&
2820 (timespec_compare(&ft->mtime,
2821 &fsp->fsp_name->st.st_ex_mtime) == 0)) {
2833 if (!fsp->fsp_flags.is_pathref) {
2834 result = futimens(fsp_get_io_fd(fsp), times);
2838 if (fsp->fsp_flags.have_proc_fds) {
2839 int fd = fsp_get_pathref_fd(fsp);
2840 const char *p = NULL;
2843 p = sys_proc_fd_path(fd, buf, sizeof(buf));
2846 * The dirfd argument of utimensat is ignored when
2847 * pathname is an absolute path
2849 result = utimensat(AT_FDCWD, p, times, 0);
2858 * The fd is a pathref (opened with O_PATH) and there isn't fd to
2859 * path translation mechanism. Fallback to path based call.
2861 result = utimensat(AT_FDCWD, fsp->fsp_name->base_name, times, 0);
2864 END_PROFILE(syscall_fntimes);
2870 /*********************************************************************
2871 A version of ftruncate that will write the space on disk if strict
2873 **********************************************************************/
2875 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2877 off_t space_to_write;
2878 uint64_t space_avail;
2879 uint64_t bsize,dfree,dsize;
2882 SMB_STRUCT_STAT *pst;
2885 ok = vfs_valid_pwrite_range(len, 0);
2891 status = vfs_stat_fsp(fsp);
2892 if (!NT_STATUS_IS_OK(status)) {
2895 pst = &fsp->fsp_name->st;
2898 if (S_ISFIFO(pst->st_ex_mode))
2902 if (pst->st_ex_size == len)
2905 /* Shrink - just ftruncate. */
2906 if (pst->st_ex_size > len)
2907 return ftruncate(fsp_get_io_fd(fsp), len);
2909 space_to_write = len - pst->st_ex_size;
2911 /* for allocation try fallocate first. This can fail on some
2912 platforms e.g. when the filesystem doesn't support it and no
2913 emulation is being done by the libc (like on AIX with JFS1). In that
2914 case we do our own emulation. fallocate implementations can
2915 return ENOTSUP or EINVAL in cases like that. */
2916 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2917 if (ret == -1 && errno == ENOSPC) {
2923 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2924 "error %d. Falling back to slow manual allocation\n", errno));
2926 /* available disk space is enough or not? */
2928 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2929 /* space_avail is 1k blocks */
2930 if (space_avail == (uint64_t)-1 ||
2931 ((uint64_t)space_to_write/1024 > space_avail) ) {
2936 /* Write out the real space on disk. */
2937 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2945 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2948 SMB_STRUCT_STAT *pst;
2952 START_PROFILE(syscall_ftruncate);
2954 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->fsp_flags.is_sparse) {
2955 result = strict_allocate_ftruncate(handle, fsp, len);
2956 END_PROFILE(syscall_ftruncate);
2960 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2961 ftruncate if the system supports it. Then I discovered that
2962 you can have some filesystems that support ftruncate
2963 expansion and some that don't! On Linux fat can't do
2964 ftruncate extend but ext2 can. */
2966 result = ftruncate(fsp_get_io_fd(fsp), len);
2968 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2969 extend a file with ftruncate. Provide alternate implementation
2972 /* Do an fstat to see if the file is longer than the requested
2973 size in which case the ftruncate above should have
2974 succeeded or shorter, in which case seek to len - 1 and
2975 write 1 byte of zero */
2976 status = vfs_stat_fsp(fsp);
2977 if (!NT_STATUS_IS_OK(status)) {
2981 /* We need to update the files_struct after successful ftruncate */
2986 pst = &fsp->fsp_name->st;
2989 if (S_ISFIFO(pst->st_ex_mode)) {
2995 if (pst->st_ex_size == len) {
3000 if (pst->st_ex_size > len) {
3001 /* the ftruncate should have worked */
3005 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
3013 END_PROFILE(syscall_ftruncate);
3017 static int vfswrap_fallocate(vfs_handle_struct *handle,
3025 START_PROFILE(syscall_fallocate);
3027 result = sys_posix_fallocate(fsp_get_io_fd(fsp), offset, len);
3029 * posix_fallocate returns 0 on success, errno on error
3030 * and doesn't set errno. Make it behave like fallocate()
3031 * which returns -1, and sets errno on failure.
3038 /* sys_fallocate handles filtering of unsupported mode flags */
3039 result = sys_fallocate(fsp_get_io_fd(fsp), mode, offset, len);
3041 END_PROFILE(syscall_fallocate);
3045 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
3049 START_PROFILE(syscall_fcntl_lock);
3051 if (fsp->fsp_flags.use_ofd_locks) {
3052 op = map_process_lock_to_ofd_lock(op);
3055 result = fcntl_lock(fsp_get_io_fd(fsp), op, offset, count, type);
3056 END_PROFILE(syscall_fcntl_lock);
3060 static int vfswrap_filesystem_sharemode(vfs_handle_struct *handle,
3062 uint32_t share_access,
3063 uint32_t access_mask)
3069 static int vfswrap_fcntl(vfs_handle_struct *handle, files_struct *fsp, int cmd,
3073 va_list dup_cmd_arg;
3077 START_PROFILE(syscall_fcntl);
3079 va_copy(dup_cmd_arg, cmd_arg);
3085 #if defined(HAVE_OFD_LOCKS)
3090 #if defined(HAVE_F_OWNER_EX)
3094 #if defined(HAVE_RW_HINTS)
3097 case F_GET_FILE_RW_HINT:
3098 case F_SET_FILE_RW_HINT:
3100 argp = va_arg(dup_cmd_arg, void *);
3101 result = sys_fcntl_ptr(fsp_get_io_fd(fsp), cmd, argp);
3104 val = va_arg(dup_cmd_arg, int);
3105 result = sys_fcntl_int(fsp_get_io_fd(fsp), cmd, val);
3108 va_end(dup_cmd_arg);
3110 END_PROFILE(syscall_fcntl);
3114 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
3119 START_PROFILE(syscall_fcntl_getlock);
3121 if (fsp->fsp_flags.use_ofd_locks) {
3122 op = map_process_lock_to_ofd_lock(op);
3125 result = fcntl_getlock(fsp_get_io_fd(fsp), op, poffset, pcount, ptype, ppid);
3126 END_PROFILE(syscall_fcntl_getlock);
3130 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
3135 START_PROFILE(syscall_linux_setlease);
3137 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
3138 result = linux_setlease(fsp_get_io_fd(fsp), leasetype);
3142 END_PROFILE(syscall_linux_setlease);
3146 static int vfswrap_symlinkat(vfs_handle_struct *handle,
3147 const struct smb_filename *link_target,
3148 struct files_struct *dirfsp,
3149 const struct smb_filename *new_smb_fname)
3153 START_PROFILE(syscall_symlinkat);
3155 result = symlinkat(link_target->base_name,
3156 fsp_get_pathref_fd(dirfsp),
3157 new_smb_fname->base_name);
3158 END_PROFILE(syscall_symlinkat);
3162 static int vfswrap_readlinkat(vfs_handle_struct *handle,
3163 const struct files_struct *dirfsp,
3164 const struct smb_filename *smb_fname,
3170 START_PROFILE(syscall_readlinkat);
3172 result = readlinkat(fsp_get_pathref_fd(dirfsp),
3173 smb_fname->base_name,
3177 END_PROFILE(syscall_readlinkat);
3181 static int vfswrap_linkat(vfs_handle_struct *handle,
3182 files_struct *srcfsp,
3183 const struct smb_filename *old_smb_fname,
3184 files_struct *dstfsp,
3185 const struct smb_filename *new_smb_fname,
3190 START_PROFILE(syscall_linkat);
3192 result = linkat(fsp_get_pathref_fd(srcfsp),
3193 old_smb_fname->base_name,
3194 fsp_get_pathref_fd(dstfsp),
3195 new_smb_fname->base_name,
3198 END_PROFILE(syscall_linkat);
3202 static int vfswrap_mknodat(vfs_handle_struct *handle,
3203 files_struct *dirfsp,
3204 const struct smb_filename *smb_fname,
3210 START_PROFILE(syscall_mknodat);
3212 result = sys_mknodat(fsp_get_pathref_fd(dirfsp),
3213 smb_fname->base_name,
3217 END_PROFILE(syscall_mknodat);
3221 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
3223 const struct smb_filename *smb_fname)
3226 struct smb_filename *result_fname = NULL;
3228 START_PROFILE(syscall_realpath);
3229 result = sys_realpath(smb_fname->base_name);
3230 END_PROFILE(syscall_realpath);
3232 result_fname = synthetic_smb_fname(ctx,
3240 return result_fname;
3243 static int vfswrap_fchflags(vfs_handle_struct *handle,
3244 struct files_struct *fsp,
3247 #ifdef HAVE_FCHFLAGS
3248 int fd = fsp_get_pathref_fd(fsp);
3250 if (!fsp->fsp_flags.is_pathref) {
3251 return fchflags(fd, flags);
3254 if (fsp->fsp_flags.have_proc_fds) {
3255 const char *p = NULL;
3258 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3263 return chflags(p, flags);
3267 * This is no longer a handle based call.
3269 return chflags(fsp->fsp_name->base_name, flags);
3276 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
3277 const SMB_STRUCT_STAT *sbuf)
3281 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
3285 key.devid = sbuf->st_ex_dev;
3286 key.inode = sbuf->st_ex_ino;
3287 /* key.extid is unused by default. */
3292 static uint64_t vfswrap_fs_file_id(struct vfs_handle_struct *handle,
3293 const SMB_STRUCT_STAT *psbuf)
3297 if (!(psbuf->st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)) {
3298 return psbuf->st_ex_file_id;
3301 if (handle->conn->base_share_dev == psbuf->st_ex_dev) {
3302 return (uint64_t)psbuf->st_ex_ino;
3306 file_id = ((psbuf->st_ex_ino) & UINT32_MAX);
3309 file_id |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32;
3314 static NTSTATUS vfswrap_fstreaminfo(vfs_handle_struct *handle,
3315 struct files_struct *fsp,
3316 TALLOC_CTX *mem_ctx,
3317 unsigned int *pnum_streams,
3318 struct stream_struct **pstreams)
3320 struct stream_struct *tmp_streams = NULL;
3321 unsigned int num_streams = *pnum_streams;
3322 struct stream_struct *streams = *pstreams;
3325 if (fsp->fsp_flags.is_directory) {
3327 * No default streams on directories
3331 status = vfs_stat_fsp(fsp);
3332 if (!NT_STATUS_IS_OK(status)) {
3336 if (num_streams + 1 < 1) {
3338 return NT_STATUS_INVALID_PARAMETER;
3341 tmp_streams = talloc_realloc(mem_ctx,
3343 struct stream_struct,
3345 if (tmp_streams == NULL) {
3346 return NT_STATUS_NO_MEMORY;
3348 tmp_streams[num_streams].name = talloc_strdup(tmp_streams, "::$DATA");
3349 if (tmp_streams[num_streams].name == NULL) {
3350 return NT_STATUS_NO_MEMORY;
3352 tmp_streams[num_streams].size = fsp->fsp_name->st.st_ex_size;
3353 tmp_streams[num_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(
3356 &fsp->fsp_name->st);
3359 *pnum_streams = num_streams;
3360 *pstreams = tmp_streams;
3362 return NT_STATUS_OK;
3365 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
3366 const struct smb_filename *path,
3368 TALLOC_CTX *mem_ctx,
3372 * Don't fall back to get_real_filename so callers can differentiate
3373 * between a full directory scan and an actual case-insensitive stat.
3379 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
3380 const struct smb_filename *smb_fname)
3382 return handle->conn->connectpath;
3385 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
3386 struct byte_range_lock *br_lck,
3387 struct lock_struct *plock)
3389 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3391 /* Note: blr is not used in the default implementation. */
3392 return brl_lock_windows_default(br_lck, plock);
3395 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
3396 struct byte_range_lock *br_lck,
3397 const struct lock_struct *plock)
3399 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3401 return brl_unlock_windows_default(br_lck, plock);
3404 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
3406 struct lock_struct *plock)
3408 SMB_ASSERT(plock->lock_type == READ_LOCK ||
3409 plock->lock_type == WRITE_LOCK);
3411 return strict_lock_check_default(fsp, plock);
3414 /* NT ACL operations. */
3416 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
3418 uint32_t security_info,
3419 TALLOC_CTX *mem_ctx,
3420 struct security_descriptor **ppdesc)
3424 START_PROFILE(fget_nt_acl);
3425 result = posix_fget_nt_acl(fsp, security_info,
3427 END_PROFILE(fget_nt_acl);
3431 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
3435 START_PROFILE(fset_nt_acl);
3436 result = set_nt_acl(fsp, security_info_sent, psd);
3437 END_PROFILE(fset_nt_acl);
3441 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
3442 struct smb_filename *file,
3443 struct security_acl *sacl,
3444 uint32_t access_requested,
3445 uint32_t access_denied)
3447 return NT_STATUS_OK; /* Nothing to do here ... */
3450 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
3452 SMB_ACL_TYPE_T type,
3453 TALLOC_CTX *mem_ctx)
3455 return sys_acl_get_fd(handle, fsp, type, mem_ctx);
3458 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle,
3460 SMB_ACL_TYPE_T type,
3463 return sys_acl_set_fd(handle, fsp, type, theacl);
3466 static int vfswrap_sys_acl_delete_def_fd(vfs_handle_struct *handle,
3469 return sys_acl_delete_def_fd(handle, fsp);
3472 /****************************************************************
3473 Extended attribute operations.
3474 *****************************************************************/
3476 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle,
3477 struct files_struct *fsp,
3482 int fd = fsp_get_pathref_fd(fsp);
3484 if (!fsp->fsp_flags.is_pathref) {
3485 return fgetxattr(fd, name, value, size);
3488 if (fsp->fsp_flags.have_proc_fds) {
3489 const char *p = NULL;
3492 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3497 return getxattr(p, name, value, size);
3501 * This is no longer a handle based call.
3503 return getxattr(fsp->fsp_name->base_name, name, value, size);
3506 struct vfswrap_getxattrat_state {
3507 struct tevent_context *ev;
3508 struct vfs_handle_struct *handle;
3509 files_struct *dir_fsp;
3510 const struct smb_filename *smb_fname;
3513 * The following variables are talloced off "state" which is protected
3514 * by a destructor and thus are guaranteed to be safe to be used in the
3515 * job function in the worker thread.
3518 const char *xattr_name;
3519 uint8_t *xattr_value;
3520 struct security_unix_token *token;
3523 struct vfs_aio_state vfs_aio_state;
3524 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
3527 static int vfswrap_getxattrat_state_destructor(
3528 struct vfswrap_getxattrat_state *state)
3533 static void vfswrap_getxattrat_do_sync(struct tevent_req *req);
3534 static void vfswrap_getxattrat_do_async(void *private_data);
3535 static void vfswrap_getxattrat_done(struct tevent_req *subreq);
3537 static struct tevent_req *vfswrap_getxattrat_send(
3538 TALLOC_CTX *mem_ctx,
3539 struct tevent_context *ev,
3540 struct vfs_handle_struct *handle,
3541 files_struct *dir_fsp,
3542 const struct smb_filename *smb_fname,
3543 const char *xattr_name,
3546 struct tevent_req *req = NULL;
3547 struct tevent_req *subreq = NULL;
3548 struct vfswrap_getxattrat_state *state = NULL;
3549 size_t max_threads = 0;
3550 bool have_per_thread_cwd = false;
3551 bool have_per_thread_creds = false;
3552 bool do_async = false;
3554 req = tevent_req_create(mem_ctx, &state,
3555 struct vfswrap_getxattrat_state);
3559 *state = (struct vfswrap_getxattrat_state) {
3563 .smb_fname = smb_fname,
3566 max_threads = pthreadpool_tevent_max_threads(dir_fsp->conn->sconn->pool);
3567 if (max_threads >= 1) {
3569 * We need a non sync threadpool!
3571 have_per_thread_cwd = per_thread_cwd_supported();
3573 #ifdef HAVE_LINUX_THREAD_CREDENTIALS
3574 have_per_thread_creds = true;
3576 if (have_per_thread_cwd && have_per_thread_creds) {
3580 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat, profile_p,
3581 state->profile_bytes, 0);
3583 if (fsp_get_pathref_fd(dir_fsp) == -1) {
3584 DBG_ERR("Need a valid directory fd\n");
3585 tevent_req_error(req, EINVAL);
3586 return tevent_req_post(req, ev);
3589 if (alloc_hint > 0) {
3590 state->xattr_value = talloc_zero_array(state,
3593 if (tevent_req_nomem(state->xattr_value, req)) {
3594 return tevent_req_post(req, ev);
3599 vfswrap_getxattrat_do_sync(req);
3600 return tevent_req_post(req, ev);
3604 * Now allocate all parameters from a memory context that won't go away
3605 * no matter what. These paremeters will get used in threads and we
3606 * can't reliably cancel threads, so all buffers passed to the threads
3607 * must not be freed before all referencing threads terminate.
3610 state->name = talloc_strdup(state, smb_fname->base_name);
3611 if (tevent_req_nomem(state->name, req)) {
3612 return tevent_req_post(req, ev);
3615 state->xattr_name = talloc_strdup(state, xattr_name);
3616 if (tevent_req_nomem(state->xattr_name, req)) {
3617 return tevent_req_post(req, ev);
3621 * This is a hot codepath so at first glance one might think we should
3622 * somehow optimize away the token allocation and do a
3623 * talloc_reference() or similar black magic instead. But due to the
3624 * talloc_stackframe pool per SMB2 request this should be a simple copy
3625 * without a malloc in most cases.
3627 if (geteuid() == sec_initial_uid()) {
3628 state->token = root_unix_token(state);
3630 state->token = copy_unix_token(
3632 dir_fsp->conn->session_info->unix_token);
3634 if (tevent_req_nomem(state->token, req)) {
3635 return tevent_req_post(req, ev);
3638 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3640 subreq = pthreadpool_tevent_job_send(
3643 dir_fsp->conn->sconn->pool,
3644 vfswrap_getxattrat_do_async,
3646 if (tevent_req_nomem(subreq, req)) {
3647 return tevent_req_post(req, ev);
3649 tevent_req_set_callback(subreq, vfswrap_getxattrat_done, req);
3651 talloc_set_destructor(state, vfswrap_getxattrat_state_destructor);
3656 static void vfswrap_getxattrat_do_sync(struct tevent_req *req)
3658 struct vfswrap_getxattrat_state *state = tevent_req_data(
3659 req, struct vfswrap_getxattrat_state);
3660 struct files_struct *fsp = metadata_fsp(state->smb_fname->fsp);
3662 state->xattr_size = vfswrap_fgetxattr(state->handle,
3666 talloc_array_length(state->xattr_value));
3667 if (state->xattr_size == -1) {
3668 tevent_req_error(req, errno);
3672 tevent_req_done(req);
3676 static void vfswrap_getxattrat_do_async(void *private_data)
3678 struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3679 private_data, struct vfswrap_getxattrat_state);
3680 struct timespec start_time;
3681 struct timespec end_time;
3683 struct files_struct *fsp = metadata_fsp(state->smb_fname->fsp);
3685 PROFILE_TIMESTAMP(&start_time);
3686 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
3689 * Here we simulate a getxattrat()
3690 * call using fchdir();getxattr()
3693 per_thread_cwd_activate();
3695 /* Become the correct credential on this thread. */
3696 ret = set_thread_credentials(state->token->uid,
3698 (size_t)state->token->ngroups,
3699 state->token->groups);
3701 state->xattr_size = -1;
3702 state->vfs_aio_state.error = errno;
3706 state->xattr_size = vfswrap_fgetxattr(state->handle,
3710 talloc_array_length(state->xattr_value));
3711 if (state->xattr_size == -1) {
3712 state->vfs_aio_state.error = errno;
3716 PROFILE_TIMESTAMP(&end_time);
3717 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
3718 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3721 static void vfswrap_getxattrat_done(struct tevent_req *subreq)
3723 struct tevent_req *req = tevent_req_callback_data(
3724 subreq, struct tevent_req);
3725 struct vfswrap_getxattrat_state *state = tevent_req_data(
3726 req, struct vfswrap_getxattrat_state);
3731 * Make sure we run as the user again
3733 ok = change_to_user_and_service_by_fsp(state->dir_fsp);
3736 ret = pthreadpool_tevent_job_recv(subreq);
3737 TALLOC_FREE(subreq);
3738 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
3739 talloc_set_destructor(state, NULL);
3741 if (ret != EAGAIN) {
3742 tevent_req_error(req, ret);
3746 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
3747 * means the lower level pthreadpool failed to create a new
3748 * thread. Fallback to sync processing in that case to allow
3749 * some progress for the client.
3751 vfswrap_getxattrat_do_sync(req);
3755 if (state->xattr_size == -1) {
3756 tevent_req_error(req, state->vfs_aio_state.error);
3760 if (state->xattr_value == NULL) {
3762 * The caller only wanted the size.
3764 tevent_req_done(req);
3769 * shrink the buffer to the returned size.
3770 * (can't fail). It means NULL if size is 0.
3772 state->xattr_value = talloc_realloc(state,
3777 tevent_req_done(req);
3780 static ssize_t vfswrap_getxattrat_recv(struct tevent_req *req,
3781 struct vfs_aio_state *aio_state,
3782 TALLOC_CTX *mem_ctx,
3783 uint8_t **xattr_value)
3785 struct vfswrap_getxattrat_state *state = tevent_req_data(
3786 req, struct vfswrap_getxattrat_state);
3789 if (tevent_req_is_unix_error(req, &aio_state->error)) {
3790 tevent_req_received(req);
3794 *aio_state = state->vfs_aio_state;
3795 xattr_size = state->xattr_size;
3796 if (xattr_value != NULL) {
3797 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
3800 tevent_req_received(req);
3804 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
3806 int fd = fsp_get_pathref_fd(fsp);
3808 if (!fsp->fsp_flags.is_pathref) {
3809 return flistxattr(fd, list, size);
3812 if (fsp->fsp_flags.have_proc_fds) {
3813 const char *p = NULL;
3816 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3821 return listxattr(p, list, size);
3825 * This is no longer a handle based call.
3827 return listxattr(fsp->fsp_name->base_name, list, size);
3830 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
3832 int fd = fsp_get_pathref_fd(fsp);
3834 if (!fsp->fsp_flags.is_pathref) {
3835 return fremovexattr(fd, name);
3838 if (fsp->fsp_flags.have_proc_fds) {
3839 const char *p = NULL;
3842 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3847 return removexattr(p, name);
3851 * This is no longer a handle based call.
3853 return removexattr(fsp->fsp_name->base_name, name);
3856 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
3858 int fd = fsp_get_pathref_fd(fsp);
3860 if (!fsp->fsp_flags.is_pathref) {
3861 return fsetxattr(fd, name, value, size, flags);
3864 if (fsp->fsp_flags.have_proc_fds) {
3865 const char *p = NULL;
3868 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3873 return setxattr(p, name, value, size, flags);
3877 * This is no longer a handle based call.
3879 return setxattr(fsp->fsp_name->base_name, name, value, size, flags);
3882 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
3887 static bool vfswrap_is_offline(struct connection_struct *conn,
3888 const struct smb_filename *fname)
3892 bool offline = false;
3894 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
3898 if (!lp_dmapi_support(SNUM(conn)) || !dmapi_have_session()) {
3899 #if defined(ENOTSUP)
3905 status = get_full_smb_filename(talloc_tos(), fname, &path);
3906 if (!NT_STATUS_IS_OK(status)) {
3907 errno = map_errno_from_nt_status(status);
3911 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
3918 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
3919 struct files_struct *fsp,
3920 TALLOC_CTX *mem_ctx,
3923 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
3926 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
3927 struct files_struct *fsp,
3928 const DATA_BLOB old_cookie,
3929 TALLOC_CTX *mem_ctx,
3930 DATA_BLOB *new_cookie)
3932 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
3936 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
3937 struct smb_request *smb1req,
3938 struct smbXsrv_open *op,
3939 const DATA_BLOB old_cookie,
3940 TALLOC_CTX *mem_ctx,
3941 struct files_struct **fsp,
3942 DATA_BLOB *new_cookie)
3944 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
3945 old_cookie, mem_ctx,
3949 static struct vfs_fn_pointers vfs_default_fns = {
3950 /* Disk operations */
3952 .connect_fn = vfswrap_connect,
3953 .disconnect_fn = vfswrap_disconnect,
3954 .disk_free_fn = vfswrap_disk_free,
3955 .get_quota_fn = vfswrap_get_quota,
3956 .set_quota_fn = vfswrap_set_quota,
3957 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3958 .statvfs_fn = vfswrap_statvfs,
3959 .fs_capabilities_fn = vfswrap_fs_capabilities,
3960 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3961 .create_dfs_pathat_fn = vfswrap_create_dfs_pathat,
3962 .read_dfs_pathat_fn = vfswrap_read_dfs_pathat,
3963 .snap_check_path_fn = vfswrap_snap_check_path,
3964 .snap_create_fn = vfswrap_snap_create,
3965 .snap_delete_fn = vfswrap_snap_delete,
3967 /* Directory operations */
3969 .fdopendir_fn = vfswrap_fdopendir,
3970 .readdir_fn = vfswrap_readdir,
3971 .freaddir_attr_fn = vfswrap_freaddir_attr,
3972 .seekdir_fn = vfswrap_seekdir,
3973 .telldir_fn = vfswrap_telldir,
3974 .rewind_dir_fn = vfswrap_rewinddir,
3975 .mkdirat_fn = vfswrap_mkdirat,
3976 .closedir_fn = vfswrap_closedir,
3978 /* File operations */
3980 .openat_fn = vfswrap_openat,
3981 .create_file_fn = vfswrap_create_file,
3982 .close_fn = vfswrap_close,
3983 .pread_fn = vfswrap_pread,
3984 .pread_send_fn = vfswrap_pread_send,
3985 .pread_recv_fn = vfswrap_pread_recv,
3986 .pwrite_fn = vfswrap_pwrite,
3987 .pwrite_send_fn = vfswrap_pwrite_send,
3988 .pwrite_recv_fn = vfswrap_pwrite_recv,
3989 .lseek_fn = vfswrap_lseek,
3990 .sendfile_fn = vfswrap_sendfile,
3991 .recvfile_fn = vfswrap_recvfile,
3992 .renameat_fn = vfswrap_renameat,
3993 .fsync_send_fn = vfswrap_fsync_send,
3994 .fsync_recv_fn = vfswrap_fsync_recv,
3995 .stat_fn = vfswrap_stat,
3996 .fstat_fn = vfswrap_fstat,
3997 .lstat_fn = vfswrap_lstat,
3998 .fstatat_fn = vfswrap_fstatat,
3999 .get_alloc_size_fn = vfswrap_get_alloc_size,
4000 .unlinkat_fn = vfswrap_unlinkat,
4001 .fchmod_fn = vfswrap_fchmod,
4002 .fchown_fn = vfswrap_fchown,
4003 .lchown_fn = vfswrap_lchown,
4004 .chdir_fn = vfswrap_chdir,
4005 .getwd_fn = vfswrap_getwd,
4006 .fntimes_fn = vfswrap_fntimes,
4007 .ftruncate_fn = vfswrap_ftruncate,
4008 .fallocate_fn = vfswrap_fallocate,
4009 .lock_fn = vfswrap_lock,
4010 .filesystem_sharemode_fn = vfswrap_filesystem_sharemode,
4011 .fcntl_fn = vfswrap_fcntl,
4012 .linux_setlease_fn = vfswrap_linux_setlease,
4013 .getlock_fn = vfswrap_getlock,
4014 .symlinkat_fn = vfswrap_symlinkat,
4015 .readlinkat_fn = vfswrap_readlinkat,
4016 .linkat_fn = vfswrap_linkat,
4017 .mknodat_fn = vfswrap_mknodat,
4018 .realpath_fn = vfswrap_realpath,
4019 .fchflags_fn = vfswrap_fchflags,
4020 .file_id_create_fn = vfswrap_file_id_create,
4021 .fs_file_id_fn = vfswrap_fs_file_id,
4022 .fstreaminfo_fn = vfswrap_fstreaminfo,
4023 .get_real_filename_fn = vfswrap_get_real_filename,
4024 .connectpath_fn = vfswrap_connectpath,
4025 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
4026 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
4027 .strict_lock_check_fn = vfswrap_strict_lock_check,
4028 .translate_name_fn = vfswrap_translate_name,
4029 .parent_pathname_fn = vfswrap_parent_pathname,
4030 .fsctl_fn = vfswrap_fsctl,
4031 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
4032 .get_dos_attributes_send_fn = vfswrap_get_dos_attributes_send,
4033 .get_dos_attributes_recv_fn = vfswrap_get_dos_attributes_recv,
4034 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
4035 .offload_read_send_fn = vfswrap_offload_read_send,
4036 .offload_read_recv_fn = vfswrap_offload_read_recv,
4037 .offload_write_send_fn = vfswrap_offload_write_send,
4038 .offload_write_recv_fn = vfswrap_offload_write_recv,
4039 .fget_compression_fn = vfswrap_fget_compression,
4040 .set_compression_fn = vfswrap_set_compression,
4042 /* NT ACL operations. */
4044 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
4045 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
4046 .audit_file_fn = vfswrap_audit_file,
4048 /* POSIX ACL operations. */
4050 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
4051 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
4052 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
4053 .sys_acl_delete_def_fd_fn = vfswrap_sys_acl_delete_def_fd,
4055 /* EA operations. */
4056 .getxattrat_send_fn = vfswrap_getxattrat_send,
4057 .getxattrat_recv_fn = vfswrap_getxattrat_recv,
4058 .fgetxattr_fn = vfswrap_fgetxattr,
4059 .flistxattr_fn = vfswrap_flistxattr,
4060 .fremovexattr_fn = vfswrap_fremovexattr,
4061 .fsetxattr_fn = vfswrap_fsetxattr,
4063 /* aio operations */
4064 .aio_force_fn = vfswrap_aio_force,
4066 /* durable handle operations */
4067 .durable_cookie_fn = vfswrap_durable_cookie,
4068 .durable_disconnect_fn = vfswrap_durable_disconnect,
4069 .durable_reconnect_fn = vfswrap_durable_reconnect,
4073 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
4076 * Here we need to implement every call!
4078 * As this is the end of the vfs module chain.
4080 smb_vfs_assert_all_fns(&vfs_default_fns, DEFAULT_VFS_MODULE_NAME);
4081 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
4082 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);