2 Unix SMB/CIFS implementation.
3 Wrap disk only vfs functions to sidestep dodgy compilers.
4 Copyright (C) Tim Potter 1998
5 Copyright (C) Jeremy Allison 2007
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "system/time.h"
23 #include "system/filesys.h"
24 #include "smbd/smbd.h"
25 #include "smbd/globals.h"
27 #include "smbprofile.h"
28 #include "../libcli/security/security.h"
29 #include "passdb/lookup_sid.h"
30 #include "source3/include/msdfs.h"
31 #include "librpc/gen_ndr/ndr_dfsblobs.h"
32 #include "lib/util/tevent_unix.h"
33 #include "lib/util/tevent_ntstatus.h"
34 #include "lib/util/sys_rw.h"
35 #include "lib/pthreadpool/pthreadpool_tevent.h"
36 #include "librpc/gen_ndr/ndr_ioctl.h"
37 #include "offload_token.h"
38 #include "util_reparse.h"
39 #include "lib/util/string_wrappers.h"
42 #define DBGC_CLASS DBGC_VFS
44 /* Check for NULL pointer parameters in vfswrap_* functions */
46 /* We don't want to have NULL function pointers lying around. Someone
47 is sure to try and execute them. These stubs are used to prevent
50 static int vfswrap_connect(vfs_handle_struct *handle, const char *service, const char *user)
52 handle->conn->have_proc_fds = sys_have_proc_fds();
53 return 0; /* Return >= 0 for success */
56 static void vfswrap_disconnect(vfs_handle_struct *handle)
62 static uint64_t vfswrap_disk_free(vfs_handle_struct *handle,
63 const struct smb_filename *smb_fname,
68 if (sys_fsusage(smb_fname->base_name, dfree, dsize) != 0) {
76 static int vfswrap_get_quota(struct vfs_handle_struct *handle,
77 const struct smb_filename *smb_fname,
78 enum SMB_QUOTA_TYPE qtype,
82 #ifdef HAVE_SYS_QUOTAS
85 START_PROFILE(syscall_get_quota);
86 result = sys_get_quota(smb_fname->base_name, qtype, id, qt);
87 END_PROFILE(syscall_get_quota);
95 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
97 #ifdef HAVE_SYS_QUOTAS
100 START_PROFILE(syscall_set_quota);
101 result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
102 END_PROFILE(syscall_set_quota);
110 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
111 struct files_struct *fsp,
112 struct shadow_copy_data *shadow_copy_data,
116 return -1; /* Not implemented. */
119 static int vfswrap_statvfs(struct vfs_handle_struct *handle,
120 const struct smb_filename *smb_fname,
121 vfs_statvfs_struct *statbuf)
123 return sys_statvfs(smb_fname->base_name, statbuf);
126 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
127 enum timestamp_set_resolution *p_ts_res)
129 const struct loadparm_substitution *lp_sub =
130 loadparm_s3_global_substitution();
131 connection_struct *conn = handle->conn;
132 uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
133 struct smb_filename *smb_fname_cpath = NULL;
134 struct vfs_statvfs_struct statbuf;
137 smb_fname_cpath = synthetic_smb_fname(talloc_tos(),
143 if (smb_fname_cpath == NULL) {
147 ZERO_STRUCT(statbuf);
148 ret = SMB_VFS_STATVFS(conn, smb_fname_cpath, &statbuf);
150 caps = statbuf.FsCapabilities;
153 *p_ts_res = TIMESTAMP_SET_SECONDS;
155 /* Work out what timestamp resolution we can
156 * use when setting a timestamp. */
158 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
160 TALLOC_FREE(smb_fname_cpath);
164 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
165 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
166 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
167 /* If any of the normal UNIX directory timestamps
168 * have a non-zero tv_nsec component assume
169 * we might be able to set sub-second timestamps.
170 * See what filetime set primitives we have.
172 #if defined(HAVE_UTIMENSAT)
173 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
174 #elif defined(HAVE_UTIMES)
175 /* utimes allows msec timestamps to be set. */
176 *p_ts_res = TIMESTAMP_SET_MSEC;
177 #elif defined(HAVE_UTIME)
178 /* utime only allows sec timestamps to be set. */
179 *p_ts_res = TIMESTAMP_SET_SECONDS;
182 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
184 "available on share %s, directory %s\n",
185 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
186 lp_servicename(talloc_tos(), lp_sub, conn->params->service),
187 conn->connectpath ));
189 TALLOC_FREE(smb_fname_cpath);
193 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
194 struct dfs_GetDFSReferral *r)
196 struct junction_map *junction = NULL;
198 bool self_referral = false;
199 char *pathnamep = NULL;
200 char *local_dfs_path = NULL;
203 uint16_t max_referral_level = r->in.req.max_referral_level;
206 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
209 /* get the junction entry */
210 if (r->in.req.servername == NULL) {
211 return NT_STATUS_NOT_FOUND;
215 * Trim pathname sent by client so it begins with only one backslash.
216 * Two backslashes confuse some dfs clients
219 local_dfs_path = talloc_strdup(r, r->in.req.servername);
220 if (local_dfs_path == NULL) {
221 return NT_STATUS_NO_MEMORY;
223 pathnamep = local_dfs_path;
224 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
225 IS_DIRECTORY_SEP(pathnamep[1])) {
229 junction = talloc_zero(r, struct junction_map);
230 if (junction == NULL) {
231 return NT_STATUS_NO_MEMORY;
234 /* The following call can change cwd. */
235 status = get_referred_path(r,
236 handle->conn->session_info,
238 handle->conn->sconn->remote_address,
239 handle->conn->sconn->local_address,
240 !handle->conn->sconn->using_smb2,
241 junction, &consumedcnt, &self_referral);
242 if (!NT_STATUS_IS_OK(status)) {
243 struct smb_filename connectpath_fname = {
244 .base_name = handle->conn->connectpath
246 vfs_ChDir(handle->conn, &connectpath_fname);
250 struct smb_filename connectpath_fname = {
251 .base_name = handle->conn->connectpath
253 vfs_ChDir(handle->conn, &connectpath_fname);
256 if (!self_referral) {
257 pathnamep[consumedcnt] = '\0';
260 dbgtext("Path %s to alternate path(s):",
262 for (i=0; i < junction->referral_count; i++) {
264 junction->referral_list[i].alternate_path);
270 if (r->in.req.max_referral_level <= 2) {
271 max_referral_level = 2;
273 if (r->in.req.max_referral_level >= 3) {
274 max_referral_level = 3;
277 r->out.resp = talloc_zero(r, struct dfs_referral_resp);
278 if (r->out.resp == NULL) {
279 return NT_STATUS_NO_MEMORY;
282 r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
283 r->out.resp->nb_referrals = junction->referral_count;
285 r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
287 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
290 r->out.resp->referral_entries = talloc_zero_array(r,
291 struct dfs_referral_type,
292 r->out.resp->nb_referrals);
293 if (r->out.resp->referral_entries == NULL) {
294 return NT_STATUS_NO_MEMORY;
297 switch (max_referral_level) {
299 for(i=0; i < junction->referral_count; i++) {
300 struct referral *ref = &junction->referral_list[i];
301 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
302 struct dfs_referral_type *t =
303 &r->out.resp->referral_entries[i];
304 struct dfs_referral_v2 *v2 = &t->referral.v2;
307 v2->size = VERSION2_REFERRAL_SIZE;
309 v2->server_type = DFS_SERVER_ROOT;
311 v2->server_type = DFS_SERVER_NON_ROOT;
314 v2->proximity = ref->proximity;
316 v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
317 if (v2->DFS_path == NULL) {
318 return NT_STATUS_NO_MEMORY;
320 v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
321 if (v2->DFS_alt_path == NULL) {
322 return NT_STATUS_NO_MEMORY;
324 v2->netw_address = talloc_strdup(mem_ctx,
325 ref->alternate_path);
326 if (v2->netw_address == NULL) {
327 return NT_STATUS_NO_MEMORY;
333 for(i=0; i < junction->referral_count; i++) {
334 struct referral *ref = &junction->referral_list[i];
335 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
336 struct dfs_referral_type *t =
337 &r->out.resp->referral_entries[i];
338 struct dfs_referral_v3 *v3 = &t->referral.v3;
339 struct dfs_normal_referral *r1 = &v3->referrals.r1;
342 v3->size = VERSION3_REFERRAL_SIZE;
344 v3->server_type = DFS_SERVER_ROOT;
346 v3->server_type = DFS_SERVER_NON_ROOT;
350 r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
351 if (r1->DFS_path == NULL) {
352 return NT_STATUS_NO_MEMORY;
354 r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
355 if (r1->DFS_alt_path == NULL) {
356 return NT_STATUS_NO_MEMORY;
358 r1->netw_address = talloc_strdup(mem_ctx,
359 ref->alternate_path);
360 if (r1->netw_address == NULL) {
361 return NT_STATUS_NO_MEMORY;
366 DEBUG(0,("Invalid dfs referral version: %d\n",
367 max_referral_level));
368 return NT_STATUS_INVALID_LEVEL;
372 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
378 static NTSTATUS vfswrap_create_dfs_pathat(struct vfs_handle_struct *handle,
379 struct files_struct *dirfsp,
380 const struct smb_filename *smb_fname,
381 const struct referral *reflist,
382 size_t referral_count)
384 TALLOC_CTX *frame = talloc_stackframe();
385 NTSTATUS status = NT_STATUS_NO_MEMORY;
387 char *msdfs_link = NULL;
389 /* Form the msdfs_link contents */
390 msdfs_link = msdfs_link_string(frame,
393 if (msdfs_link == NULL) {
397 ret = symlinkat(msdfs_link,
398 fsp_get_pathref_fd(dirfsp),
399 smb_fname->base_name);
401 status = NT_STATUS_OK;
403 status = map_nt_error_from_unix(errno);
413 * Read and return the contents of a DFS redirect given a
414 * pathname. A caller can pass in NULL for ppreflist and
415 * preferral_count but still determine if this was a
416 * DFS redirect point by getting NT_STATUS_OK back
417 * without incurring the overhead of reading and parsing
418 * the referral contents.
421 static NTSTATUS vfswrap_read_dfs_pathat(struct vfs_handle_struct *handle,
423 struct files_struct *dirfsp,
424 struct smb_filename *smb_fname,
425 struct referral **ppreflist,
426 size_t *preferral_count)
428 NTSTATUS status = NT_STATUS_NO_MEMORY;
430 char *link_target = NULL;
433 #if defined(HAVE_BROKEN_READLINK)
434 char link_target_buf[PATH_MAX];
436 char link_target_buf[7];
440 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
442 if (is_named_stream(smb_fname)) {
443 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
447 if (ppreflist == NULL && preferral_count == NULL) {
449 * We're only checking if this is a DFS
450 * redirect. We don't need to return data.
452 bufsize = sizeof(link_target_buf);
453 link_target = link_target_buf;
456 link_target = talloc_array(mem_ctx, char, bufsize);
462 referral_len = readlinkat(fsp_get_pathref_fd(dirfsp),
463 smb_fname->base_name,
466 if (referral_len == -1) {
467 if (errno == EINVAL) {
469 * If the path isn't a link, readlinkat
470 * returns EINVAL. Allow the caller to
473 DBG_INFO("%s is not a link.\n", smb_fname->base_name);
474 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
476 status = map_nt_error_from_unix(errno);
477 if (errno == ENOENT) {
478 DBG_NOTICE("Error reading "
479 "msdfs link %s: %s\n",
480 smb_fname->base_name,
483 DBG_ERR("Error reading "
484 "msdfs link %s: %s\n",
485 smb_fname->base_name,
491 link_target[referral_len] = '\0';
493 DBG_INFO("%s -> %s\n",
494 smb_fname->base_name,
497 if (!strnequal(link_target, "msdfs:", 6)) {
498 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
502 ret = sys_fstatat(fsp_get_pathref_fd(dirfsp),
503 smb_fname->base_name,
506 lp_fake_directory_create_times(SNUM(handle->conn)));
508 status = map_nt_error_from_unix(errno);
512 if (ppreflist == NULL && preferral_count == NULL) {
513 /* Early return for checking if this is a DFS link. */
517 ok = parse_msdfs_symlink(mem_ctx,
518 lp_msdfs_shuffle_referrals(SNUM(handle->conn)),
524 status = NT_STATUS_OK;
526 status = NT_STATUS_NO_MEMORY;
531 if (link_target != link_target_buf) {
532 TALLOC_FREE(link_target);
537 static NTSTATUS vfswrap_snap_check_path(struct vfs_handle_struct *handle,
539 const char *service_path,
542 return NT_STATUS_NOT_SUPPORTED;
545 static NTSTATUS vfswrap_snap_create(struct vfs_handle_struct *handle,
547 const char *base_volume,
553 return NT_STATUS_NOT_SUPPORTED;
556 static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle,
561 return NT_STATUS_NOT_SUPPORTED;
564 /* Directory operations */
566 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
573 START_PROFILE(syscall_fdopendir);
574 result = sys_fdopendir(fsp_get_io_fd(fsp));
575 END_PROFILE(syscall_fdopendir);
580 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
581 struct files_struct *dirfsp,
583 SMB_STRUCT_STAT *sbuf)
585 struct dirent *result;
586 bool fake_ctime = lp_fake_directory_create_times(SNUM(handle->conn));
587 int flags = AT_SYMLINK_NOFOLLOW;
591 START_PROFILE(syscall_readdir);
593 result = readdir(dirp);
594 END_PROFILE(syscall_readdir);
599 if (result == NULL) {
604 * Default Posix readdir() does not give us stat info.
605 * Set to invalid to indicate we didn't return this info.
607 SET_STAT_INVALID(*sbuf);
609 ret = sys_fstatat(dirfd(dirp),
619 * As this is an optimization, ignore it if we stat'ed a
620 * symlink for non-POSIX context. Make the caller do it again
621 * as we don't know if they wanted the link info, or its
624 if (S_ISLNK(st.st_ex_mode) &&
625 !(dirfsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH))
634 static NTSTATUS vfswrap_freaddir_attr(struct vfs_handle_struct *handle,
635 struct files_struct *fsp,
637 struct readdir_attr_data **attr_data)
639 return NT_STATUS_NOT_SUPPORTED;
642 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
644 START_PROFILE(syscall_seekdir);
645 seekdir(dirp, offset);
646 END_PROFILE(syscall_seekdir);
649 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
652 START_PROFILE(syscall_telldir);
653 result = telldir(dirp);
654 END_PROFILE(syscall_telldir);
658 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
660 START_PROFILE(syscall_rewinddir);
662 END_PROFILE(syscall_rewinddir);
665 static int vfswrap_mkdirat(vfs_handle_struct *handle,
666 struct files_struct *dirfsp,
667 const struct smb_filename *smb_fname,
672 START_PROFILE(syscall_mkdirat);
674 result = mkdirat(fsp_get_pathref_fd(dirfsp), smb_fname->base_name, mode);
676 END_PROFILE(syscall_mkdirat);
680 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
684 START_PROFILE(syscall_closedir);
685 result = closedir(dirp);
686 END_PROFILE(syscall_closedir);
690 /* File operations */
692 static int vfswrap_openat(vfs_handle_struct *handle,
693 const struct files_struct *dirfsp,
694 const struct smb_filename *smb_fname,
699 bool have_opath = false;
700 bool became_root = false;
703 START_PROFILE(syscall_openat);
705 if (is_named_stream(smb_fname)) {
713 if (fsp->fsp_flags.is_pathref) {
718 if (fsp->fsp_flags.is_pathref && !have_opath) {
723 result = openat(fsp_get_pathref_fd(dirfsp),
724 smb_fname->base_name,
732 fsp->fsp_flags.have_proc_fds = fsp->conn->have_proc_fds;
735 END_PROFILE(syscall_openat);
738 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
739 struct smb_request *req,
740 struct smb_filename *smb_fname,
741 uint32_t access_mask,
742 uint32_t share_access,
743 uint32_t create_disposition,
744 uint32_t create_options,
745 uint32_t file_attributes,
746 uint32_t oplock_request,
747 const struct smb2_lease *lease,
748 uint64_t allocation_size,
749 uint32_t private_flags,
750 struct security_descriptor *sd,
751 struct ea_list *ea_list,
752 files_struct **result,
754 const struct smb2_create_blobs *in_context_blobs,
755 struct smb2_create_blobs *out_context_blobs)
757 return create_file_default(handle->conn, req, smb_fname,
758 access_mask, share_access,
759 create_disposition, create_options,
760 file_attributes, oplock_request, lease,
761 allocation_size, private_flags,
763 pinfo, in_context_blobs, out_context_blobs);
766 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
770 START_PROFILE(syscall_close);
771 result = fd_close_posix(fsp);
772 END_PROFILE(syscall_close);
776 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
777 size_t n, off_t offset)
781 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
782 START_PROFILE_BYTES(syscall_pread, n);
783 result = sys_pread_full(fsp_get_io_fd(fsp), data, n, offset);
784 END_PROFILE_BYTES(syscall_pread);
786 if (result == -1 && errno == ESPIPE) {
787 /* Maintain the fiction that pipes can be seeked (sought?) on. */
788 result = sys_read(fsp_get_io_fd(fsp), data, n);
789 fh_set_pos(fsp->fh, 0);
792 #else /* HAVE_PREAD */
795 #endif /* HAVE_PREAD */
800 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
801 size_t n, off_t offset)
805 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
806 START_PROFILE_BYTES(syscall_pwrite, n);
807 result = sys_pwrite_full(fsp_get_io_fd(fsp), data, n, offset);
808 END_PROFILE_BYTES(syscall_pwrite);
810 if (result == -1 && errno == ESPIPE) {
811 /* Maintain the fiction that pipes can be sought on. */
812 result = sys_write(fsp_get_io_fd(fsp), data, n);
815 #else /* HAVE_PWRITE */
818 #endif /* HAVE_PWRITE */
823 struct vfswrap_pread_state {
830 struct vfs_aio_state vfs_aio_state;
831 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
834 static void vfs_pread_do(void *private_data);
835 static void vfs_pread_done(struct tevent_req *subreq);
836 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state);
838 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
840 struct tevent_context *ev,
841 struct files_struct *fsp,
843 size_t n, off_t offset)
845 struct tevent_req *req, *subreq;
846 struct vfswrap_pread_state *state;
848 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
854 state->fd = fsp_get_io_fd(fsp);
857 state->offset = offset;
859 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
860 state->profile_bytes, n);
861 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
863 subreq = pthreadpool_tevent_job_send(
864 state, ev, handle->conn->sconn->pool,
865 vfs_pread_do, state);
866 if (tevent_req_nomem(subreq, req)) {
867 return tevent_req_post(req, ev);
869 tevent_req_set_callback(subreq, vfs_pread_done, req);
871 talloc_set_destructor(state, vfs_pread_state_destructor);
876 static void vfs_pread_do(void *private_data)
878 struct vfswrap_pread_state *state = talloc_get_type_abort(
879 private_data, struct vfswrap_pread_state);
880 struct timespec start_time;
881 struct timespec end_time;
883 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
885 PROFILE_TIMESTAMP(&start_time);
887 state->ret = sys_pread_full(state->fd,
892 if (state->ret == -1) {
893 state->vfs_aio_state.error = errno;
896 PROFILE_TIMESTAMP(&end_time);
898 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
900 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
903 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state)
908 static void vfs_pread_done(struct tevent_req *subreq)
910 struct tevent_req *req = tevent_req_callback_data(
911 subreq, struct tevent_req);
912 struct vfswrap_pread_state *state = tevent_req_data(
913 req, struct vfswrap_pread_state);
916 ret = pthreadpool_tevent_job_recv(subreq);
918 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
919 talloc_set_destructor(state, NULL);
922 tevent_req_error(req, ret);
926 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
927 * means the lower level pthreadpool failed to create a new
928 * thread. Fallback to sync processing in that case to allow
929 * some progress for the client.
934 tevent_req_done(req);
937 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
938 struct vfs_aio_state *vfs_aio_state)
940 struct vfswrap_pread_state *state = tevent_req_data(
941 req, struct vfswrap_pread_state);
943 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
947 *vfs_aio_state = state->vfs_aio_state;
951 struct vfswrap_pwrite_state {
958 struct vfs_aio_state vfs_aio_state;
959 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
962 static void vfs_pwrite_do(void *private_data);
963 static void vfs_pwrite_done(struct tevent_req *subreq);
964 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state);
966 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
968 struct tevent_context *ev,
969 struct files_struct *fsp,
971 size_t n, off_t offset)
973 struct tevent_req *req, *subreq;
974 struct vfswrap_pwrite_state *state;
976 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
982 state->fd = fsp_get_io_fd(fsp);
985 state->offset = offset;
987 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
988 state->profile_bytes, n);
989 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
991 subreq = pthreadpool_tevent_job_send(
992 state, ev, handle->conn->sconn->pool,
993 vfs_pwrite_do, state);
994 if (tevent_req_nomem(subreq, req)) {
995 return tevent_req_post(req, ev);
997 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
999 talloc_set_destructor(state, vfs_pwrite_state_destructor);
1004 static void vfs_pwrite_do(void *private_data)
1006 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
1007 private_data, struct vfswrap_pwrite_state);
1008 struct timespec start_time;
1009 struct timespec end_time;
1011 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
1013 PROFILE_TIMESTAMP(&start_time);
1015 state->ret = sys_pwrite_full(state->fd,
1020 if (state->ret == -1) {
1021 state->vfs_aio_state.error = errno;
1024 PROFILE_TIMESTAMP(&end_time);
1026 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1028 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1031 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state)
1036 static void vfs_pwrite_done(struct tevent_req *subreq)
1038 struct tevent_req *req = tevent_req_callback_data(
1039 subreq, struct tevent_req);
1040 struct vfswrap_pwrite_state *state = tevent_req_data(
1041 req, struct vfswrap_pwrite_state);
1044 ret = pthreadpool_tevent_job_recv(subreq);
1045 TALLOC_FREE(subreq);
1046 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1047 talloc_set_destructor(state, NULL);
1049 if (ret != EAGAIN) {
1050 tevent_req_error(req, ret);
1054 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1055 * means the lower level pthreadpool failed to create a new
1056 * thread. Fallback to sync processing in that case to allow
1057 * some progress for the client.
1059 vfs_pwrite_do(state);
1062 tevent_req_done(req);
1065 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
1066 struct vfs_aio_state *vfs_aio_state)
1068 struct vfswrap_pwrite_state *state = tevent_req_data(
1069 req, struct vfswrap_pwrite_state);
1071 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1075 *vfs_aio_state = state->vfs_aio_state;
1079 struct vfswrap_fsync_state {
1083 struct vfs_aio_state vfs_aio_state;
1084 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
1087 static void vfs_fsync_do(void *private_data);
1088 static void vfs_fsync_done(struct tevent_req *subreq);
1089 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state);
1091 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
1092 TALLOC_CTX *mem_ctx,
1093 struct tevent_context *ev,
1094 struct files_struct *fsp)
1096 struct tevent_req *req, *subreq;
1097 struct vfswrap_fsync_state *state;
1099 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
1105 state->fd = fsp_get_io_fd(fsp);
1107 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_fsync, profile_p,
1108 state->profile_bytes, 0);
1109 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1111 subreq = pthreadpool_tevent_job_send(
1112 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
1113 if (tevent_req_nomem(subreq, req)) {
1114 return tevent_req_post(req, ev);
1116 tevent_req_set_callback(subreq, vfs_fsync_done, req);
1118 talloc_set_destructor(state, vfs_fsync_state_destructor);
1123 static void vfs_fsync_do(void *private_data)
1125 struct vfswrap_fsync_state *state = talloc_get_type_abort(
1126 private_data, struct vfswrap_fsync_state);
1127 struct timespec start_time;
1128 struct timespec end_time;
1130 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
1132 PROFILE_TIMESTAMP(&start_time);
1135 state->ret = fsync(state->fd);
1136 } while ((state->ret == -1) && (errno == EINTR));
1138 if (state->ret == -1) {
1139 state->vfs_aio_state.error = errno;
1142 PROFILE_TIMESTAMP(&end_time);
1144 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1146 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1149 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state)
1154 static void vfs_fsync_done(struct tevent_req *subreq)
1156 struct tevent_req *req = tevent_req_callback_data(
1157 subreq, struct tevent_req);
1158 struct vfswrap_fsync_state *state = tevent_req_data(
1159 req, struct vfswrap_fsync_state);
1162 ret = pthreadpool_tevent_job_recv(subreq);
1163 TALLOC_FREE(subreq);
1164 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1165 talloc_set_destructor(state, NULL);
1167 if (ret != EAGAIN) {
1168 tevent_req_error(req, ret);
1172 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1173 * means the lower level pthreadpool failed to create a new
1174 * thread. Fallback to sync processing in that case to allow
1175 * some progress for the client.
1177 vfs_fsync_do(state);
1180 tevent_req_done(req);
1183 static int vfswrap_fsync_recv(struct tevent_req *req,
1184 struct vfs_aio_state *vfs_aio_state)
1186 struct vfswrap_fsync_state *state = tevent_req_data(
1187 req, struct vfswrap_fsync_state);
1189 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1193 *vfs_aio_state = state->vfs_aio_state;
1197 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1201 START_PROFILE(syscall_lseek);
1203 result = lseek(fsp_get_io_fd(fsp), offset, whence);
1205 * We want to maintain the fiction that we can seek
1206 * on a fifo for file system purposes. This allows
1207 * people to set up UNIX fifo's that feed data to Windows
1208 * applications. JRA.
1211 if((result == -1) && (errno == ESPIPE)) {
1216 END_PROFILE(syscall_lseek);
1220 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1221 off_t offset, size_t n)
1225 START_PROFILE_BYTES(syscall_sendfile, n);
1226 result = sys_sendfile(tofd, fsp_get_io_fd(fromfsp), hdr, offset, n);
1227 END_PROFILE_BYTES(syscall_sendfile);
1231 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1233 files_struct *tofsp,
1239 START_PROFILE_BYTES(syscall_recvfile, n);
1240 result = sys_recvfile(fromfd, fsp_get_io_fd(tofsp), offset, n);
1241 END_PROFILE_BYTES(syscall_recvfile);
1245 static int vfswrap_renameat(vfs_handle_struct *handle,
1246 files_struct *srcfsp,
1247 const struct smb_filename *smb_fname_src,
1248 files_struct *dstfsp,
1249 const struct smb_filename *smb_fname_dst)
1253 START_PROFILE(syscall_renameat);
1255 if (is_named_stream(smb_fname_src) || is_named_stream(smb_fname_dst)) {
1260 result = renameat(fsp_get_pathref_fd(srcfsp),
1261 smb_fname_src->base_name,
1262 fsp_get_pathref_fd(dstfsp),
1263 smb_fname_dst->base_name);
1266 END_PROFILE(syscall_renameat);
1270 static int vfswrap_stat(vfs_handle_struct *handle,
1271 struct smb_filename *smb_fname)
1275 START_PROFILE(syscall_stat);
1277 if (is_named_stream(smb_fname)) {
1282 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1283 lp_fake_directory_create_times(SNUM(handle->conn)));
1285 END_PROFILE(syscall_stat);
1289 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1293 START_PROFILE(syscall_fstat);
1294 result = sys_fstat(fsp_get_pathref_fd(fsp),
1295 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1296 END_PROFILE(syscall_fstat);
1300 static int vfswrap_lstat(vfs_handle_struct *handle,
1301 struct smb_filename *smb_fname)
1305 START_PROFILE(syscall_lstat);
1307 if (is_named_stream(smb_fname)) {
1312 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1313 lp_fake_directory_create_times(SNUM(handle->conn)));
1315 END_PROFILE(syscall_lstat);
1319 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1321 enum vfs_translate_direction direction,
1322 TALLOC_CTX *mem_ctx,
1325 return NT_STATUS_NONE_MAPPED;
1329 * Return allocated parent directory and basename of path
1331 * Note: if requesting name, it is returned as talloc child of the
1332 * parent. Freeing the parent is thus sufficient to free both.
1334 static NTSTATUS vfswrap_parent_pathname(struct vfs_handle_struct *handle,
1335 TALLOC_CTX *mem_ctx,
1336 const struct smb_filename *smb_fname_in,
1337 struct smb_filename **parent_dir_out,
1338 struct smb_filename **atname_out)
1340 TALLOC_CTX *frame = talloc_stackframe();
1341 struct smb_filename *parent = NULL;
1342 struct smb_filename *name = NULL;
1345 parent = cp_smb_filename(frame, smb_fname_in);
1346 if (parent == NULL) {
1348 return NT_STATUS_NO_MEMORY;
1350 TALLOC_FREE(parent->stream_name);
1351 SET_STAT_INVALID(parent->st);
1353 p = strrchr_m(parent->base_name, '/'); /* Find final '/', if any */
1355 TALLOC_FREE(parent->base_name);
1356 parent->base_name = talloc_strdup(parent, ".");
1357 if (parent->base_name == NULL) {
1359 return NT_STATUS_NO_MEMORY;
1361 p = smb_fname_in->base_name;
1367 if (atname_out == NULL) {
1368 *parent_dir_out = talloc_move(mem_ctx, &parent);
1370 return NT_STATUS_OK;
1373 name = cp_smb_filename(frame, smb_fname_in);
1376 return NT_STATUS_NO_MEMORY;
1378 TALLOC_FREE(name->base_name);
1380 name->base_name = talloc_strdup(name, p);
1381 if (name->base_name == NULL) {
1383 return NT_STATUS_NO_MEMORY;
1386 *parent_dir_out = talloc_move(mem_ctx, &parent);
1387 *atname_out = talloc_move(*parent_dir_out, &name);
1389 return NT_STATUS_OK;
1393 * Implement the default fsctl operation.
1395 static bool vfswrap_logged_ioctl_message = false;
1397 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1398 struct files_struct *fsp,
1401 uint16_t req_flags, /* Needed for UNICODE ... */
1402 const uint8_t *_in_data,
1404 uint8_t **_out_data,
1405 uint32_t max_out_len,
1408 const char *in_data = (const char *)_in_data;
1409 char **out_data = (char **)_out_data;
1413 case FSCTL_SET_SPARSE:
1415 bool set_sparse = true;
1417 if (in_len >= 1 && in_data[0] == 0) {
1421 status = file_set_sparse(handle->conn, fsp, set_sparse);
1423 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1424 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1425 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1426 nt_errstr(status)));
1431 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1433 unsigned char objid[16];
1434 char *return_data = NULL;
1436 /* This should return the object-id on this file.
1437 * I think I'll make this be the inode+dev. JRA.
1440 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1441 fsp_fnum_dbg(fsp)));
1443 *out_len = MIN(max_out_len, 64);
1445 /* Hmmm, will this cause problems if less data asked for? */
1446 return_data = talloc_array(ctx, char, 64);
1447 if (return_data == NULL) {
1448 return NT_STATUS_NO_MEMORY;
1451 /* For backwards compatibility only store the dev/inode. */
1452 push_file_id_16(return_data, &fsp->file_id);
1453 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1454 push_file_id_16(return_data+32, &fsp->file_id);
1455 memset(return_data+48, 0, 16);
1456 *out_data = return_data;
1457 return NT_STATUS_OK;
1460 case FSCTL_GET_REPARSE_POINT:
1462 status = fsctl_get_reparse_point(
1463 fsp, ctx, out_data, max_out_len, out_len);
1467 case FSCTL_SET_REPARSE_POINT:
1469 status = fsctl_set_reparse_point(fsp, ctx, _in_data, in_len);
1473 case FSCTL_DELETE_REPARSE_POINT:
1475 status = fsctl_del_reparse_point(fsp, ctx, _in_data, in_len);
1479 case FSCTL_GET_SHADOW_COPY_DATA:
1482 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1483 * and return their volume names. If max_data_count is 16, then it is just
1484 * asking for the number of volumes and length of the combined names.
1486 * pdata is the data allocated by our caller, but that uses
1487 * total_data_count (which is 0 in our case) rather than max_data_count.
1488 * Allocate the correct amount and return the pointer to let
1489 * it be deallocated when we return.
1491 struct shadow_copy_data *shadow_data = NULL;
1492 bool labels = False;
1493 uint32_t labels_data_count = 0;
1495 char *cur_pdata = NULL;
1497 if (max_out_len < 16) {
1498 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1500 return NT_STATUS_INVALID_PARAMETER;
1503 if (max_out_len > 16) {
1507 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1508 if (shadow_data == NULL) {
1509 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1510 return NT_STATUS_NO_MEMORY;
1514 * Call the VFS routine to actually do the work.
1516 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1519 /* broken module didn't set errno on error */
1520 status = NT_STATUS_UNSUCCESSFUL;
1522 status = map_nt_error_from_unix(errno);
1523 if (NT_STATUS_EQUAL(status,
1524 NT_STATUS_NOT_SUPPORTED)) {
1528 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1529 "connectpath %s, failed - %s.\n",
1530 fsp->conn->connectpath,
1531 nt_errstr(status)));
1532 TALLOC_FREE(shadow_data);
1536 labels_data_count = (shadow_data->num_volumes * 2 *
1537 sizeof(SHADOW_COPY_LABEL)) + 2;
1542 *out_len = 12 + labels_data_count;
1545 if (max_out_len < *out_len) {
1546 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1547 max_out_len, *out_len));
1548 TALLOC_FREE(shadow_data);
1549 return NT_STATUS_BUFFER_TOO_SMALL;
1552 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1553 if (cur_pdata == NULL) {
1554 TALLOC_FREE(shadow_data);
1555 return NT_STATUS_NO_MEMORY;
1558 *out_data = cur_pdata;
1560 /* num_volumes 4 bytes */
1561 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1564 /* num_labels 4 bytes */
1565 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1568 /* needed_data_count 4 bytes */
1569 SIVAL(cur_pdata, 8, labels_data_count);
1573 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1574 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1575 if (labels && shadow_data->labels) {
1576 for (i=0; i<shadow_data->num_volumes; i++) {
1578 status = srvstr_push(cur_pdata, req_flags,
1579 cur_pdata, shadow_data->labels[i],
1580 2 * sizeof(SHADOW_COPY_LABEL),
1581 STR_UNICODE|STR_TERMINATE, &len);
1582 if (!NT_STATUS_IS_OK(status)) {
1583 TALLOC_FREE(*out_data);
1584 TALLOC_FREE(shadow_data);
1587 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1588 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1592 TALLOC_FREE(shadow_data);
1594 return NT_STATUS_OK;
1597 case FSCTL_FIND_FILES_BY_SID:
1599 /* pretend this succeeded -
1601 * we have to send back a list with all files owned by this SID
1603 * but I have to check that --metze
1607 struct dom_sid_buf buf;
1611 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1612 fsp_fnum_dbg(fsp)));
1615 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1616 return NT_STATUS_INVALID_PARAMETER;
1619 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1621 /* unknown 4 bytes: this is not the length of the sid :-( */
1622 /*unknown = IVAL(pdata,0);*/
1624 ret = sid_parse(_in_data + 4, sid_len, &sid);
1626 return NT_STATUS_INVALID_PARAMETER;
1628 DEBUGADD(10, ("for SID: %s\n",
1629 dom_sid_str_buf(&sid, &buf)));
1631 if (!sid_to_uid(&sid, &uid)) {
1632 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1633 dom_sid_str_buf(&sid, &buf),
1634 (unsigned long)sid_len));
1638 /* we can take a look at the find source :-)
1640 * find ./ -uid $uid -name '*' is what we need here
1643 * and send 4bytes len and then NULL terminated unicode strings
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 * but I don't know how to deal with the paged results
1650 * (maybe we can hang the result anywhere in the fsp struct)
1652 * we don't send all files at once
1653 * and at the next we should *not* start from the beginning,
1654 * so we have to cache the result
1659 /* this works for now... */
1660 return NT_STATUS_OK;
1663 case FSCTL_QUERY_ALLOCATED_RANGES:
1665 /* FIXME: This is just a dummy reply, telling that all of the
1666 * file is allocated. MKS cp needs that.
1667 * Adding the real allocated ranges via FIEMAP on Linux
1668 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1669 * this FSCTL correct for sparse files.
1671 uint64_t offset, length;
1672 char *out_data_tmp = NULL;
1675 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1677 return NT_STATUS_INVALID_PARAMETER;
1680 if (max_out_len < 16) {
1681 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1683 return NT_STATUS_INVALID_PARAMETER;
1686 offset = BVAL(in_data,0);
1687 length = BVAL(in_data,8);
1689 if (offset + length < offset) {
1690 /* No 64-bit integer wrap. */
1691 return NT_STATUS_INVALID_PARAMETER;
1694 /* Shouldn't this be SMB_VFS_STAT ... ? */
1695 status = vfs_stat_fsp(fsp);
1696 if (!NT_STATUS_IS_OK(status)) {
1701 out_data_tmp = talloc_array(ctx, char, *out_len);
1702 if (out_data_tmp == NULL) {
1703 DEBUG(10, ("unable to allocate memory for response\n"));
1704 return NT_STATUS_NO_MEMORY;
1707 if (offset > fsp->fsp_name->st.st_ex_size ||
1708 fsp->fsp_name->st.st_ex_size == 0 ||
1710 memset(out_data_tmp, 0, *out_len);
1712 uint64_t end = offset + length;
1713 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1714 SBVAL(out_data_tmp, 0, 0);
1715 SBVAL(out_data_tmp, 8, end);
1718 *out_data = out_data_tmp;
1720 return NT_STATUS_OK;
1723 case FSCTL_IS_VOLUME_DIRTY:
1725 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1726 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1728 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1729 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1731 return NT_STATUS_INVALID_PARAMETER;
1736 * Only print once ... unfortunately there could be lots of
1737 * different FSCTLs that are called.
1739 if (!vfswrap_logged_ioctl_message) {
1740 vfswrap_logged_ioctl_message = true;
1741 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1742 __func__, function));
1746 return NT_STATUS_NOT_SUPPORTED;
1749 static bool vfswrap_is_offline(struct connection_struct *conn,
1750 const struct smb_filename *fname);
1752 struct vfswrap_get_dos_attributes_state {
1753 struct vfs_aio_state aio_state;
1754 connection_struct *conn;
1755 TALLOC_CTX *mem_ctx;
1756 struct tevent_context *ev;
1757 files_struct *dir_fsp;
1758 struct smb_filename *smb_fname;
1763 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq);
1765 static struct tevent_req *vfswrap_get_dos_attributes_send(
1766 TALLOC_CTX *mem_ctx,
1767 struct tevent_context *ev,
1768 struct vfs_handle_struct *handle,
1769 files_struct *dir_fsp,
1770 struct smb_filename *smb_fname)
1772 struct tevent_req *req = NULL;
1773 struct tevent_req *subreq = NULL;
1774 struct vfswrap_get_dos_attributes_state *state = NULL;
1776 req = tevent_req_create(mem_ctx, &state,
1777 struct vfswrap_get_dos_attributes_state);
1782 *state = (struct vfswrap_get_dos_attributes_state) {
1783 .conn = dir_fsp->conn,
1787 .smb_fname = smb_fname,
1790 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1794 SAMBA_XATTR_DOS_ATTRIB,
1796 if (tevent_req_nomem(subreq, req)) {
1797 return tevent_req_post(req, ev);
1799 tevent_req_set_callback(subreq,
1800 vfswrap_get_dos_attributes_getxattr_done,
1806 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq)
1808 struct tevent_req *req =
1809 tevent_req_callback_data(subreq,
1811 struct vfswrap_get_dos_attributes_state *state =
1812 tevent_req_data(req,
1813 struct vfswrap_get_dos_attributes_state);
1815 DATA_BLOB blob = {0};
1817 char *tofree = NULL;
1818 char pathbuf[PATH_MAX+1];
1820 struct smb_filename smb_fname;
1824 xattr_size = SMB_VFS_GETXATTRAT_RECV(subreq,
1828 TALLOC_FREE(subreq);
1829 if (xattr_size == -1) {
1830 status = map_nt_error_from_unix(state->aio_state.error);
1832 if (state->as_root) {
1833 tevent_req_nterror(req, status);
1836 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1837 tevent_req_nterror(req, status);
1841 state->as_root = true;
1844 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1848 SAMBA_XATTR_DOS_ATTRIB,
1851 if (tevent_req_nomem(subreq, req)) {
1854 tevent_req_set_callback(subreq,
1855 vfswrap_get_dos_attributes_getxattr_done,
1860 blob.length = xattr_size;
1862 status = parse_dos_attribute_blob(state->smb_fname,
1865 if (!NT_STATUS_IS_OK(status)) {
1866 tevent_req_nterror(req, status);
1870 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
1871 state->smb_fname->base_name,
1876 if (pathlen == -1) {
1877 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1881 smb_fname = (struct smb_filename) {
1883 .st = state->smb_fname->st,
1884 .flags = state->smb_fname->flags,
1885 .twrp = state->smb_fname->twrp,
1888 offline = vfswrap_is_offline(state->conn, &smb_fname);
1890 state->dosmode |= FILE_ATTRIBUTE_OFFLINE;
1892 TALLOC_FREE(tofree);
1894 tevent_req_done(req);
1898 static NTSTATUS vfswrap_get_dos_attributes_recv(struct tevent_req *req,
1899 struct vfs_aio_state *aio_state,
1902 struct vfswrap_get_dos_attributes_state *state =
1903 tevent_req_data(req,
1904 struct vfswrap_get_dos_attributes_state);
1907 if (tevent_req_is_nterror(req, &status)) {
1908 tevent_req_received(req);
1912 *aio_state = state->aio_state;
1913 *dosmode = state->dosmode;
1914 tevent_req_received(req);
1915 return NT_STATUS_OK;
1918 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1919 struct files_struct *fsp,
1924 offline = vfswrap_is_offline(handle->conn, fsp->fsp_name);
1926 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1929 return fget_ea_dos_attribute(fsp, dosmode);
1932 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1933 struct files_struct *fsp,
1936 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1939 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1941 struct vfswrap_offload_read_state {
1945 static struct tevent_req *vfswrap_offload_read_send(
1946 TALLOC_CTX *mem_ctx,
1947 struct tevent_context *ev,
1948 struct vfs_handle_struct *handle,
1949 struct files_struct *fsp,
1955 struct tevent_req *req = NULL;
1956 struct vfswrap_offload_read_state *state = NULL;
1959 req = tevent_req_create(mem_ctx, &state,
1960 struct vfswrap_offload_read_state);
1965 status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1966 &vfswrap_offload_ctx);
1967 if (tevent_req_nterror(req, status)) {
1968 return tevent_req_post(req, ev);
1971 if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1972 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1973 return tevent_req_post(req, ev);
1976 status = vfs_offload_token_create_blob(state, fsp, fsctl,
1978 if (tevent_req_nterror(req, status)) {
1979 return tevent_req_post(req, ev);
1982 status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1984 if (tevent_req_nterror(req, status)) {
1985 return tevent_req_post(req, ev);
1988 tevent_req_done(req);
1989 return tevent_req_post(req, ev);
1992 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
1993 struct vfs_handle_struct *handle,
1994 TALLOC_CTX *mem_ctx,
1997 struct vfswrap_offload_read_state *state = tevent_req_data(
1998 req, struct vfswrap_offload_read_state);
2001 if (tevent_req_is_nterror(req, &status)) {
2002 tevent_req_received(req);
2006 token->length = state->token.length;
2007 token->data = talloc_move(mem_ctx, &state->token.data);
2009 tevent_req_received(req);
2010 return NT_STATUS_OK;
2013 struct vfswrap_offload_write_state {
2015 bool read_lck_locked;
2016 bool write_lck_locked;
2018 struct tevent_context *src_ev;
2019 struct files_struct *src_fsp;
2021 struct tevent_context *dst_ev;
2022 struct files_struct *dst_fsp;
2027 size_t next_io_size;
2030 static void vfswrap_offload_write_cleanup(struct tevent_req *req,
2031 enum tevent_req_state req_state)
2033 struct vfswrap_offload_write_state *state = tevent_req_data(
2034 req, struct vfswrap_offload_write_state);
2037 if (state->dst_fsp == NULL) {
2041 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2043 state->dst_fsp = NULL;
2046 static NTSTATUS vfswrap_offload_copy_file_range(struct tevent_req *req);
2047 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
2049 static struct tevent_req *vfswrap_offload_write_send(
2050 struct vfs_handle_struct *handle,
2051 TALLOC_CTX *mem_ctx,
2052 struct tevent_context *ev,
2055 off_t transfer_offset,
2056 struct files_struct *dest_fsp,
2060 struct tevent_req *req;
2061 struct vfswrap_offload_write_state *state = NULL;
2062 /* off_t is signed! */
2063 off_t max_offset = INT64_MAX - to_copy;
2064 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
2065 files_struct *src_fsp = NULL;
2069 req = tevent_req_create(mem_ctx, &state,
2070 struct vfswrap_offload_write_state);
2075 *state = (struct vfswrap_offload_write_state) {
2077 .src_off = transfer_offset,
2079 .dst_fsp = dest_fsp,
2080 .dst_off = dest_off,
2082 .remaining = to_copy,
2085 tevent_req_set_cleanup_fn(req, vfswrap_offload_write_cleanup);
2088 case FSCTL_SRV_COPYCHUNK:
2089 case FSCTL_SRV_COPYCHUNK_WRITE:
2092 case FSCTL_OFFLOAD_WRITE:
2093 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
2094 return tevent_req_post(req, ev);
2096 case FSCTL_DUP_EXTENTS_TO_FILE:
2097 DBG_DEBUG("COW clones not supported by vfs_default\n");
2098 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2099 return tevent_req_post(req, ev);
2102 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2103 return tevent_req_post(req, ev);
2107 * From here on we assume a copy-chunk fsctl
2111 tevent_req_done(req);
2112 return tevent_req_post(req, ev);
2115 if (state->src_off > max_offset) {
2117 * Protect integer checks below.
2119 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2120 return tevent_req_post(req, ev);
2122 if (state->src_off < 0) {
2124 * Protect integer checks below.
2126 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2127 return tevent_req_post(req, ev);
2129 if (state->dst_off > max_offset) {
2131 * Protect integer checks below.
2133 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2134 return tevent_req_post(req, ev);
2136 if (state->dst_off < 0) {
2138 * Protect integer checks below.
2140 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2141 return tevent_req_post(req, ev);
2144 status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
2146 if (tevent_req_nterror(req, status)) {
2147 return tevent_req_post(req, ev);
2150 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
2152 status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
2153 if (!NT_STATUS_IS_OK(status)) {
2154 tevent_req_nterror(req, status);
2155 return tevent_req_post(req, ev);
2158 ok = change_to_user_and_service_by_fsp(src_fsp);
2160 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2161 return tevent_req_post(req, ev);
2164 state->src_ev = src_fsp->conn->sconn->ev_ctx;
2165 state->src_fsp = src_fsp;
2167 status = vfs_stat_fsp(src_fsp);
2168 if (tevent_req_nterror(req, status)) {
2169 return tevent_req_post(req, ev);
2172 if (src_fsp->fsp_name->st.st_ex_size < state->src_off + to_copy) {
2174 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
2175 * If the SourceOffset or SourceOffset + Length extends beyond
2176 * the end of file, the server SHOULD<240> treat this as a
2177 * STATUS_END_OF_FILE error.
2179 * <240> Section 3.3.5.15.6: Windows servers will return
2180 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
2182 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
2183 return tevent_req_post(req, ev);
2186 status = vfswrap_offload_copy_file_range(req);
2187 if (NT_STATUS_IS_OK(status)) {
2188 tevent_req_done(req);
2189 return tevent_req_post(req, ev);
2191 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2192 tevent_req_nterror(req, status);
2193 return tevent_req_post(req, ev);
2196 state->buf = talloc_array(state, uint8_t, num);
2197 if (tevent_req_nomem(state->buf, req)) {
2198 return tevent_req_post(req, ev);
2201 status = vfswrap_offload_write_loop(req);
2202 if (!NT_STATUS_IS_OK(status)) {
2203 tevent_req_nterror(req, status);
2204 return tevent_req_post(req, ev);
2210 static NTSTATUS vfswrap_offload_copy_file_range(struct tevent_req *req)
2212 struct vfswrap_offload_write_state *state = tevent_req_data(
2213 req, struct vfswrap_offload_write_state);
2214 struct lock_struct lck;
2220 #ifndef USE_COPY_FILE_RANGE
2221 return NT_STATUS_MORE_PROCESSING_REQUIRED;
2224 same_file = file_id_equal(&state->src_fsp->file_id,
2225 &state->dst_fsp->file_id);
2227 sys_io_ranges_overlap(state->remaining,
2232 return NT_STATUS_MORE_PROCESSING_REQUIRED;
2235 if (is_named_stream(state->src_fsp->fsp_name) ||
2236 is_named_stream(state->dst_fsp->fsp_name))
2238 return NT_STATUS_MORE_PROCESSING_REQUIRED;
2241 init_strict_lock_struct(state->src_fsp,
2242 state->src_fsp->op->global->open_persistent_id,
2248 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
2252 return NT_STATUS_FILE_LOCK_CONFLICT;
2255 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2257 return NT_STATUS_INTERNAL_ERROR;
2260 init_strict_lock_struct(state->dst_fsp,
2261 state->dst_fsp->op->global->open_persistent_id,
2267 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
2271 return NT_STATUS_FILE_LOCK_CONFLICT;
2274 while (state->remaining > 0) {
2275 nwritten = copy_file_range(fsp_get_io_fd(state->src_fsp),
2277 fsp_get_io_fd(state->dst_fsp),
2281 if (nwritten == -1) {
2282 DBG_DEBUG("copy_file_range src [%s]:[%jd] dst [%s]:[%jd] "
2283 "n [%jd] failed: %s\n",
2284 fsp_str_dbg(state->src_fsp),
2285 (intmax_t)state->src_off,
2286 fsp_str_dbg(state->dst_fsp),
2287 (intmax_t)state->dst_off,
2288 (intmax_t)state->remaining,
2292 status = NT_STATUS_MORE_PROCESSING_REQUIRED;
2295 status = map_nt_error_from_unix(errno);
2296 if (NT_STATUS_EQUAL(
2298 NT_STATUS_MORE_PROCESSING_REQUIRED))
2300 /* Avoid triggering the fallback */
2301 status = NT_STATUS_INTERNAL_ERROR;
2308 if (state->remaining < nwritten) {
2309 DBG_DEBUG("copy_file_range src [%s] dst [%s] "
2310 "n [%jd] remaining [%jd]\n",
2311 fsp_str_dbg(state->src_fsp),
2312 fsp_str_dbg(state->dst_fsp),
2314 (intmax_t)state->remaining);
2315 return NT_STATUS_INTERNAL_ERROR;
2318 if (nwritten == 0) {
2321 state->copied += nwritten;
2322 state->remaining -= nwritten;
2326 * Tell the req cleanup function there's no need to call
2327 * change_to_user_and_service_by_fsp() on the dst handle.
2329 state->dst_fsp = NULL;
2330 return NT_STATUS_OK;
2333 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
2335 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
2337 struct vfswrap_offload_write_state *state = tevent_req_data(
2338 req, struct vfswrap_offload_write_state);
2339 struct tevent_req *subreq = NULL;
2340 struct lock_struct read_lck;
2344 * This is called under the context of state->src_fsp.
2347 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
2349 init_strict_lock_struct(state->src_fsp,
2350 state->src_fsp->op->global->open_persistent_id,
2352 state->next_io_size,
2356 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
2360 return NT_STATUS_FILE_LOCK_CONFLICT;
2363 subreq = SMB_VFS_PREAD_SEND(state,
2367 state->next_io_size,
2369 if (subreq == NULL) {
2370 return NT_STATUS_NO_MEMORY;
2372 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
2374 return NT_STATUS_OK;
2377 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
2379 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
2381 struct tevent_req *req = tevent_req_callback_data(
2382 subreq, struct tevent_req);
2383 struct vfswrap_offload_write_state *state = tevent_req_data(
2384 req, struct vfswrap_offload_write_state);
2385 struct vfs_aio_state aio_state;
2386 struct lock_struct write_lck;
2390 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
2391 TALLOC_FREE(subreq);
2393 DBG_ERR("read failed: %s\n", strerror(aio_state.error));
2394 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2397 if (nread != state->next_io_size) {
2398 DBG_ERR("Short read, only %zd of %zu\n",
2399 nread, state->next_io_size);
2400 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2404 state->src_off += nread;
2406 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2408 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2412 init_strict_lock_struct(state->dst_fsp,
2413 state->dst_fsp->op->global->open_persistent_id,
2415 state->next_io_size,
2419 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
2423 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
2427 subreq = SMB_VFS_PWRITE_SEND(state,
2431 state->next_io_size,
2433 if (subreq == NULL) {
2434 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2437 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
2440 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
2442 struct tevent_req *req = tevent_req_callback_data(
2443 subreq, struct tevent_req);
2444 struct vfswrap_offload_write_state *state = tevent_req_data(
2445 req, struct vfswrap_offload_write_state);
2446 struct vfs_aio_state aio_state;
2451 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
2452 TALLOC_FREE(subreq);
2453 if (nwritten == -1) {
2454 DBG_ERR("write failed: %s\n", strerror(aio_state.error));
2455 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2458 if (nwritten != state->next_io_size) {
2459 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
2460 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2464 state->dst_off += nwritten;
2466 if (state->remaining < nwritten) {
2467 /* Paranoia check */
2468 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2471 state->copied += nwritten;
2472 state->remaining -= nwritten;
2473 if (state->remaining == 0) {
2474 tevent_req_done(req);
2478 ok = change_to_user_and_service_by_fsp(state->src_fsp);
2480 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2484 status = vfswrap_offload_write_loop(req);
2485 if (!NT_STATUS_IS_OK(status)) {
2486 tevent_req_nterror(req, status);
2493 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
2494 struct tevent_req *req,
2497 struct vfswrap_offload_write_state *state = tevent_req_data(
2498 req, struct vfswrap_offload_write_state);
2501 if (tevent_req_is_nterror(req, &status)) {
2502 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
2504 tevent_req_received(req);
2508 *copied = state->copied;
2509 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
2510 tevent_req_received(req);
2512 return NT_STATUS_OK;
2515 static NTSTATUS vfswrap_fget_compression(struct vfs_handle_struct *handle,
2516 TALLOC_CTX *mem_ctx,
2517 struct files_struct *fsp,
2518 uint16_t *_compression_fmt)
2520 return NT_STATUS_INVALID_DEVICE_REQUEST;
2523 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
2524 TALLOC_CTX *mem_ctx,
2525 struct files_struct *fsp,
2526 uint16_t compression_fmt)
2528 return NT_STATUS_INVALID_DEVICE_REQUEST;
2531 /********************************************************************
2532 Given a stat buffer return the allocated size on disk, taking into
2533 account sparse files.
2534 ********************************************************************/
2535 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
2536 struct files_struct *fsp,
2537 const SMB_STRUCT_STAT *sbuf)
2541 START_PROFILE(syscall_get_alloc_size);
2543 if(S_ISDIR(sbuf->st_ex_mode)) {
2548 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2549 /* The type of st_blocksize is blkcnt_t which *MUST* be
2550 signed (according to POSIX) and can be less than 64-bits.
2551 Ensure when we're converting to 64 bits wide we don't
2553 #if defined(SIZEOF_BLKCNT_T_8)
2554 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2555 #elif defined(SIZEOF_BLKCNT_T_4)
2557 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2558 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2561 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2565 * Some file systems do not allocate a block for very
2566 * small files. But for non-empty file should report a
2570 uint64_t filesize = get_file_size_stat(sbuf);
2572 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2576 result = get_file_size_stat(sbuf);
2579 if (fsp && fsp->initial_allocation_size)
2580 result = MAX(result,fsp->initial_allocation_size);
2582 result = smb_roundup(handle->conn, result);
2585 END_PROFILE(syscall_get_alloc_size);
2589 static int vfswrap_unlinkat(vfs_handle_struct *handle,
2590 struct files_struct *dirfsp,
2591 const struct smb_filename *smb_fname,
2596 START_PROFILE(syscall_unlinkat);
2598 if (is_named_stream(smb_fname)) {
2602 result = unlinkat(fsp_get_pathref_fd(dirfsp),
2603 smb_fname->base_name,
2607 END_PROFILE(syscall_unlinkat);
2611 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2615 START_PROFILE(syscall_fchmod);
2617 if (!fsp->fsp_flags.is_pathref) {
2618 result = fchmod(fsp_get_io_fd(fsp), mode);
2619 END_PROFILE(syscall_fchmod);
2623 if (fsp->fsp_flags.have_proc_fds) {
2624 int fd = fsp_get_pathref_fd(fsp);
2625 const char *p = NULL;
2628 p = sys_proc_fd_path(fd, buf, sizeof(buf));
2630 result = chmod(p, mode);
2634 END_PROFILE(syscall_fchmod);
2639 * This is no longer a handle based call.
2641 result = chmod(fsp->fsp_name->base_name, mode);
2643 END_PROFILE(syscall_fchmod);
2647 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2652 START_PROFILE(syscall_fchown);
2653 if (!fsp->fsp_flags.is_pathref) {
2654 result = fchown(fsp_get_io_fd(fsp), uid, gid);
2655 END_PROFILE(syscall_fchown);
2659 if (fsp->fsp_flags.have_proc_fds) {
2660 int fd = fsp_get_pathref_fd(fsp);
2661 const char *p = NULL;
2664 p = sys_proc_fd_path(fd, buf, sizeof(buf));
2666 result = chown(p, uid, gid);
2670 END_PROFILE(syscall_fchown);
2675 * This is no longer a handle based call.
2677 result = chown(fsp->fsp_name->base_name, uid, gid);
2678 END_PROFILE(syscall_fchown);
2686 static int vfswrap_lchown(vfs_handle_struct *handle,
2687 const struct smb_filename *smb_fname,
2693 START_PROFILE(syscall_lchown);
2694 result = lchown(smb_fname->base_name, uid, gid);
2695 END_PROFILE(syscall_lchown);
2699 static int vfswrap_chdir(vfs_handle_struct *handle,
2700 const struct smb_filename *smb_fname)
2704 START_PROFILE(syscall_chdir);
2705 result = chdir(smb_fname->base_name);
2706 END_PROFILE(syscall_chdir);
2710 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2714 struct smb_filename *smb_fname = NULL;
2716 START_PROFILE(syscall_getwd);
2717 result = sys_getwd();
2718 END_PROFILE(syscall_getwd);
2720 if (result == NULL) {
2723 smb_fname = synthetic_smb_fname(ctx,
2730 * sys_getwd() *always* returns malloced memory.
2731 * We must free here to avoid leaks:
2732 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2738 /*********************************************************************
2739 nsec timestamp resolution call. Convert down to whatever the underlying
2740 system will support.
2741 **********************************************************************/
2743 static int vfswrap_fntimes(vfs_handle_struct *handle,
2745 struct smb_file_time *ft)
2748 struct timespec ts[2];
2749 struct timespec *times = NULL;
2751 START_PROFILE(syscall_fntimes);
2753 if (is_named_stream(fsp->fsp_name)) {
2759 if (is_omit_timespec(&ft->atime)) {
2760 ft->atime = fsp->fsp_name->st.st_ex_atime;
2763 if (is_omit_timespec(&ft->mtime)) {
2764 ft->mtime = fsp->fsp_name->st.st_ex_mtime;
2767 if (!is_omit_timespec(&ft->create_time)) {
2768 set_create_timespec_ea(fsp,
2772 if ((timespec_compare(&ft->atime,
2773 &fsp->fsp_name->st.st_ex_atime) == 0) &&
2774 (timespec_compare(&ft->mtime,
2775 &fsp->fsp_name->st.st_ex_mtime) == 0)) {
2787 if (!fsp->fsp_flags.is_pathref) {
2788 result = futimens(fsp_get_io_fd(fsp), times);
2792 if (fsp->fsp_flags.have_proc_fds) {
2793 int fd = fsp_get_pathref_fd(fsp);
2794 const char *p = NULL;
2797 p = sys_proc_fd_path(fd, buf, sizeof(buf));
2800 * The dirfd argument of utimensat is ignored when
2801 * pathname is an absolute path
2803 result = utimensat(AT_FDCWD, p, times, 0);
2812 * The fd is a pathref (opened with O_PATH) and there isn't fd to
2813 * path translation mechanism. Fallback to path based call.
2815 result = utimensat(AT_FDCWD, fsp->fsp_name->base_name, times, 0);
2818 END_PROFILE(syscall_fntimes);
2824 /*********************************************************************
2825 A version of ftruncate that will write the space on disk if strict
2827 **********************************************************************/
2829 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2831 off_t space_to_write;
2832 uint64_t space_avail;
2833 uint64_t bsize,dfree,dsize;
2836 SMB_STRUCT_STAT *pst;
2839 ok = vfs_valid_pwrite_range(len, 0);
2845 status = vfs_stat_fsp(fsp);
2846 if (!NT_STATUS_IS_OK(status)) {
2849 pst = &fsp->fsp_name->st;
2852 if (S_ISFIFO(pst->st_ex_mode))
2856 if (pst->st_ex_size == len)
2859 /* Shrink - just ftruncate. */
2860 if (pst->st_ex_size > len)
2861 return ftruncate(fsp_get_io_fd(fsp), len);
2863 space_to_write = len - pst->st_ex_size;
2865 /* for allocation try fallocate first. This can fail on some
2866 platforms e.g. when the filesystem doesn't support it and no
2867 emulation is being done by the libc (like on AIX with JFS1). In that
2868 case we do our own emulation. fallocate implementations can
2869 return ENOTSUP or EINVAL in cases like that. */
2870 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2871 if (ret == -1 && errno == ENOSPC) {
2877 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2878 "error %d. Falling back to slow manual allocation\n", errno));
2880 /* available disk space is enough or not? */
2882 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2883 /* space_avail is 1k blocks */
2884 if (space_avail == (uint64_t)-1 ||
2885 ((uint64_t)space_to_write/1024 > space_avail) ) {
2890 /* Write out the real space on disk. */
2891 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2899 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2902 SMB_STRUCT_STAT *pst;
2906 START_PROFILE(syscall_ftruncate);
2908 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->fsp_flags.is_sparse) {
2909 result = strict_allocate_ftruncate(handle, fsp, len);
2910 END_PROFILE(syscall_ftruncate);
2914 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2915 ftruncate if the system supports it. Then I discovered that
2916 you can have some filesystems that support ftruncate
2917 expansion and some that don't! On Linux fat can't do
2918 ftruncate extend but ext2 can. */
2920 result = ftruncate(fsp_get_io_fd(fsp), len);
2922 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2923 extend a file with ftruncate. Provide alternate implementation
2926 /* Do an fstat to see if the file is longer than the requested
2927 size in which case the ftruncate above should have
2928 succeeded or shorter, in which case seek to len - 1 and
2929 write 1 byte of zero */
2930 status = vfs_stat_fsp(fsp);
2931 if (!NT_STATUS_IS_OK(status)) {
2935 /* We need to update the files_struct after successful ftruncate */
2940 pst = &fsp->fsp_name->st;
2943 if (S_ISFIFO(pst->st_ex_mode)) {
2949 if (pst->st_ex_size == len) {
2954 if (pst->st_ex_size > len) {
2955 /* the ftruncate should have worked */
2959 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2967 END_PROFILE(syscall_ftruncate);
2971 static int vfswrap_fallocate(vfs_handle_struct *handle,
2979 START_PROFILE(syscall_fallocate);
2981 result = sys_posix_fallocate(fsp_get_io_fd(fsp), offset, len);
2983 * posix_fallocate returns 0 on success, errno on error
2984 * and doesn't set errno. Make it behave like fallocate()
2985 * which returns -1, and sets errno on failure.
2992 /* sys_fallocate handles filtering of unsupported mode flags */
2993 result = sys_fallocate(fsp_get_io_fd(fsp), mode, offset, len);
2995 END_PROFILE(syscall_fallocate);
2999 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
3003 START_PROFILE(syscall_fcntl_lock);
3005 if (fsp->fsp_flags.use_ofd_locks) {
3006 op = map_process_lock_to_ofd_lock(op);
3009 result = fcntl_lock(fsp_get_io_fd(fsp), op, offset, count, type);
3010 END_PROFILE(syscall_fcntl_lock);
3014 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
3015 uint32_t share_access, uint32_t access_mask)
3017 START_PROFILE(syscall_kernel_flock);
3018 kernel_flock(fsp_get_io_fd(fsp), share_access, access_mask);
3019 END_PROFILE(syscall_kernel_flock);
3023 static int vfswrap_fcntl(vfs_handle_struct *handle, files_struct *fsp, int cmd,
3027 va_list dup_cmd_arg;
3031 START_PROFILE(syscall_fcntl);
3033 va_copy(dup_cmd_arg, cmd_arg);
3039 #if defined(HAVE_OFD_LOCKS)
3044 #if defined(HAVE_F_OWNER_EX)
3048 #if defined(HAVE_RW_HINTS)
3051 case F_GET_FILE_RW_HINT:
3052 case F_SET_FILE_RW_HINT:
3054 argp = va_arg(dup_cmd_arg, void *);
3055 result = sys_fcntl_ptr(fsp_get_io_fd(fsp), cmd, argp);
3058 val = va_arg(dup_cmd_arg, int);
3059 result = sys_fcntl_int(fsp_get_io_fd(fsp), cmd, val);
3062 va_end(dup_cmd_arg);
3064 END_PROFILE(syscall_fcntl);
3068 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
3073 START_PROFILE(syscall_fcntl_getlock);
3075 if (fsp->fsp_flags.use_ofd_locks) {
3076 op = map_process_lock_to_ofd_lock(op);
3079 result = fcntl_getlock(fsp_get_io_fd(fsp), op, poffset, pcount, ptype, ppid);
3080 END_PROFILE(syscall_fcntl_getlock);
3084 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
3089 START_PROFILE(syscall_linux_setlease);
3091 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
3092 result = linux_setlease(fsp_get_io_fd(fsp), leasetype);
3096 END_PROFILE(syscall_linux_setlease);
3100 static int vfswrap_symlinkat(vfs_handle_struct *handle,
3101 const struct smb_filename *link_target,
3102 struct files_struct *dirfsp,
3103 const struct smb_filename *new_smb_fname)
3107 START_PROFILE(syscall_symlinkat);
3109 result = symlinkat(link_target->base_name,
3110 fsp_get_pathref_fd(dirfsp),
3111 new_smb_fname->base_name);
3112 END_PROFILE(syscall_symlinkat);
3116 static int vfswrap_readlinkat(vfs_handle_struct *handle,
3117 const struct files_struct *dirfsp,
3118 const struct smb_filename *smb_fname,
3124 START_PROFILE(syscall_readlinkat);
3126 result = readlinkat(fsp_get_pathref_fd(dirfsp),
3127 smb_fname->base_name,
3131 END_PROFILE(syscall_readlinkat);
3135 static int vfswrap_linkat(vfs_handle_struct *handle,
3136 files_struct *srcfsp,
3137 const struct smb_filename *old_smb_fname,
3138 files_struct *dstfsp,
3139 const struct smb_filename *new_smb_fname,
3144 START_PROFILE(syscall_linkat);
3146 result = linkat(fsp_get_pathref_fd(srcfsp),
3147 old_smb_fname->base_name,
3148 fsp_get_pathref_fd(dstfsp),
3149 new_smb_fname->base_name,
3152 END_PROFILE(syscall_linkat);
3156 static int vfswrap_mknodat(vfs_handle_struct *handle,
3157 files_struct *dirfsp,
3158 const struct smb_filename *smb_fname,
3164 START_PROFILE(syscall_mknodat);
3166 result = sys_mknodat(fsp_get_pathref_fd(dirfsp),
3167 smb_fname->base_name,
3171 END_PROFILE(syscall_mknodat);
3175 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
3177 const struct smb_filename *smb_fname)
3180 struct smb_filename *result_fname = NULL;
3182 START_PROFILE(syscall_realpath);
3183 result = sys_realpath(smb_fname->base_name);
3184 END_PROFILE(syscall_realpath);
3186 result_fname = synthetic_smb_fname(ctx,
3194 return result_fname;
3197 static int vfswrap_fchflags(vfs_handle_struct *handle,
3198 struct files_struct *fsp,
3201 #ifdef HAVE_FCHFLAGS
3202 int fd = fsp_get_pathref_fd(fsp);
3204 if (!fsp->fsp_flags.is_pathref) {
3205 return fchflags(fd, flags);
3208 if (fsp->fsp_flags.have_proc_fds) {
3209 const char *p = NULL;
3212 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3217 return chflags(p, flags);
3221 * This is no longer a handle based call.
3223 return chflags(fsp->fsp_name->base_name, flags);
3230 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
3231 const SMB_STRUCT_STAT *sbuf)
3235 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
3239 key.devid = sbuf->st_ex_dev;
3240 key.inode = sbuf->st_ex_ino;
3241 /* key.extid is unused by default. */
3246 static uint64_t vfswrap_fs_file_id(struct vfs_handle_struct *handle,
3247 const SMB_STRUCT_STAT *psbuf)
3251 if (!(psbuf->st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)) {
3252 return psbuf->st_ex_file_id;
3255 if (handle->conn->base_share_dev == psbuf->st_ex_dev) {
3256 return (uint64_t)psbuf->st_ex_ino;
3260 file_id = ((psbuf->st_ex_ino) & UINT32_MAX);
3263 file_id |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32;
3268 static NTSTATUS vfswrap_fstreaminfo(vfs_handle_struct *handle,
3269 struct files_struct *fsp,
3270 TALLOC_CTX *mem_ctx,
3271 unsigned int *pnum_streams,
3272 struct stream_struct **pstreams)
3274 struct stream_struct *tmp_streams = NULL;
3275 unsigned int num_streams = *pnum_streams;
3276 struct stream_struct *streams = *pstreams;
3279 if (fsp->fsp_flags.is_directory) {
3281 * No default streams on directories
3285 status = vfs_stat_fsp(fsp);
3286 if (!NT_STATUS_IS_OK(status)) {
3290 if (num_streams + 1 < 1) {
3292 return NT_STATUS_INVALID_PARAMETER;
3295 tmp_streams = talloc_realloc(mem_ctx,
3297 struct stream_struct,
3299 if (tmp_streams == NULL) {
3300 return NT_STATUS_NO_MEMORY;
3302 tmp_streams[num_streams].name = talloc_strdup(tmp_streams, "::$DATA");
3303 if (tmp_streams[num_streams].name == NULL) {
3304 return NT_STATUS_NO_MEMORY;
3306 tmp_streams[num_streams].size = fsp->fsp_name->st.st_ex_size;
3307 tmp_streams[num_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(
3310 &fsp->fsp_name->st);
3313 *pnum_streams = num_streams;
3314 *pstreams = tmp_streams;
3316 return NT_STATUS_OK;
3319 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
3320 const struct smb_filename *path,
3322 TALLOC_CTX *mem_ctx,
3326 * Don't fall back to get_real_filename so callers can differentiate
3327 * between a full directory scan and an actual case-insensitive stat.
3333 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
3334 const struct smb_filename *smb_fname)
3336 return handle->conn->connectpath;
3339 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
3340 struct byte_range_lock *br_lck,
3341 struct lock_struct *plock)
3343 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3345 /* Note: blr is not used in the default implementation. */
3346 return brl_lock_windows_default(br_lck, plock);
3349 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
3350 struct byte_range_lock *br_lck,
3351 const struct lock_struct *plock)
3353 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3355 return brl_unlock_windows_default(br_lck, plock);
3358 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
3360 struct lock_struct *plock)
3362 SMB_ASSERT(plock->lock_type == READ_LOCK ||
3363 plock->lock_type == WRITE_LOCK);
3365 return strict_lock_check_default(fsp, plock);
3368 /* NT ACL operations. */
3370 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
3372 uint32_t security_info,
3373 TALLOC_CTX *mem_ctx,
3374 struct security_descriptor **ppdesc)
3378 START_PROFILE(fget_nt_acl);
3379 result = posix_fget_nt_acl(fsp, security_info,
3381 END_PROFILE(fget_nt_acl);
3385 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
3389 START_PROFILE(fset_nt_acl);
3390 result = set_nt_acl(fsp, security_info_sent, psd);
3391 END_PROFILE(fset_nt_acl);
3395 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
3396 struct smb_filename *file,
3397 struct security_acl *sacl,
3398 uint32_t access_requested,
3399 uint32_t access_denied)
3401 return NT_STATUS_OK; /* Nothing to do here ... */
3404 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
3406 SMB_ACL_TYPE_T type,
3407 TALLOC_CTX *mem_ctx)
3409 return sys_acl_get_fd(handle, fsp, type, mem_ctx);
3412 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle,
3414 SMB_ACL_TYPE_T type,
3417 return sys_acl_set_fd(handle, fsp, type, theacl);
3420 static int vfswrap_sys_acl_delete_def_fd(vfs_handle_struct *handle,
3423 return sys_acl_delete_def_fd(handle, fsp);
3426 /****************************************************************
3427 Extended attribute operations.
3428 *****************************************************************/
3430 struct vfswrap_getxattrat_state {
3431 struct tevent_context *ev;
3432 files_struct *dir_fsp;
3433 const struct smb_filename *smb_fname;
3436 * The following variables are talloced off "state" which is protected
3437 * by a destructor and thus are guaranteed to be safe to be used in the
3438 * job function in the worker thread.
3441 const char *xattr_name;
3442 uint8_t *xattr_value;
3443 struct security_unix_token *token;
3446 struct vfs_aio_state vfs_aio_state;
3447 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
3450 static int vfswrap_getxattrat_state_destructor(
3451 struct vfswrap_getxattrat_state *state)
3456 static void vfswrap_getxattrat_do_sync(struct tevent_req *req);
3457 static void vfswrap_getxattrat_do_async(void *private_data);
3458 static void vfswrap_getxattrat_done(struct tevent_req *subreq);
3460 static struct tevent_req *vfswrap_getxattrat_send(
3461 TALLOC_CTX *mem_ctx,
3462 struct tevent_context *ev,
3463 struct vfs_handle_struct *handle,
3464 files_struct *dir_fsp,
3465 const struct smb_filename *smb_fname,
3466 const char *xattr_name,
3469 struct tevent_req *req = NULL;
3470 struct tevent_req *subreq = NULL;
3471 struct vfswrap_getxattrat_state *state = NULL;
3472 size_t max_threads = 0;
3473 bool have_per_thread_cwd = false;
3474 bool have_per_thread_creds = false;
3475 bool do_async = false;
3477 req = tevent_req_create(mem_ctx, &state,
3478 struct vfswrap_getxattrat_state);
3482 *state = (struct vfswrap_getxattrat_state) {
3485 .smb_fname = smb_fname,
3488 max_threads = pthreadpool_tevent_max_threads(dir_fsp->conn->sconn->pool);
3489 if (max_threads >= 1) {
3491 * We need a non sync threadpool!
3493 have_per_thread_cwd = per_thread_cwd_supported();
3495 #ifdef HAVE_LINUX_THREAD_CREDENTIALS
3496 have_per_thread_creds = true;
3498 if (have_per_thread_cwd && have_per_thread_creds) {
3502 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat, profile_p,
3503 state->profile_bytes, 0);
3505 if (fsp_get_pathref_fd(dir_fsp) == -1) {
3506 DBG_ERR("Need a valid directory fd\n");
3507 tevent_req_error(req, EINVAL);
3508 return tevent_req_post(req, ev);
3511 if (alloc_hint > 0) {
3512 state->xattr_value = talloc_zero_array(state,
3515 if (tevent_req_nomem(state->xattr_value, req)) {
3516 return tevent_req_post(req, ev);
3521 vfswrap_getxattrat_do_sync(req);
3522 return tevent_req_post(req, ev);
3526 * Now allocate all parameters from a memory context that won't go away
3527 * no matter what. These paremeters will get used in threads and we
3528 * can't reliably cancel threads, so all buffers passed to the threads
3529 * must not be freed before all referencing threads terminate.
3532 state->name = talloc_strdup(state, smb_fname->base_name);
3533 if (tevent_req_nomem(state->name, req)) {
3534 return tevent_req_post(req, ev);
3537 state->xattr_name = talloc_strdup(state, xattr_name);
3538 if (tevent_req_nomem(state->xattr_name, req)) {
3539 return tevent_req_post(req, ev);
3543 * This is a hot codepath so at first glance one might think we should
3544 * somehow optimize away the token allocation and do a
3545 * talloc_reference() or similar black magic instead. But due to the
3546 * talloc_stackframe pool per SMB2 request this should be a simple copy
3547 * without a malloc in most cases.
3549 if (geteuid() == sec_initial_uid()) {
3550 state->token = root_unix_token(state);
3552 state->token = copy_unix_token(
3554 dir_fsp->conn->session_info->unix_token);
3556 if (tevent_req_nomem(state->token, req)) {
3557 return tevent_req_post(req, ev);
3560 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3562 subreq = pthreadpool_tevent_job_send(
3565 dir_fsp->conn->sconn->pool,
3566 vfswrap_getxattrat_do_async,
3568 if (tevent_req_nomem(subreq, req)) {
3569 return tevent_req_post(req, ev);
3571 tevent_req_set_callback(subreq, vfswrap_getxattrat_done, req);
3573 talloc_set_destructor(state, vfswrap_getxattrat_state_destructor);
3578 static void vfswrap_getxattrat_do_sync(struct tevent_req *req)
3580 struct vfswrap_getxattrat_state *state = tevent_req_data(
3581 req, struct vfswrap_getxattrat_state);
3583 char *tofree = NULL;
3584 char pathbuf[PATH_MAX+1];
3588 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
3589 state->smb_fname->base_name,
3594 if (pathlen == -1) {
3595 tevent_req_error(req, ENOMEM);
3599 state->xattr_size = getxattr(path,
3602 talloc_array_length(state->xattr_value));
3604 TALLOC_FREE(tofree);
3605 if (state->xattr_size == -1) {
3606 tevent_req_error(req, err);
3610 tevent_req_done(req);
3614 static void vfswrap_getxattrat_do_async(void *private_data)
3616 struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3617 private_data, struct vfswrap_getxattrat_state);
3618 struct timespec start_time;
3619 struct timespec end_time;
3622 PROFILE_TIMESTAMP(&start_time);
3623 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
3626 * Here we simulate a getxattrat()
3627 * call using fchdir();getxattr()
3630 per_thread_cwd_activate();
3632 /* Become the correct credential on this thread. */
3633 ret = set_thread_credentials(state->token->uid,
3635 (size_t)state->token->ngroups,
3636 state->token->groups);
3638 state->xattr_size = -1;
3639 state->vfs_aio_state.error = errno;
3643 ret = fchdir(fsp_get_pathref_fd(state->dir_fsp));
3645 state->xattr_size = -1;
3646 state->vfs_aio_state.error = errno;
3650 state->xattr_size = getxattr(state->name,
3653 talloc_array_length(state->xattr_value));
3654 if (state->xattr_size == -1) {
3655 state->vfs_aio_state.error = errno;
3659 PROFILE_TIMESTAMP(&end_time);
3660 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
3661 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3664 static void vfswrap_getxattrat_done(struct tevent_req *subreq)
3666 struct tevent_req *req = tevent_req_callback_data(
3667 subreq, struct tevent_req);
3668 struct vfswrap_getxattrat_state *state = tevent_req_data(
3669 req, struct vfswrap_getxattrat_state);
3674 * Make sure we run as the user again
3676 ok = change_to_user_and_service_by_fsp(state->dir_fsp);
3679 ret = pthreadpool_tevent_job_recv(subreq);
3680 TALLOC_FREE(subreq);
3681 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
3682 talloc_set_destructor(state, NULL);
3684 if (ret != EAGAIN) {
3685 tevent_req_error(req, ret);
3689 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
3690 * means the lower level pthreadpool failed to create a new
3691 * thread. Fallback to sync processing in that case to allow
3692 * some progress for the client.
3694 vfswrap_getxattrat_do_sync(req);
3698 if (state->xattr_size == -1) {
3699 tevent_req_error(req, state->vfs_aio_state.error);
3703 if (state->xattr_value == NULL) {
3705 * The caller only wanted the size.
3707 tevent_req_done(req);
3712 * shrink the buffer to the returned size.
3713 * (can't fail). It means NULL if size is 0.
3715 state->xattr_value = talloc_realloc(state,
3720 tevent_req_done(req);
3723 static ssize_t vfswrap_getxattrat_recv(struct tevent_req *req,
3724 struct vfs_aio_state *aio_state,
3725 TALLOC_CTX *mem_ctx,
3726 uint8_t **xattr_value)
3728 struct vfswrap_getxattrat_state *state = tevent_req_data(
3729 req, struct vfswrap_getxattrat_state);
3732 if (tevent_req_is_unix_error(req, &aio_state->error)) {
3733 tevent_req_received(req);
3737 *aio_state = state->vfs_aio_state;
3738 xattr_size = state->xattr_size;
3739 if (xattr_value != NULL) {
3740 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
3743 tevent_req_received(req);
3747 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle,
3748 struct files_struct *fsp,
3753 int fd = fsp_get_pathref_fd(fsp);
3755 if (!fsp->fsp_flags.is_pathref) {
3756 return fgetxattr(fd, name, value, size);
3759 if (fsp->fsp_flags.have_proc_fds) {
3760 const char *p = NULL;
3763 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3768 return getxattr(p, name, value, size);
3772 * This is no longer a handle based call.
3774 return getxattr(fsp->fsp_name->base_name, name, value, size);
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 .kernel_flock_fn = vfswrap_kernel_flock,
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);