2 Unix SMB/CIFS implementation.
3 Wrap disk only vfs functions to sidestep dodgy compilers.
4 Copyright (C) Tim Potter 1998
5 Copyright (C) Jeremy Allison 2007
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "system/time.h"
23 #include "system/filesys.h"
24 #include "smbd/smbd.h"
25 #include "smbd/globals.h"
27 #include "smbprofile.h"
28 #include "../libcli/security/security.h"
29 #include "passdb/lookup_sid.h"
30 #include "source3/include/msdfs.h"
31 #include "librpc/gen_ndr/ndr_dfsblobs.h"
32 #include "lib/util/tevent_unix.h"
33 #include "lib/util/tevent_ntstatus.h"
34 #include "lib/util/sys_rw.h"
35 #include "lib/pthreadpool/pthreadpool_tevent.h"
36 #include "librpc/gen_ndr/ndr_ioctl.h"
37 #include "offload_token.h"
38 #include "util_reparse.h"
39 #include "lib/util/string_wrappers.h"
42 #define DBGC_CLASS DBGC_VFS
44 /* Check for NULL pointer parameters in vfswrap_* functions */
46 /* We don't want to have NULL function pointers lying around. Someone
47 is sure to try and execute them. These stubs are used to prevent
50 static int vfswrap_connect(vfs_handle_struct *handle, const char *service, const char *user)
52 handle->conn->have_proc_fds = sys_have_proc_fds();
53 return 0; /* Return >= 0 for success */
56 static void vfswrap_disconnect(vfs_handle_struct *handle)
62 static uint64_t vfswrap_disk_free(vfs_handle_struct *handle,
63 const struct smb_filename *smb_fname,
68 if (sys_fsusage(smb_fname->base_name, dfree, dsize) != 0) {
76 static int vfswrap_get_quota(struct vfs_handle_struct *handle,
77 const struct smb_filename *smb_fname,
78 enum SMB_QUOTA_TYPE qtype,
82 #ifdef HAVE_SYS_QUOTAS
85 START_PROFILE(syscall_get_quota);
86 result = sys_get_quota(smb_fname->base_name, qtype, id, qt);
87 END_PROFILE(syscall_get_quota);
95 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
97 #ifdef HAVE_SYS_QUOTAS
100 START_PROFILE(syscall_set_quota);
101 result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
102 END_PROFILE(syscall_set_quota);
110 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
111 struct files_struct *fsp,
112 struct shadow_copy_data *shadow_copy_data,
116 return -1; /* Not implemented. */
119 static int vfswrap_statvfs(struct vfs_handle_struct *handle,
120 const struct smb_filename *smb_fname,
121 vfs_statvfs_struct *statbuf)
123 return sys_statvfs(smb_fname->base_name, statbuf);
126 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
127 enum timestamp_set_resolution *p_ts_res)
129 const struct loadparm_substitution *lp_sub =
130 loadparm_s3_global_substitution();
131 connection_struct *conn = handle->conn;
132 uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
133 struct smb_filename *smb_fname_cpath = NULL;
134 struct vfs_statvfs_struct statbuf;
137 smb_fname_cpath = synthetic_smb_fname(talloc_tos(),
143 if (smb_fname_cpath == NULL) {
147 ZERO_STRUCT(statbuf);
148 ret = SMB_VFS_STATVFS(conn, smb_fname_cpath, &statbuf);
150 caps = statbuf.FsCapabilities;
153 *p_ts_res = TIMESTAMP_SET_SECONDS;
155 /* Work out what timestamp resolution we can
156 * use when setting a timestamp. */
158 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
160 TALLOC_FREE(smb_fname_cpath);
164 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
165 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
166 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
167 /* If any of the normal UNIX directory timestamps
168 * have a non-zero tv_nsec component assume
169 * we might be able to set sub-second timestamps.
170 * See what filetime set primitives we have.
172 #if defined(HAVE_UTIMENSAT)
173 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
174 #elif defined(HAVE_UTIMES)
175 /* utimes allows msec timestamps to be set. */
176 *p_ts_res = TIMESTAMP_SET_MSEC;
177 #elif defined(HAVE_UTIME)
178 /* utime only allows sec timestamps to be set. */
179 *p_ts_res = TIMESTAMP_SET_SECONDS;
182 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
184 "available on share %s, directory %s\n",
185 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
186 lp_servicename(talloc_tos(), lp_sub, conn->params->service),
187 conn->connectpath ));
189 TALLOC_FREE(smb_fname_cpath);
193 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
194 struct dfs_GetDFSReferral *r)
196 struct junction_map *junction = NULL;
198 bool self_referral = false;
199 char *pathnamep = NULL;
200 char *local_dfs_path = NULL;
203 uint16_t max_referral_level = r->in.req.max_referral_level;
206 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
209 /* get the junction entry */
210 if (r->in.req.servername == NULL) {
211 return NT_STATUS_NOT_FOUND;
215 * Trim pathname sent by client so it begins with only one backslash.
216 * Two backslashes confuse some dfs clients
219 local_dfs_path = talloc_strdup(r, r->in.req.servername);
220 if (local_dfs_path == NULL) {
221 return NT_STATUS_NO_MEMORY;
223 pathnamep = local_dfs_path;
224 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
225 IS_DIRECTORY_SEP(pathnamep[1])) {
229 junction = talloc_zero(r, struct junction_map);
230 if (junction == NULL) {
231 return NT_STATUS_NO_MEMORY;
234 /* The following call can change cwd. */
235 status = get_referred_path(r,
236 handle->conn->session_info,
238 handle->conn->sconn->remote_address,
239 handle->conn->sconn->local_address,
240 !handle->conn->sconn->using_smb2,
241 junction, &consumedcnt, &self_referral);
242 if (!NT_STATUS_IS_OK(status)) {
243 struct smb_filename connectpath_fname = {
244 .base_name = handle->conn->connectpath
246 vfs_ChDir(handle->conn, &connectpath_fname);
250 struct smb_filename connectpath_fname = {
251 .base_name = handle->conn->connectpath
253 vfs_ChDir(handle->conn, &connectpath_fname);
256 if (!self_referral) {
257 pathnamep[consumedcnt] = '\0';
260 dbgtext("Path %s to alternate path(s):",
262 for (i=0; i < junction->referral_count; i++) {
264 junction->referral_list[i].alternate_path);
270 if (r->in.req.max_referral_level <= 2) {
271 max_referral_level = 2;
273 if (r->in.req.max_referral_level >= 3) {
274 max_referral_level = 3;
277 r->out.resp = talloc_zero(r, struct dfs_referral_resp);
278 if (r->out.resp == NULL) {
279 return NT_STATUS_NO_MEMORY;
282 r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
283 r->out.resp->nb_referrals = junction->referral_count;
285 r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
287 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
290 r->out.resp->referral_entries = talloc_zero_array(r,
291 struct dfs_referral_type,
292 r->out.resp->nb_referrals);
293 if (r->out.resp->referral_entries == NULL) {
294 return NT_STATUS_NO_MEMORY;
297 switch (max_referral_level) {
299 for(i=0; i < junction->referral_count; i++) {
300 struct referral *ref = &junction->referral_list[i];
301 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
302 struct dfs_referral_type *t =
303 &r->out.resp->referral_entries[i];
304 struct dfs_referral_v2 *v2 = &t->referral.v2;
307 v2->size = VERSION2_REFERRAL_SIZE;
309 v2->server_type = DFS_SERVER_ROOT;
311 v2->server_type = DFS_SERVER_NON_ROOT;
314 v2->proximity = ref->proximity;
316 v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
317 if (v2->DFS_path == NULL) {
318 return NT_STATUS_NO_MEMORY;
320 v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
321 if (v2->DFS_alt_path == NULL) {
322 return NT_STATUS_NO_MEMORY;
324 v2->netw_address = talloc_strdup(mem_ctx,
325 ref->alternate_path);
326 if (v2->netw_address == NULL) {
327 return NT_STATUS_NO_MEMORY;
333 for(i=0; i < junction->referral_count; i++) {
334 struct referral *ref = &junction->referral_list[i];
335 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
336 struct dfs_referral_type *t =
337 &r->out.resp->referral_entries[i];
338 struct dfs_referral_v3 *v3 = &t->referral.v3;
339 struct dfs_normal_referral *r1 = &v3->referrals.r1;
342 v3->size = VERSION3_REFERRAL_SIZE;
344 v3->server_type = DFS_SERVER_ROOT;
346 v3->server_type = DFS_SERVER_NON_ROOT;
350 r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
351 if (r1->DFS_path == NULL) {
352 return NT_STATUS_NO_MEMORY;
354 r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
355 if (r1->DFS_alt_path == NULL) {
356 return NT_STATUS_NO_MEMORY;
358 r1->netw_address = talloc_strdup(mem_ctx,
359 ref->alternate_path);
360 if (r1->netw_address == NULL) {
361 return NT_STATUS_NO_MEMORY;
366 DEBUG(0,("Invalid dfs referral version: %d\n",
367 max_referral_level));
368 return NT_STATUS_INVALID_LEVEL;
372 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
378 static NTSTATUS vfswrap_create_dfs_pathat(struct vfs_handle_struct *handle,
379 struct files_struct *dirfsp,
380 const struct smb_filename *smb_fname,
381 const struct referral *reflist,
382 size_t referral_count)
384 TALLOC_CTX *frame = talloc_stackframe();
385 NTSTATUS status = NT_STATUS_NO_MEMORY;
387 char *msdfs_link = NULL;
389 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
391 /* Form the msdfs_link contents */
392 msdfs_link = msdfs_link_string(frame,
395 if (msdfs_link == NULL) {
399 ret = symlinkat(msdfs_link,
400 fsp_get_io_fd(dirfsp),
401 smb_fname->base_name);
403 status = NT_STATUS_OK;
405 status = map_nt_error_from_unix(errno);
415 * Read and return the contents of a DFS redirect given a
416 * pathname. A caller can pass in NULL for ppreflist and
417 * preferral_count but still determine if this was a
418 * DFS redirect point by getting NT_STATUS_OK back
419 * without incurring the overhead of reading and parsing
420 * the referral contents.
423 static NTSTATUS vfswrap_read_dfs_pathat(struct vfs_handle_struct *handle,
425 struct files_struct *dirfsp,
426 struct smb_filename *smb_fname,
427 struct referral **ppreflist,
428 size_t *preferral_count)
430 NTSTATUS status = NT_STATUS_NO_MEMORY;
432 char *link_target = NULL;
435 #if defined(HAVE_BROKEN_READLINK)
436 char link_target_buf[PATH_MAX];
438 char link_target_buf[7];
442 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
444 if (is_named_stream(smb_fname)) {
445 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
449 if (ppreflist == NULL && preferral_count == NULL) {
451 * We're only checking if this is a DFS
452 * redirect. We don't need to return data.
454 bufsize = sizeof(link_target_buf);
455 link_target = link_target_buf;
458 link_target = talloc_array(mem_ctx, char, bufsize);
464 referral_len = readlinkat(fsp_get_io_fd(dirfsp),
465 smb_fname->base_name,
468 if (referral_len == -1) {
469 if (errno == EINVAL) {
471 * If the path isn't a link, readlinkat
472 * returns EINVAL. Allow the caller to
475 DBG_INFO("%s is not a link.\n", smb_fname->base_name);
476 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
478 status = map_nt_error_from_unix(errno);
479 DBG_ERR("Error reading "
480 "msdfs link %s: %s\n",
481 smb_fname->base_name,
486 link_target[referral_len] = '\0';
488 DBG_INFO("%s -> %s\n",
489 smb_fname->base_name,
492 if (!strnequal(link_target, "msdfs:", 6)) {
493 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
497 ret = sys_lstat(smb_fname->base_name,
499 lp_fake_directory_create_times(SNUM(handle->conn)));
501 status = map_nt_error_from_unix(errno);
505 if (ppreflist == NULL && preferral_count == NULL) {
506 /* Early return for checking if this is a DFS link. */
510 ok = parse_msdfs_symlink(mem_ctx,
511 lp_msdfs_shuffle_referrals(SNUM(handle->conn)),
517 status = NT_STATUS_OK;
519 status = NT_STATUS_NO_MEMORY;
524 if (link_target != link_target_buf) {
525 TALLOC_FREE(link_target);
530 static NTSTATUS vfswrap_snap_check_path(struct vfs_handle_struct *handle,
532 const char *service_path,
535 return NT_STATUS_NOT_SUPPORTED;
538 static NTSTATUS vfswrap_snap_create(struct vfs_handle_struct *handle,
540 const char *base_volume,
546 return NT_STATUS_NOT_SUPPORTED;
549 static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle,
554 return NT_STATUS_NOT_SUPPORTED;
557 /* Directory operations */
559 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
566 START_PROFILE(syscall_fdopendir);
567 result = sys_fdopendir(fsp_get_io_fd(fsp));
568 END_PROFILE(syscall_fdopendir);
573 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
574 struct files_struct *dirfsp,
576 SMB_STRUCT_STAT *sbuf)
578 struct dirent *result;
579 bool do_stat = false;
580 bool fake_ctime = lp_fake_directory_create_times(SNUM(handle->conn));
581 int flags = AT_SYMLINK_NOFOLLOW;
585 START_PROFILE(syscall_readdir);
587 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
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 /* See if we can efficiently return this. */
612 ret = fstatat(dirfd(dirp),
621 * As this is an optimization, ignore it if we stat'ed a
622 * symlink for non-POSIX context. Make the caller do it again
623 * as we don't know if they wanted the link info, or its
626 if (S_ISLNK(st.st_mode) &&
627 !(dirfsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH))
631 init_stat_ex_from_stat(sbuf, &st, fake_ctime);
636 static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
637 const struct smb_filename *fname,
639 struct readdir_attr_data **attr_data)
641 return NT_STATUS_NOT_SUPPORTED;
644 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
646 START_PROFILE(syscall_seekdir);
647 seekdir(dirp, offset);
648 END_PROFILE(syscall_seekdir);
651 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
654 START_PROFILE(syscall_telldir);
655 result = telldir(dirp);
656 END_PROFILE(syscall_telldir);
660 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
662 START_PROFILE(syscall_rewinddir);
664 END_PROFILE(syscall_rewinddir);
667 static int vfswrap_mkdirat(vfs_handle_struct *handle,
668 struct files_struct *dirfsp,
669 const struct smb_filename *smb_fname,
673 struct smb_filename *parent = NULL;
676 START_PROFILE(syscall_mkdirat);
678 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
680 if (lp_inherit_acls(SNUM(handle->conn))) {
681 ok = parent_smb_fname(talloc_tos(), smb_fname, &parent, NULL);
682 if (ok && directory_has_default_acl(handle->conn,
686 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
692 result = mkdirat(fsp_get_pathref_fd(dirfsp), smb_fname->base_name, mode);
694 END_PROFILE(syscall_mkdirat);
698 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
702 START_PROFILE(syscall_closedir);
703 result = closedir(dirp);
704 END_PROFILE(syscall_closedir);
708 /* File operations */
710 static int vfswrap_openat(vfs_handle_struct *handle,
711 const struct files_struct *dirfsp,
712 const struct smb_filename *smb_fname,
717 bool have_opath = false;
718 bool became_root = false;
721 START_PROFILE(syscall_openat);
723 if (is_named_stream(smb_fname)) {
731 if (fsp->fsp_flags.is_pathref) {
736 if (fsp->fsp_flags.is_pathref && !have_opath) {
741 result = openat(fsp_get_pathref_fd(dirfsp),
742 smb_fname->base_name,
750 fsp->fsp_flags.have_proc_fds = fsp->conn->have_proc_fds;
753 END_PROFILE(syscall_openat);
756 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
757 struct smb_request *req,
758 struct smb_filename *smb_fname,
759 uint32_t access_mask,
760 uint32_t share_access,
761 uint32_t create_disposition,
762 uint32_t create_options,
763 uint32_t file_attributes,
764 uint32_t oplock_request,
765 const struct smb2_lease *lease,
766 uint64_t allocation_size,
767 uint32_t private_flags,
768 struct security_descriptor *sd,
769 struct ea_list *ea_list,
770 files_struct **result,
772 const struct smb2_create_blobs *in_context_blobs,
773 struct smb2_create_blobs *out_context_blobs)
775 return create_file_default(handle->conn, req, smb_fname,
776 access_mask, share_access,
777 create_disposition, create_options,
778 file_attributes, oplock_request, lease,
779 allocation_size, private_flags,
781 pinfo, in_context_blobs, out_context_blobs);
784 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
788 START_PROFILE(syscall_close);
789 result = fd_close_posix(fsp);
790 END_PROFILE(syscall_close);
794 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
795 size_t n, off_t offset)
799 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
800 START_PROFILE_BYTES(syscall_pread, n);
801 result = sys_pread_full(fsp_get_io_fd(fsp), data, n, offset);
802 END_PROFILE_BYTES(syscall_pread);
804 if (result == -1 && errno == ESPIPE) {
805 /* Maintain the fiction that pipes can be seeked (sought?) on. */
806 result = sys_read(fsp_get_io_fd(fsp), data, n);
807 fh_set_pos(fsp->fh, 0);
810 #else /* HAVE_PREAD */
813 #endif /* HAVE_PREAD */
818 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
819 size_t n, off_t offset)
823 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
824 START_PROFILE_BYTES(syscall_pwrite, n);
825 result = sys_pwrite_full(fsp_get_io_fd(fsp), data, n, offset);
826 END_PROFILE_BYTES(syscall_pwrite);
828 if (result == -1 && errno == ESPIPE) {
829 /* Maintain the fiction that pipes can be sought on. */
830 result = sys_write(fsp_get_io_fd(fsp), data, n);
833 #else /* HAVE_PWRITE */
836 #endif /* HAVE_PWRITE */
841 struct vfswrap_pread_state {
848 struct vfs_aio_state vfs_aio_state;
849 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
852 static void vfs_pread_do(void *private_data);
853 static void vfs_pread_done(struct tevent_req *subreq);
854 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state);
856 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
858 struct tevent_context *ev,
859 struct files_struct *fsp,
861 size_t n, off_t offset)
863 struct tevent_req *req, *subreq;
864 struct vfswrap_pread_state *state;
866 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
872 state->fd = fsp_get_io_fd(fsp);
875 state->offset = offset;
877 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
878 state->profile_bytes, n);
879 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
881 subreq = pthreadpool_tevent_job_send(
882 state, ev, handle->conn->sconn->pool,
883 vfs_pread_do, state);
884 if (tevent_req_nomem(subreq, req)) {
885 return tevent_req_post(req, ev);
887 tevent_req_set_callback(subreq, vfs_pread_done, req);
889 talloc_set_destructor(state, vfs_pread_state_destructor);
894 static void vfs_pread_do(void *private_data)
896 struct vfswrap_pread_state *state = talloc_get_type_abort(
897 private_data, struct vfswrap_pread_state);
898 struct timespec start_time;
899 struct timespec end_time;
901 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
903 PROFILE_TIMESTAMP(&start_time);
905 state->ret = sys_pread_full(state->fd,
910 if (state->ret == -1) {
911 state->vfs_aio_state.error = errno;
914 PROFILE_TIMESTAMP(&end_time);
916 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
918 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
921 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state)
926 static void vfs_pread_done(struct tevent_req *subreq)
928 struct tevent_req *req = tevent_req_callback_data(
929 subreq, struct tevent_req);
930 struct vfswrap_pread_state *state = tevent_req_data(
931 req, struct vfswrap_pread_state);
934 ret = pthreadpool_tevent_job_recv(subreq);
936 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
937 talloc_set_destructor(state, NULL);
940 tevent_req_error(req, ret);
944 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
945 * means the lower level pthreadpool failed to create a new
946 * thread. Fallback to sync processing in that case to allow
947 * some progress for the client.
952 tevent_req_done(req);
955 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
956 struct vfs_aio_state *vfs_aio_state)
958 struct vfswrap_pread_state *state = tevent_req_data(
959 req, struct vfswrap_pread_state);
961 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
965 *vfs_aio_state = state->vfs_aio_state;
969 struct vfswrap_pwrite_state {
976 struct vfs_aio_state vfs_aio_state;
977 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
980 static void vfs_pwrite_do(void *private_data);
981 static void vfs_pwrite_done(struct tevent_req *subreq);
982 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state);
984 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
986 struct tevent_context *ev,
987 struct files_struct *fsp,
989 size_t n, off_t offset)
991 struct tevent_req *req, *subreq;
992 struct vfswrap_pwrite_state *state;
994 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
1000 state->fd = fsp_get_io_fd(fsp);
1003 state->offset = offset;
1005 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
1006 state->profile_bytes, n);
1007 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1009 subreq = pthreadpool_tevent_job_send(
1010 state, ev, handle->conn->sconn->pool,
1011 vfs_pwrite_do, state);
1012 if (tevent_req_nomem(subreq, req)) {
1013 return tevent_req_post(req, ev);
1015 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
1017 talloc_set_destructor(state, vfs_pwrite_state_destructor);
1022 static void vfs_pwrite_do(void *private_data)
1024 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
1025 private_data, struct vfswrap_pwrite_state);
1026 struct timespec start_time;
1027 struct timespec end_time;
1029 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
1031 PROFILE_TIMESTAMP(&start_time);
1033 state->ret = sys_pwrite_full(state->fd,
1038 if (state->ret == -1) {
1039 state->vfs_aio_state.error = errno;
1042 PROFILE_TIMESTAMP(&end_time);
1044 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1046 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1049 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state)
1054 static void vfs_pwrite_done(struct tevent_req *subreq)
1056 struct tevent_req *req = tevent_req_callback_data(
1057 subreq, struct tevent_req);
1058 struct vfswrap_pwrite_state *state = tevent_req_data(
1059 req, struct vfswrap_pwrite_state);
1062 ret = pthreadpool_tevent_job_recv(subreq);
1063 TALLOC_FREE(subreq);
1064 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1065 talloc_set_destructor(state, NULL);
1067 if (ret != EAGAIN) {
1068 tevent_req_error(req, ret);
1072 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1073 * means the lower level pthreadpool failed to create a new
1074 * thread. Fallback to sync processing in that case to allow
1075 * some progress for the client.
1077 vfs_pwrite_do(state);
1080 tevent_req_done(req);
1083 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
1084 struct vfs_aio_state *vfs_aio_state)
1086 struct vfswrap_pwrite_state *state = tevent_req_data(
1087 req, struct vfswrap_pwrite_state);
1089 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1093 *vfs_aio_state = state->vfs_aio_state;
1097 struct vfswrap_fsync_state {
1101 struct vfs_aio_state vfs_aio_state;
1102 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
1105 static void vfs_fsync_do(void *private_data);
1106 static void vfs_fsync_done(struct tevent_req *subreq);
1107 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state);
1109 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
1110 TALLOC_CTX *mem_ctx,
1111 struct tevent_context *ev,
1112 struct files_struct *fsp)
1114 struct tevent_req *req, *subreq;
1115 struct vfswrap_fsync_state *state;
1117 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
1123 state->fd = fsp_get_io_fd(fsp);
1125 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_fsync, profile_p,
1126 state->profile_bytes, 0);
1127 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1129 subreq = pthreadpool_tevent_job_send(
1130 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
1131 if (tevent_req_nomem(subreq, req)) {
1132 return tevent_req_post(req, ev);
1134 tevent_req_set_callback(subreq, vfs_fsync_done, req);
1136 talloc_set_destructor(state, vfs_fsync_state_destructor);
1141 static void vfs_fsync_do(void *private_data)
1143 struct vfswrap_fsync_state *state = talloc_get_type_abort(
1144 private_data, struct vfswrap_fsync_state);
1145 struct timespec start_time;
1146 struct timespec end_time;
1148 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
1150 PROFILE_TIMESTAMP(&start_time);
1153 state->ret = fsync(state->fd);
1154 } while ((state->ret == -1) && (errno == EINTR));
1156 if (state->ret == -1) {
1157 state->vfs_aio_state.error = errno;
1160 PROFILE_TIMESTAMP(&end_time);
1162 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1164 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1167 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state)
1172 static void vfs_fsync_done(struct tevent_req *subreq)
1174 struct tevent_req *req = tevent_req_callback_data(
1175 subreq, struct tevent_req);
1176 struct vfswrap_fsync_state *state = tevent_req_data(
1177 req, struct vfswrap_fsync_state);
1180 ret = pthreadpool_tevent_job_recv(subreq);
1181 TALLOC_FREE(subreq);
1182 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1183 talloc_set_destructor(state, NULL);
1185 if (ret != EAGAIN) {
1186 tevent_req_error(req, ret);
1190 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1191 * means the lower level pthreadpool failed to create a new
1192 * thread. Fallback to sync processing in that case to allow
1193 * some progress for the client.
1195 vfs_fsync_do(state);
1198 tevent_req_done(req);
1201 static int vfswrap_fsync_recv(struct tevent_req *req,
1202 struct vfs_aio_state *vfs_aio_state)
1204 struct vfswrap_fsync_state *state = tevent_req_data(
1205 req, struct vfswrap_fsync_state);
1207 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1211 *vfs_aio_state = state->vfs_aio_state;
1215 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1219 START_PROFILE(syscall_lseek);
1221 result = lseek(fsp_get_io_fd(fsp), offset, whence);
1223 * We want to maintain the fiction that we can seek
1224 * on a fifo for file system purposes. This allows
1225 * people to set up UNIX fifo's that feed data to Windows
1226 * applications. JRA.
1229 if((result == -1) && (errno == ESPIPE)) {
1234 END_PROFILE(syscall_lseek);
1238 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1239 off_t offset, size_t n)
1243 START_PROFILE_BYTES(syscall_sendfile, n);
1244 result = sys_sendfile(tofd, fsp_get_io_fd(fromfsp), hdr, offset, n);
1245 END_PROFILE_BYTES(syscall_sendfile);
1249 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1251 files_struct *tofsp,
1257 START_PROFILE_BYTES(syscall_recvfile, n);
1258 result = sys_recvfile(fromfd, fsp_get_io_fd(tofsp), offset, n);
1259 END_PROFILE_BYTES(syscall_recvfile);
1263 static int vfswrap_renameat(vfs_handle_struct *handle,
1264 files_struct *srcfsp,
1265 const struct smb_filename *smb_fname_src,
1266 files_struct *dstfsp,
1267 const struct smb_filename *smb_fname_dst)
1271 START_PROFILE(syscall_renameat);
1273 if (is_named_stream(smb_fname_src) || is_named_stream(smb_fname_dst)) {
1278 result = renameat(fsp_get_pathref_fd(srcfsp),
1279 smb_fname_src->base_name,
1280 fsp_get_pathref_fd(dstfsp),
1281 smb_fname_dst->base_name);
1284 END_PROFILE(syscall_renameat);
1288 static int vfswrap_stat(vfs_handle_struct *handle,
1289 struct smb_filename *smb_fname)
1293 START_PROFILE(syscall_stat);
1295 if (is_named_stream(smb_fname)) {
1300 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1301 lp_fake_directory_create_times(SNUM(handle->conn)));
1303 END_PROFILE(syscall_stat);
1307 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1311 START_PROFILE(syscall_fstat);
1312 result = sys_fstat(fsp_get_pathref_fd(fsp),
1313 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1314 END_PROFILE(syscall_fstat);
1318 static int vfswrap_lstat(vfs_handle_struct *handle,
1319 struct smb_filename *smb_fname)
1323 START_PROFILE(syscall_lstat);
1325 if (is_named_stream(smb_fname)) {
1330 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1331 lp_fake_directory_create_times(SNUM(handle->conn)));
1333 END_PROFILE(syscall_lstat);
1337 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1339 enum vfs_translate_direction direction,
1340 TALLOC_CTX *mem_ctx,
1343 return NT_STATUS_NONE_MAPPED;
1347 * Implement the default fsctl operation.
1349 static bool vfswrap_logged_ioctl_message = false;
1351 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1352 struct files_struct *fsp,
1355 uint16_t req_flags, /* Needed for UNICODE ... */
1356 const uint8_t *_in_data,
1358 uint8_t **_out_data,
1359 uint32_t max_out_len,
1362 const char *in_data = (const char *)_in_data;
1363 char **out_data = (char **)_out_data;
1367 case FSCTL_SET_SPARSE:
1369 bool set_sparse = true;
1371 if (in_len >= 1 && in_data[0] == 0) {
1375 status = file_set_sparse(handle->conn, fsp, set_sparse);
1377 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1378 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1379 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1380 nt_errstr(status)));
1385 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1387 unsigned char objid[16];
1388 char *return_data = NULL;
1390 /* This should return the object-id on this file.
1391 * I think I'll make this be the inode+dev. JRA.
1394 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1395 fsp_fnum_dbg(fsp)));
1397 *out_len = MIN(max_out_len, 64);
1399 /* Hmmm, will this cause problems if less data asked for? */
1400 return_data = talloc_array(ctx, char, 64);
1401 if (return_data == NULL) {
1402 return NT_STATUS_NO_MEMORY;
1405 /* For backwards compatibility only store the dev/inode. */
1406 push_file_id_16(return_data, &fsp->file_id);
1407 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1408 push_file_id_16(return_data+32, &fsp->file_id);
1409 memset(return_data+48, 0, 16);
1410 *out_data = return_data;
1411 return NT_STATUS_OK;
1414 case FSCTL_GET_REPARSE_POINT:
1416 status = fsctl_get_reparse_point(
1417 fsp, ctx, out_data, max_out_len, out_len);
1421 case FSCTL_SET_REPARSE_POINT:
1423 status = fsctl_set_reparse_point(fsp, ctx, _in_data, in_len);
1427 case FSCTL_DELETE_REPARSE_POINT:
1429 status = fsctl_del_reparse_point(fsp, ctx, _in_data, in_len);
1433 case FSCTL_GET_SHADOW_COPY_DATA:
1436 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1437 * and return their volume names. If max_data_count is 16, then it is just
1438 * asking for the number of volumes and length of the combined names.
1440 * pdata is the data allocated by our caller, but that uses
1441 * total_data_count (which is 0 in our case) rather than max_data_count.
1442 * Allocate the correct amount and return the pointer to let
1443 * it be deallocated when we return.
1445 struct shadow_copy_data *shadow_data = NULL;
1446 bool labels = False;
1447 uint32_t labels_data_count = 0;
1449 char *cur_pdata = NULL;
1451 if (max_out_len < 16) {
1452 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1454 return NT_STATUS_INVALID_PARAMETER;
1457 if (max_out_len > 16) {
1461 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1462 if (shadow_data == NULL) {
1463 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1464 return NT_STATUS_NO_MEMORY;
1468 * Call the VFS routine to actually do the work.
1470 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1473 /* broken module didn't set errno on error */
1474 status = NT_STATUS_UNSUCCESSFUL;
1476 status = map_nt_error_from_unix(errno);
1477 if (NT_STATUS_EQUAL(status,
1478 NT_STATUS_NOT_SUPPORTED)) {
1482 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1483 "connectpath %s, failed - %s.\n",
1484 fsp->conn->connectpath,
1485 nt_errstr(status)));
1486 TALLOC_FREE(shadow_data);
1490 labels_data_count = (shadow_data->num_volumes * 2 *
1491 sizeof(SHADOW_COPY_LABEL)) + 2;
1496 *out_len = 12 + labels_data_count;
1499 if (max_out_len < *out_len) {
1500 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1501 max_out_len, *out_len));
1502 TALLOC_FREE(shadow_data);
1503 return NT_STATUS_BUFFER_TOO_SMALL;
1506 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1507 if (cur_pdata == NULL) {
1508 TALLOC_FREE(shadow_data);
1509 return NT_STATUS_NO_MEMORY;
1512 *out_data = cur_pdata;
1514 /* num_volumes 4 bytes */
1515 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1518 /* num_labels 4 bytes */
1519 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1522 /* needed_data_count 4 bytes */
1523 SIVAL(cur_pdata, 8, labels_data_count);
1527 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1528 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1529 if (labels && shadow_data->labels) {
1530 for (i=0; i<shadow_data->num_volumes; i++) {
1532 status = srvstr_push(cur_pdata, req_flags,
1533 cur_pdata, shadow_data->labels[i],
1534 2 * sizeof(SHADOW_COPY_LABEL),
1535 STR_UNICODE|STR_TERMINATE, &len);
1536 if (!NT_STATUS_IS_OK(status)) {
1537 TALLOC_FREE(*out_data);
1538 TALLOC_FREE(shadow_data);
1541 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1542 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1546 TALLOC_FREE(shadow_data);
1548 return NT_STATUS_OK;
1551 case FSCTL_FIND_FILES_BY_SID:
1553 /* pretend this succeeded -
1555 * we have to send back a list with all files owned by this SID
1557 * but I have to check that --metze
1561 struct dom_sid_buf buf;
1565 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1566 fsp_fnum_dbg(fsp)));
1569 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1570 return NT_STATUS_INVALID_PARAMETER;
1573 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1575 /* unknown 4 bytes: this is not the length of the sid :-( */
1576 /*unknown = IVAL(pdata,0);*/
1578 ret = sid_parse(_in_data + 4, sid_len, &sid);
1580 return NT_STATUS_INVALID_PARAMETER;
1582 DEBUGADD(10, ("for SID: %s\n",
1583 dom_sid_str_buf(&sid, &buf)));
1585 if (!sid_to_uid(&sid, &uid)) {
1586 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1587 dom_sid_str_buf(&sid, &buf),
1588 (unsigned long)sid_len));
1592 /* we can take a look at the find source :-)
1594 * find ./ -uid $uid -name '*' is what we need here
1597 * and send 4bytes len and then NULL terminated unicode strings
1600 * but I don't know how to deal with the paged results
1601 * (maybe we can hang the result anywhere in the fsp struct)
1603 * but I don't know how to deal with the paged results
1604 * (maybe we can hang the result anywhere in the fsp struct)
1606 * we don't send all files at once
1607 * and at the next we should *not* start from the beginning,
1608 * so we have to cache the result
1613 /* this works for now... */
1614 return NT_STATUS_OK;
1617 case FSCTL_QUERY_ALLOCATED_RANGES:
1619 /* FIXME: This is just a dummy reply, telling that all of the
1620 * file is allocated. MKS cp needs that.
1621 * Adding the real allocated ranges via FIEMAP on Linux
1622 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1623 * this FSCTL correct for sparse files.
1625 uint64_t offset, length;
1626 char *out_data_tmp = NULL;
1629 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1631 return NT_STATUS_INVALID_PARAMETER;
1634 if (max_out_len < 16) {
1635 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1637 return NT_STATUS_INVALID_PARAMETER;
1640 offset = BVAL(in_data,0);
1641 length = BVAL(in_data,8);
1643 if (offset + length < offset) {
1644 /* No 64-bit integer wrap. */
1645 return NT_STATUS_INVALID_PARAMETER;
1648 /* Shouldn't this be SMB_VFS_STAT ... ? */
1649 status = vfs_stat_fsp(fsp);
1650 if (!NT_STATUS_IS_OK(status)) {
1655 out_data_tmp = talloc_array(ctx, char, *out_len);
1656 if (out_data_tmp == NULL) {
1657 DEBUG(10, ("unable to allocate memory for response\n"));
1658 return NT_STATUS_NO_MEMORY;
1661 if (offset > fsp->fsp_name->st.st_ex_size ||
1662 fsp->fsp_name->st.st_ex_size == 0 ||
1664 memset(out_data_tmp, 0, *out_len);
1666 uint64_t end = offset + length;
1667 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1668 SBVAL(out_data_tmp, 0, 0);
1669 SBVAL(out_data_tmp, 8, end);
1672 *out_data = out_data_tmp;
1674 return NT_STATUS_OK;
1677 case FSCTL_IS_VOLUME_DIRTY:
1679 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1680 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1682 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1683 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1685 return NT_STATUS_INVALID_PARAMETER;
1690 * Only print once ... unfortunately there could be lots of
1691 * different FSCTLs that are called.
1693 if (!vfswrap_logged_ioctl_message) {
1694 vfswrap_logged_ioctl_message = true;
1695 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1696 __func__, function));
1700 return NT_STATUS_NOT_SUPPORTED;
1703 static bool vfswrap_is_offline(struct connection_struct *conn,
1704 const struct smb_filename *fname);
1706 struct vfswrap_get_dos_attributes_state {
1707 struct vfs_aio_state aio_state;
1708 connection_struct *conn;
1709 TALLOC_CTX *mem_ctx;
1710 struct tevent_context *ev;
1711 files_struct *dir_fsp;
1712 struct smb_filename *smb_fname;
1717 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq);
1719 static struct tevent_req *vfswrap_get_dos_attributes_send(
1720 TALLOC_CTX *mem_ctx,
1721 struct tevent_context *ev,
1722 struct vfs_handle_struct *handle,
1723 files_struct *dir_fsp,
1724 struct smb_filename *smb_fname)
1726 struct tevent_req *req = NULL;
1727 struct tevent_req *subreq = NULL;
1728 struct vfswrap_get_dos_attributes_state *state = NULL;
1730 req = tevent_req_create(mem_ctx, &state,
1731 struct vfswrap_get_dos_attributes_state);
1736 *state = (struct vfswrap_get_dos_attributes_state) {
1737 .conn = dir_fsp->conn,
1741 .smb_fname = smb_fname,
1744 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1748 SAMBA_XATTR_DOS_ATTRIB,
1750 if (tevent_req_nomem(subreq, req)) {
1751 return tevent_req_post(req, ev);
1753 tevent_req_set_callback(subreq,
1754 vfswrap_get_dos_attributes_getxattr_done,
1760 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq)
1762 struct tevent_req *req =
1763 tevent_req_callback_data(subreq,
1765 struct vfswrap_get_dos_attributes_state *state =
1766 tevent_req_data(req,
1767 struct vfswrap_get_dos_attributes_state);
1769 DATA_BLOB blob = {0};
1771 char *tofree = NULL;
1772 char pathbuf[PATH_MAX+1];
1774 struct smb_filename smb_fname;
1778 xattr_size = SMB_VFS_GETXATTRAT_RECV(subreq,
1782 TALLOC_FREE(subreq);
1783 if (xattr_size == -1) {
1784 status = map_nt_error_from_unix(state->aio_state.error);
1786 if (state->as_root) {
1787 tevent_req_nterror(req, status);
1790 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1791 tevent_req_nterror(req, status);
1795 state->as_root = true;
1798 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1802 SAMBA_XATTR_DOS_ATTRIB,
1805 if (tevent_req_nomem(subreq, req)) {
1808 tevent_req_set_callback(subreq,
1809 vfswrap_get_dos_attributes_getxattr_done,
1814 blob.length = xattr_size;
1816 status = parse_dos_attribute_blob(state->smb_fname,
1819 if (!NT_STATUS_IS_OK(status)) {
1820 tevent_req_nterror(req, status);
1824 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
1825 state->smb_fname->base_name,
1830 if (pathlen == -1) {
1831 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1835 smb_fname = (struct smb_filename) {
1837 .st = state->smb_fname->st,
1838 .flags = state->smb_fname->flags,
1839 .twrp = state->smb_fname->twrp,
1842 offline = vfswrap_is_offline(state->conn, &smb_fname);
1844 state->dosmode |= FILE_ATTRIBUTE_OFFLINE;
1846 TALLOC_FREE(tofree);
1848 tevent_req_done(req);
1852 static NTSTATUS vfswrap_get_dos_attributes_recv(struct tevent_req *req,
1853 struct vfs_aio_state *aio_state,
1856 struct vfswrap_get_dos_attributes_state *state =
1857 tevent_req_data(req,
1858 struct vfswrap_get_dos_attributes_state);
1861 if (tevent_req_is_nterror(req, &status)) {
1862 tevent_req_received(req);
1866 *aio_state = state->aio_state;
1867 *dosmode = state->dosmode;
1868 tevent_req_received(req);
1869 return NT_STATUS_OK;
1872 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1873 struct files_struct *fsp,
1878 offline = vfswrap_is_offline(handle->conn, fsp->fsp_name);
1880 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1883 return fget_ea_dos_attribute(fsp, dosmode);
1886 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1887 const struct smb_filename *smb_fname,
1890 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1893 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1894 struct files_struct *fsp,
1897 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1900 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1902 struct vfswrap_offload_read_state {
1906 static struct tevent_req *vfswrap_offload_read_send(
1907 TALLOC_CTX *mem_ctx,
1908 struct tevent_context *ev,
1909 struct vfs_handle_struct *handle,
1910 struct files_struct *fsp,
1916 struct tevent_req *req = NULL;
1917 struct vfswrap_offload_read_state *state = NULL;
1920 req = tevent_req_create(mem_ctx, &state,
1921 struct vfswrap_offload_read_state);
1926 status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1927 &vfswrap_offload_ctx);
1928 if (tevent_req_nterror(req, status)) {
1929 return tevent_req_post(req, ev);
1932 if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1933 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1934 return tevent_req_post(req, ev);
1937 status = vfs_offload_token_create_blob(state, fsp, fsctl,
1939 if (tevent_req_nterror(req, status)) {
1940 return tevent_req_post(req, ev);
1943 status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1945 if (tevent_req_nterror(req, status)) {
1946 return tevent_req_post(req, ev);
1949 tevent_req_done(req);
1950 return tevent_req_post(req, ev);
1953 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
1954 struct vfs_handle_struct *handle,
1955 TALLOC_CTX *mem_ctx,
1958 struct vfswrap_offload_read_state *state = tevent_req_data(
1959 req, struct vfswrap_offload_read_state);
1962 if (tevent_req_is_nterror(req, &status)) {
1963 tevent_req_received(req);
1967 token->length = state->token.length;
1968 token->data = talloc_move(mem_ctx, &state->token.data);
1970 tevent_req_received(req);
1971 return NT_STATUS_OK;
1974 struct vfswrap_offload_write_state {
1976 bool read_lck_locked;
1977 bool write_lck_locked;
1979 struct tevent_context *src_ev;
1980 struct files_struct *src_fsp;
1982 struct tevent_context *dst_ev;
1983 struct files_struct *dst_fsp;
1987 size_t next_io_size;
1990 static void vfswrap_offload_write_cleanup(struct tevent_req *req,
1991 enum tevent_req_state req_state)
1993 struct vfswrap_offload_write_state *state = tevent_req_data(
1994 req, struct vfswrap_offload_write_state);
1997 if (state->dst_fsp == NULL) {
2001 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2003 state->dst_fsp = NULL;
2006 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
2008 static struct tevent_req *vfswrap_offload_write_send(
2009 struct vfs_handle_struct *handle,
2010 TALLOC_CTX *mem_ctx,
2011 struct tevent_context *ev,
2014 off_t transfer_offset,
2015 struct files_struct *dest_fsp,
2019 struct tevent_req *req;
2020 struct vfswrap_offload_write_state *state = NULL;
2021 /* off_t is signed! */
2022 off_t max_offset = INT64_MAX - to_copy;
2023 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
2024 files_struct *src_fsp = NULL;
2028 req = tevent_req_create(mem_ctx, &state,
2029 struct vfswrap_offload_write_state);
2034 *state = (struct vfswrap_offload_write_state) {
2036 .src_off = transfer_offset,
2038 .dst_fsp = dest_fsp,
2039 .dst_off = dest_off,
2041 .remaining = to_copy,
2044 tevent_req_set_cleanup_fn(req, vfswrap_offload_write_cleanup);
2047 case FSCTL_SRV_COPYCHUNK:
2048 case FSCTL_SRV_COPYCHUNK_WRITE:
2051 case FSCTL_OFFLOAD_WRITE:
2052 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
2053 return tevent_req_post(req, ev);
2055 case FSCTL_DUP_EXTENTS_TO_FILE:
2056 DBG_DEBUG("COW clones not supported by vfs_default\n");
2057 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2058 return tevent_req_post(req, ev);
2061 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2062 return tevent_req_post(req, ev);
2066 * From here on we assume a copy-chunk fsctl
2070 tevent_req_done(req);
2071 return tevent_req_post(req, ev);
2074 if (state->src_off > max_offset) {
2076 * Protect integer checks below.
2078 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2079 return tevent_req_post(req, ev);
2081 if (state->src_off < 0) {
2083 * Protect integer checks below.
2085 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2086 return tevent_req_post(req, ev);
2088 if (state->dst_off > max_offset) {
2090 * Protect integer checks below.
2092 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2093 return tevent_req_post(req, ev);
2095 if (state->dst_off < 0) {
2097 * Protect integer checks below.
2099 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2100 return tevent_req_post(req, ev);
2103 status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
2105 if (tevent_req_nterror(req, status)) {
2106 return tevent_req_post(req, ev);
2109 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
2111 status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
2112 if (!NT_STATUS_IS_OK(status)) {
2113 tevent_req_nterror(req, status);
2114 return tevent_req_post(req, ev);
2117 ok = change_to_user_and_service_by_fsp(src_fsp);
2119 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2120 return tevent_req_post(req, ev);
2123 state->src_ev = src_fsp->conn->sconn->ev_ctx;
2124 state->src_fsp = src_fsp;
2126 status = vfs_stat_fsp(src_fsp);
2127 if (tevent_req_nterror(req, status)) {
2128 return tevent_req_post(req, ev);
2131 if (src_fsp->fsp_name->st.st_ex_size < state->src_off + to_copy) {
2133 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
2134 * If the SourceOffset or SourceOffset + Length extends beyond
2135 * the end of file, the server SHOULD<240> treat this as a
2136 * STATUS_END_OF_FILE error.
2138 * <240> Section 3.3.5.15.6: Windows servers will return
2139 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
2141 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
2142 return tevent_req_post(req, ev);
2145 state->buf = talloc_array(state, uint8_t, num);
2146 if (tevent_req_nomem(state->buf, req)) {
2147 return tevent_req_post(req, ev);
2150 status = vfswrap_offload_write_loop(req);
2151 if (!NT_STATUS_IS_OK(status)) {
2152 tevent_req_nterror(req, status);
2153 return tevent_req_post(req, ev);
2159 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
2161 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
2163 struct vfswrap_offload_write_state *state = tevent_req_data(
2164 req, struct vfswrap_offload_write_state);
2165 struct tevent_req *subreq = NULL;
2166 struct lock_struct read_lck;
2170 * This is called under the context of state->src_fsp.
2173 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
2175 init_strict_lock_struct(state->src_fsp,
2176 state->src_fsp->op->global->open_persistent_id,
2178 state->next_io_size,
2182 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
2186 return NT_STATUS_FILE_LOCK_CONFLICT;
2189 subreq = SMB_VFS_PREAD_SEND(state,
2193 state->next_io_size,
2195 if (subreq == NULL) {
2196 return NT_STATUS_NO_MEMORY;
2198 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
2200 return NT_STATUS_OK;
2203 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
2205 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
2207 struct tevent_req *req = tevent_req_callback_data(
2208 subreq, struct tevent_req);
2209 struct vfswrap_offload_write_state *state = tevent_req_data(
2210 req, struct vfswrap_offload_write_state);
2211 struct vfs_aio_state aio_state;
2212 struct lock_struct write_lck;
2216 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
2217 TALLOC_FREE(subreq);
2219 DBG_ERR("read failed: %s\n", strerror(aio_state.error));
2220 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2223 if (nread != state->next_io_size) {
2224 DBG_ERR("Short read, only %zd of %zu\n",
2225 nread, state->next_io_size);
2226 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2230 state->src_off += nread;
2232 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2234 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2238 init_strict_lock_struct(state->dst_fsp,
2239 state->dst_fsp->op->global->open_persistent_id,
2241 state->next_io_size,
2245 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
2249 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
2253 subreq = SMB_VFS_PWRITE_SEND(state,
2257 state->next_io_size,
2259 if (subreq == NULL) {
2260 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2263 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
2266 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
2268 struct tevent_req *req = tevent_req_callback_data(
2269 subreq, struct tevent_req);
2270 struct vfswrap_offload_write_state *state = tevent_req_data(
2271 req, struct vfswrap_offload_write_state);
2272 struct vfs_aio_state aio_state;
2277 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
2278 TALLOC_FREE(subreq);
2279 if (nwritten == -1) {
2280 DBG_ERR("write failed: %s\n", strerror(aio_state.error));
2281 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2284 if (nwritten != state->next_io_size) {
2285 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
2286 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2290 state->dst_off += nwritten;
2292 if (state->remaining < nwritten) {
2293 /* Paranoia check */
2294 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2297 state->remaining -= nwritten;
2298 if (state->remaining == 0) {
2299 tevent_req_done(req);
2303 ok = change_to_user_and_service_by_fsp(state->src_fsp);
2305 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2309 status = vfswrap_offload_write_loop(req);
2310 if (!NT_STATUS_IS_OK(status)) {
2311 tevent_req_nterror(req, status);
2318 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
2319 struct tevent_req *req,
2322 struct vfswrap_offload_write_state *state = tevent_req_data(
2323 req, struct vfswrap_offload_write_state);
2326 if (tevent_req_is_nterror(req, &status)) {
2327 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
2329 tevent_req_received(req);
2333 *copied = state->to_copy;
2334 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
2335 tevent_req_received(req);
2337 return NT_STATUS_OK;
2340 static NTSTATUS vfswrap_fget_compression(struct vfs_handle_struct *handle,
2341 TALLOC_CTX *mem_ctx,
2342 struct files_struct *fsp,
2343 uint16_t *_compression_fmt)
2345 return NT_STATUS_INVALID_DEVICE_REQUEST;
2348 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
2349 TALLOC_CTX *mem_ctx,
2350 struct files_struct *fsp,
2351 uint16_t compression_fmt)
2353 return NT_STATUS_INVALID_DEVICE_REQUEST;
2356 /********************************************************************
2357 Given a stat buffer return the allocated size on disk, taking into
2358 account sparse files.
2359 ********************************************************************/
2360 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
2361 struct files_struct *fsp,
2362 const SMB_STRUCT_STAT *sbuf)
2366 START_PROFILE(syscall_get_alloc_size);
2368 if(S_ISDIR(sbuf->st_ex_mode)) {
2373 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2374 /* The type of st_blocksize is blkcnt_t which *MUST* be
2375 signed (according to POSIX) and can be less than 64-bits.
2376 Ensure when we're converting to 64 bits wide we don't
2378 #if defined(SIZEOF_BLKCNT_T_8)
2379 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2380 #elif defined(SIZEOF_BLKCNT_T_4)
2382 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2383 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2386 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2390 * Some file systems do not allocate a block for very
2391 * small files. But for non-empty file should report a
2395 uint64_t filesize = get_file_size_stat(sbuf);
2397 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2401 result = get_file_size_stat(sbuf);
2404 if (fsp && fsp->initial_allocation_size)
2405 result = MAX(result,fsp->initial_allocation_size);
2407 result = smb_roundup(handle->conn, result);
2410 END_PROFILE(syscall_get_alloc_size);
2414 static int vfswrap_unlinkat(vfs_handle_struct *handle,
2415 struct files_struct *dirfsp,
2416 const struct smb_filename *smb_fname,
2421 START_PROFILE(syscall_unlinkat);
2423 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2425 if (is_named_stream(smb_fname)) {
2429 result = unlinkat(fsp_get_pathref_fd(dirfsp),
2430 smb_fname->base_name,
2434 END_PROFILE(syscall_unlinkat);
2438 static int vfswrap_chmod(vfs_handle_struct *handle,
2439 const struct smb_filename *smb_fname,
2444 START_PROFILE(syscall_chmod);
2445 result = chmod(smb_fname->base_name, mode);
2446 END_PROFILE(syscall_chmod);
2450 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2454 START_PROFILE(syscall_fchmod);
2455 #if defined(HAVE_FCHMOD)
2456 result = fchmod(fsp_get_io_fd(fsp), mode);
2462 END_PROFILE(syscall_fchmod);
2466 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2471 START_PROFILE(syscall_fchown);
2472 result = fchown(fsp_get_io_fd(fsp), uid, gid);
2473 END_PROFILE(syscall_fchown);
2481 static int vfswrap_lchown(vfs_handle_struct *handle,
2482 const struct smb_filename *smb_fname,
2488 START_PROFILE(syscall_lchown);
2489 result = lchown(smb_fname->base_name, uid, gid);
2490 END_PROFILE(syscall_lchown);
2494 static int vfswrap_chdir(vfs_handle_struct *handle,
2495 const struct smb_filename *smb_fname)
2499 START_PROFILE(syscall_chdir);
2500 result = chdir(smb_fname->base_name);
2501 END_PROFILE(syscall_chdir);
2505 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2509 struct smb_filename *smb_fname = NULL;
2511 START_PROFILE(syscall_getwd);
2512 result = sys_getwd();
2513 END_PROFILE(syscall_getwd);
2515 if (result == NULL) {
2518 smb_fname = synthetic_smb_fname(ctx,
2525 * sys_getwd() *always* returns malloced memory.
2526 * We must free here to avoid leaks:
2527 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2533 /*********************************************************************
2534 nsec timestamp resolution call. Convert down to whatever the underlying
2535 system will support.
2536 **********************************************************************/
2538 static int vfswrap_ntimes(vfs_handle_struct *handle,
2539 const struct smb_filename *smb_fname,
2540 struct smb_file_time *ft)
2544 START_PROFILE(syscall_ntimes);
2546 if (is_named_stream(smb_fname)) {
2552 if (is_omit_timespec(&ft->atime)) {
2553 ft->atime= smb_fname->st.st_ex_atime;
2556 if (is_omit_timespec(&ft->mtime)) {
2557 ft->mtime = smb_fname->st.st_ex_mtime;
2560 if (!is_omit_timespec(&ft->create_time)) {
2561 set_create_timespec_ea(handle->conn,
2566 if ((timespec_compare(&ft->atime,
2567 &smb_fname->st.st_ex_atime) == 0) &&
2568 (timespec_compare(&ft->mtime,
2569 &smb_fname->st.st_ex_mtime) == 0)) {
2574 #if defined(HAVE_UTIMENSAT)
2576 struct timespec ts[2];
2579 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2581 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2583 if (!((result == -1) && (errno == ENOSYS))) {
2587 #if defined(HAVE_UTIMES)
2589 struct timeval tv[2];
2590 tv[0] = convert_timespec_to_timeval(ft->atime);
2591 tv[1] = convert_timespec_to_timeval(ft->mtime);
2592 result = utimes(smb_fname->base_name, tv);
2594 result = utimes(smb_fname->base_name, NULL);
2596 if (!((result == -1) && (errno == ENOSYS))) {
2600 #if defined(HAVE_UTIME)
2602 struct utimbuf times;
2603 times.actime = convert_timespec_to_time_t(ft->atime);
2604 times.modtime = convert_timespec_to_time_t(ft->mtime);
2605 result = utime(smb_fname->base_name, ×);
2607 result = utime(smb_fname->base_name, NULL);
2609 if (!((result == -1) && (errno == ENOSYS))) {
2617 END_PROFILE(syscall_ntimes);
2621 /*********************************************************************
2622 A version of ftruncate that will write the space on disk if strict
2624 **********************************************************************/
2626 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2628 off_t space_to_write;
2629 uint64_t space_avail;
2630 uint64_t bsize,dfree,dsize;
2633 SMB_STRUCT_STAT *pst;
2636 ok = vfs_valid_pwrite_range(len, 0);
2642 status = vfs_stat_fsp(fsp);
2643 if (!NT_STATUS_IS_OK(status)) {
2646 pst = &fsp->fsp_name->st;
2649 if (S_ISFIFO(pst->st_ex_mode))
2653 if (pst->st_ex_size == len)
2656 /* Shrink - just ftruncate. */
2657 if (pst->st_ex_size > len)
2658 return ftruncate(fsp_get_io_fd(fsp), len);
2660 space_to_write = len - pst->st_ex_size;
2662 /* for allocation try fallocate first. This can fail on some
2663 platforms e.g. when the filesystem doesn't support it and no
2664 emulation is being done by the libc (like on AIX with JFS1). In that
2665 case we do our own emulation. fallocate implementations can
2666 return ENOTSUP or EINVAL in cases like that. */
2667 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2668 if (ret == -1 && errno == ENOSPC) {
2674 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2675 "error %d. Falling back to slow manual allocation\n", errno));
2677 /* available disk space is enough or not? */
2679 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2680 /* space_avail is 1k blocks */
2681 if (space_avail == (uint64_t)-1 ||
2682 ((uint64_t)space_to_write/1024 > space_avail) ) {
2687 /* Write out the real space on disk. */
2688 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2696 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2699 SMB_STRUCT_STAT *pst;
2703 START_PROFILE(syscall_ftruncate);
2705 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->fsp_flags.is_sparse) {
2706 result = strict_allocate_ftruncate(handle, fsp, len);
2707 END_PROFILE(syscall_ftruncate);
2711 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2712 ftruncate if the system supports it. Then I discovered that
2713 you can have some filesystems that support ftruncate
2714 expansion and some that don't! On Linux fat can't do
2715 ftruncate extend but ext2 can. */
2717 result = ftruncate(fsp_get_io_fd(fsp), len);
2719 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2720 extend a file with ftruncate. Provide alternate implementation
2723 /* Do an fstat to see if the file is longer than the requested
2724 size in which case the ftruncate above should have
2725 succeeded or shorter, in which case seek to len - 1 and
2726 write 1 byte of zero */
2727 status = vfs_stat_fsp(fsp);
2728 if (!NT_STATUS_IS_OK(status)) {
2732 /* We need to update the files_struct after successful ftruncate */
2737 pst = &fsp->fsp_name->st;
2740 if (S_ISFIFO(pst->st_ex_mode)) {
2746 if (pst->st_ex_size == len) {
2751 if (pst->st_ex_size > len) {
2752 /* the ftruncate should have worked */
2756 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2764 END_PROFILE(syscall_ftruncate);
2768 static int vfswrap_fallocate(vfs_handle_struct *handle,
2776 START_PROFILE(syscall_fallocate);
2778 result = sys_posix_fallocate(fsp_get_io_fd(fsp), offset, len);
2780 * posix_fallocate returns 0 on success, errno on error
2781 * and doesn't set errno. Make it behave like fallocate()
2782 * which returns -1, and sets errno on failure.
2789 /* sys_fallocate handles filtering of unsupported mode flags */
2790 result = sys_fallocate(fsp_get_io_fd(fsp), mode, offset, len);
2792 END_PROFILE(syscall_fallocate);
2796 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2800 START_PROFILE(syscall_fcntl_lock);
2802 if (fsp->fsp_flags.use_ofd_locks) {
2803 op = map_process_lock_to_ofd_lock(op);
2806 result = fcntl_lock(fsp_get_io_fd(fsp), op, offset, count, type);
2807 END_PROFILE(syscall_fcntl_lock);
2811 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2812 uint32_t share_access, uint32_t access_mask)
2814 START_PROFILE(syscall_kernel_flock);
2815 kernel_flock(fsp_get_io_fd(fsp), share_access, access_mask);
2816 END_PROFILE(syscall_kernel_flock);
2820 static int vfswrap_fcntl(vfs_handle_struct *handle, files_struct *fsp, int cmd,
2824 va_list dup_cmd_arg;
2828 START_PROFILE(syscall_fcntl);
2830 va_copy(dup_cmd_arg, cmd_arg);
2836 #if defined(HAVE_OFD_LOCKS)
2841 #if defined(HAVE_F_OWNER_EX)
2845 #if defined(HAVE_RW_HINTS)
2848 case F_GET_FILE_RW_HINT:
2849 case F_SET_FILE_RW_HINT:
2851 argp = va_arg(dup_cmd_arg, void *);
2852 result = sys_fcntl_ptr(fsp_get_io_fd(fsp), cmd, argp);
2855 val = va_arg(dup_cmd_arg, int);
2856 result = sys_fcntl_int(fsp_get_io_fd(fsp), cmd, val);
2859 va_end(dup_cmd_arg);
2861 END_PROFILE(syscall_fcntl);
2865 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2870 START_PROFILE(syscall_fcntl_getlock);
2872 if (fsp->fsp_flags.use_ofd_locks) {
2873 op = map_process_lock_to_ofd_lock(op);
2876 result = fcntl_getlock(fsp_get_io_fd(fsp), op, poffset, pcount, ptype, ppid);
2877 END_PROFILE(syscall_fcntl_getlock);
2881 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2886 START_PROFILE(syscall_linux_setlease);
2888 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2889 result = linux_setlease(fsp_get_io_fd(fsp), leasetype);
2893 END_PROFILE(syscall_linux_setlease);
2897 static int vfswrap_symlinkat(vfs_handle_struct *handle,
2898 const struct smb_filename *link_target,
2899 struct files_struct *dirfsp,
2900 const struct smb_filename *new_smb_fname)
2904 START_PROFILE(syscall_symlinkat);
2906 result = symlinkat(link_target->base_name,
2907 fsp_get_pathref_fd(dirfsp),
2908 new_smb_fname->base_name);
2909 END_PROFILE(syscall_symlinkat);
2913 static int vfswrap_readlinkat(vfs_handle_struct *handle,
2914 const struct files_struct *dirfsp,
2915 const struct smb_filename *smb_fname,
2921 START_PROFILE(syscall_readlinkat);
2923 result = readlinkat(fsp_get_pathref_fd(dirfsp),
2924 smb_fname->base_name,
2928 END_PROFILE(syscall_readlinkat);
2932 static int vfswrap_linkat(vfs_handle_struct *handle,
2933 files_struct *srcfsp,
2934 const struct smb_filename *old_smb_fname,
2935 files_struct *dstfsp,
2936 const struct smb_filename *new_smb_fname,
2941 START_PROFILE(syscall_linkat);
2943 result = linkat(fsp_get_pathref_fd(srcfsp),
2944 old_smb_fname->base_name,
2945 fsp_get_pathref_fd(dstfsp),
2946 new_smb_fname->base_name,
2949 END_PROFILE(syscall_linkat);
2953 static int vfswrap_mknodat(vfs_handle_struct *handle,
2954 files_struct *dirfsp,
2955 const struct smb_filename *smb_fname,
2961 START_PROFILE(syscall_mknodat);
2963 result = sys_mknodat(fsp_get_pathref_fd(dirfsp),
2964 smb_fname->base_name,
2968 END_PROFILE(syscall_mknodat);
2972 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2974 const struct smb_filename *smb_fname)
2977 struct smb_filename *result_fname = NULL;
2979 START_PROFILE(syscall_realpath);
2980 result = sys_realpath(smb_fname->base_name);
2981 END_PROFILE(syscall_realpath);
2983 result_fname = synthetic_smb_fname(ctx,
2991 return result_fname;
2994 static int vfswrap_chflags(vfs_handle_struct *handle,
2995 const struct smb_filename *smb_fname,
2999 return chflags(smb_fname->base_name, flags);
3006 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
3007 const SMB_STRUCT_STAT *sbuf)
3011 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
3015 key.devid = sbuf->st_ex_dev;
3016 key.inode = sbuf->st_ex_ino;
3017 /* key.extid is unused by default. */
3022 static uint64_t vfswrap_fs_file_id(struct vfs_handle_struct *handle,
3023 const SMB_STRUCT_STAT *psbuf)
3027 if (!(psbuf->st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)) {
3028 return psbuf->st_ex_file_id;
3031 if (handle->conn->base_share_dev == psbuf->st_ex_dev) {
3032 return (uint64_t)psbuf->st_ex_ino;
3036 file_id = ((psbuf->st_ex_ino) & UINT32_MAX);
3039 file_id |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32;
3044 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
3045 struct files_struct *fsp,
3046 const struct smb_filename *smb_fname,
3047 TALLOC_CTX *mem_ctx,
3048 unsigned int *pnum_streams,
3049 struct stream_struct **pstreams)
3051 SMB_STRUCT_STAT sbuf;
3052 struct stream_struct *tmp_streams = NULL;
3055 if ((fsp != NULL) && (fsp->fsp_flags.is_directory)) {
3057 * No default streams on directories
3062 if ((fsp != NULL) && (fsp_get_pathref_fd(fsp) != -1)) {
3063 ret = SMB_VFS_FSTAT(fsp, &sbuf);
3066 struct smb_filename *smb_fname_cp = NULL;
3068 smb_fname_cp = cp_smb_filename_nostream(talloc_tos(), smb_fname);
3069 if (smb_fname_cp == NULL) {
3070 return NT_STATUS_NO_MEMORY;
3073 ret = vfs_stat(handle->conn, smb_fname_cp);
3074 sbuf = smb_fname_cp->st;
3075 TALLOC_FREE(smb_fname_cp);
3079 return map_nt_error_from_unix(errno);
3082 if (S_ISDIR(sbuf.st_ex_mode)) {
3086 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
3087 (*pnum_streams) + 1);
3088 if (tmp_streams == NULL) {
3089 return NT_STATUS_NO_MEMORY;
3091 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
3092 if (tmp_streams[*pnum_streams].name == NULL) {
3093 return NT_STATUS_NO_MEMORY;
3095 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
3096 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
3099 *pstreams = tmp_streams;
3101 return NT_STATUS_OK;
3104 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
3105 const struct smb_filename *path,
3107 TALLOC_CTX *mem_ctx,
3111 * Don't fall back to get_real_filename so callers can differentiate
3112 * between a full directory scan and an actual case-insensitive stat.
3118 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
3119 const struct smb_filename *smb_fname)
3121 return handle->conn->connectpath;
3124 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
3125 struct byte_range_lock *br_lck,
3126 struct lock_struct *plock)
3128 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3130 /* Note: blr is not used in the default implementation. */
3131 return brl_lock_windows_default(br_lck, plock);
3134 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
3135 struct byte_range_lock *br_lck,
3136 const struct lock_struct *plock)
3138 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3140 return brl_unlock_windows_default(br_lck, plock);
3143 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
3145 struct lock_struct *plock)
3147 SMB_ASSERT(plock->lock_type == READ_LOCK ||
3148 plock->lock_type == WRITE_LOCK);
3150 return strict_lock_check_default(fsp, plock);
3153 /* NT ACL operations. */
3155 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
3157 uint32_t security_info,
3158 TALLOC_CTX *mem_ctx,
3159 struct security_descriptor **ppdesc)
3163 START_PROFILE(fget_nt_acl);
3164 result = posix_fget_nt_acl(fsp, security_info,
3166 END_PROFILE(fget_nt_acl);
3170 static NTSTATUS vfswrap_get_nt_acl_at(vfs_handle_struct *handle,
3171 struct files_struct *dirfsp,
3172 const struct smb_filename *smb_fname,
3173 uint32_t security_info,
3174 TALLOC_CTX *mem_ctx,
3175 struct security_descriptor **ppdesc)
3179 START_PROFILE(get_nt_acl_at);
3181 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
3183 result = posix_get_nt_acl(handle->conn,
3188 END_PROFILE(get_nt_acl_at);
3192 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
3196 START_PROFILE(fset_nt_acl);
3197 result = set_nt_acl(fsp, security_info_sent, psd);
3198 END_PROFILE(fset_nt_acl);
3202 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
3203 struct smb_filename *file,
3204 struct security_acl *sacl,
3205 uint32_t access_requested,
3206 uint32_t access_denied)
3208 return NT_STATUS_OK; /* Nothing to do here ... */
3211 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
3212 const struct smb_filename *smb_fname,
3213 SMB_ACL_TYPE_T type,
3214 TALLOC_CTX *mem_ctx)
3216 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
3219 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
3221 TALLOC_CTX *mem_ctx)
3223 return sys_acl_get_fd(handle, fsp, mem_ctx);
3226 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
3227 const struct smb_filename *smb_fname,
3228 SMB_ACL_TYPE_T acltype,
3231 return sys_acl_set_file(handle, smb_fname, acltype, theacl);
3234 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle,
3236 SMB_ACL_TYPE_T type,
3239 if (!fsp->fsp_flags.is_pathref &&
3240 type == SMB_ACL_TYPE_ACCESS)
3242 return sys_acl_set_fd(handle, fsp, theacl);
3245 if (fsp->fsp_flags.have_proc_fds) {
3246 int fd = fsp_get_pathref_fd(fsp);
3247 struct smb_filename smb_fname;
3248 const char *p = NULL;
3251 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3256 smb_fname = (struct smb_filename) {
3260 return sys_acl_set_file(handle,
3267 * This is no longer a handle based call.
3269 return sys_acl_set_file(handle,
3275 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
3276 const struct smb_filename *smb_fname)
3278 return sys_acl_delete_def_file(handle, smb_fname);
3281 /****************************************************************
3282 Extended attribute operations.
3283 *****************************************************************/
3285 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
3286 const struct smb_filename *smb_fname,
3291 return getxattr(smb_fname->base_name, name, value, size);
3294 struct vfswrap_getxattrat_state {
3295 struct tevent_context *ev;
3296 files_struct *dir_fsp;
3297 const struct smb_filename *smb_fname;
3300 * The following variables are talloced off "state" which is protected
3301 * by a destructor and thus are guaranteed to be safe to be used in the
3302 * job function in the worker thread.
3305 const char *xattr_name;
3306 uint8_t *xattr_value;
3307 struct security_unix_token *token;
3310 struct vfs_aio_state vfs_aio_state;
3311 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
3314 static int vfswrap_getxattrat_state_destructor(
3315 struct vfswrap_getxattrat_state *state)
3320 static void vfswrap_getxattrat_do_sync(struct tevent_req *req);
3321 static void vfswrap_getxattrat_do_async(void *private_data);
3322 static void vfswrap_getxattrat_done(struct tevent_req *subreq);
3324 static struct tevent_req *vfswrap_getxattrat_send(
3325 TALLOC_CTX *mem_ctx,
3326 struct tevent_context *ev,
3327 struct vfs_handle_struct *handle,
3328 files_struct *dir_fsp,
3329 const struct smb_filename *smb_fname,
3330 const char *xattr_name,
3333 struct tevent_req *req = NULL;
3334 struct tevent_req *subreq = NULL;
3335 struct vfswrap_getxattrat_state *state = NULL;
3336 size_t max_threads = 0;
3337 bool have_per_thread_cwd = false;
3338 bool have_per_thread_creds = false;
3339 bool do_async = false;
3341 req = tevent_req_create(mem_ctx, &state,
3342 struct vfswrap_getxattrat_state);
3346 *state = (struct vfswrap_getxattrat_state) {
3349 .smb_fname = smb_fname,
3352 max_threads = pthreadpool_tevent_max_threads(dir_fsp->conn->sconn->pool);
3353 if (max_threads >= 1) {
3355 * We need a non sync threadpool!
3357 have_per_thread_cwd = per_thread_cwd_supported();
3359 #ifdef HAVE_LINUX_THREAD_CREDENTIALS
3360 have_per_thread_creds = true;
3362 if (have_per_thread_cwd && have_per_thread_creds) {
3366 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat, profile_p,
3367 state->profile_bytes, 0);
3369 if (fsp_get_pathref_fd(dir_fsp) == -1) {
3370 DBG_ERR("Need a valid directory fd\n");
3371 tevent_req_error(req, EINVAL);
3372 return tevent_req_post(req, ev);
3375 if (alloc_hint > 0) {
3376 state->xattr_value = talloc_zero_array(state,
3379 if (tevent_req_nomem(state->xattr_value, req)) {
3380 return tevent_req_post(req, ev);
3385 vfswrap_getxattrat_do_sync(req);
3386 return tevent_req_post(req, ev);
3390 * Now allocate all parameters from a memory context that won't go away
3391 * no matter what. These paremeters will get used in threads and we
3392 * can't reliably cancel threads, so all buffers passed to the threads
3393 * must not be freed before all referencing threads terminate.
3396 state->name = talloc_strdup(state, smb_fname->base_name);
3397 if (tevent_req_nomem(state->name, req)) {
3398 return tevent_req_post(req, ev);
3401 state->xattr_name = talloc_strdup(state, xattr_name);
3402 if (tevent_req_nomem(state->xattr_name, req)) {
3403 return tevent_req_post(req, ev);
3407 * This is a hot codepath so at first glance one might think we should
3408 * somehow optimize away the token allocation and do a
3409 * talloc_reference() or similar black magic instead. But due to the
3410 * talloc_stackframe pool per SMB2 request this should be a simple copy
3411 * without a malloc in most cases.
3413 if (geteuid() == sec_initial_uid()) {
3414 state->token = root_unix_token(state);
3416 state->token = copy_unix_token(
3418 dir_fsp->conn->session_info->unix_token);
3420 if (tevent_req_nomem(state->token, req)) {
3421 return tevent_req_post(req, ev);
3424 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3426 subreq = pthreadpool_tevent_job_send(
3429 dir_fsp->conn->sconn->pool,
3430 vfswrap_getxattrat_do_async,
3432 if (tevent_req_nomem(subreq, req)) {
3433 return tevent_req_post(req, ev);
3435 tevent_req_set_callback(subreq, vfswrap_getxattrat_done, req);
3437 talloc_set_destructor(state, vfswrap_getxattrat_state_destructor);
3442 static void vfswrap_getxattrat_do_sync(struct tevent_req *req)
3444 struct vfswrap_getxattrat_state *state = tevent_req_data(
3445 req, struct vfswrap_getxattrat_state);
3447 char *tofree = NULL;
3448 char pathbuf[PATH_MAX+1];
3452 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
3453 state->smb_fname->base_name,
3458 if (pathlen == -1) {
3459 tevent_req_error(req, ENOMEM);
3463 state->xattr_size = getxattr(path,
3466 talloc_array_length(state->xattr_value));
3468 TALLOC_FREE(tofree);
3469 if (state->xattr_size == -1) {
3470 tevent_req_error(req, err);
3474 tevent_req_done(req);
3478 static void vfswrap_getxattrat_do_async(void *private_data)
3480 struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3481 private_data, struct vfswrap_getxattrat_state);
3482 struct timespec start_time;
3483 struct timespec end_time;
3486 PROFILE_TIMESTAMP(&start_time);
3487 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
3490 * Here we simulate a getxattrat()
3491 * call using fchdir();getxattr()
3494 per_thread_cwd_activate();
3496 /* Become the correct credential on this thread. */
3497 ret = set_thread_credentials(state->token->uid,
3499 (size_t)state->token->ngroups,
3500 state->token->groups);
3502 state->xattr_size = -1;
3503 state->vfs_aio_state.error = errno;
3507 ret = fchdir(fsp_get_pathref_fd(state->dir_fsp));
3509 state->xattr_size = -1;
3510 state->vfs_aio_state.error = errno;
3514 state->xattr_size = getxattr(state->name,
3517 talloc_array_length(state->xattr_value));
3518 if (state->xattr_size == -1) {
3519 state->vfs_aio_state.error = errno;
3523 PROFILE_TIMESTAMP(&end_time);
3524 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
3525 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3528 static void vfswrap_getxattrat_done(struct tevent_req *subreq)
3530 struct tevent_req *req = tevent_req_callback_data(
3531 subreq, struct tevent_req);
3532 struct vfswrap_getxattrat_state *state = tevent_req_data(
3533 req, struct vfswrap_getxattrat_state);
3538 * Make sure we run as the user again
3540 ok = change_to_user_and_service_by_fsp(state->dir_fsp);
3543 ret = pthreadpool_tevent_job_recv(subreq);
3544 TALLOC_FREE(subreq);
3545 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
3546 talloc_set_destructor(state, NULL);
3548 if (ret != EAGAIN) {
3549 tevent_req_error(req, ret);
3553 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
3554 * means the lower level pthreadpool failed to create a new
3555 * thread. Fallback to sync processing in that case to allow
3556 * some progress for the client.
3558 vfswrap_getxattrat_do_sync(req);
3562 if (state->xattr_size == -1) {
3563 tevent_req_error(req, state->vfs_aio_state.error);
3567 if (state->xattr_value == NULL) {
3569 * The caller only wanted the size.
3571 tevent_req_done(req);
3576 * shrink the buffer to the returned size.
3577 * (can't fail). It means NULL if size is 0.
3579 state->xattr_value = talloc_realloc(state,
3584 tevent_req_done(req);
3587 static ssize_t vfswrap_getxattrat_recv(struct tevent_req *req,
3588 struct vfs_aio_state *aio_state,
3589 TALLOC_CTX *mem_ctx,
3590 uint8_t **xattr_value)
3592 struct vfswrap_getxattrat_state *state = tevent_req_data(
3593 req, struct vfswrap_getxattrat_state);
3596 if (tevent_req_is_unix_error(req, &aio_state->error)) {
3597 tevent_req_received(req);
3601 *aio_state = state->vfs_aio_state;
3602 xattr_size = state->xattr_size;
3603 if (xattr_value != NULL) {
3604 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
3607 tevent_req_received(req);
3611 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle,
3612 struct files_struct *fsp,
3617 int fd = fsp_get_pathref_fd(fsp);
3619 if (!fsp->fsp_flags.is_pathref) {
3620 return fgetxattr(fd, name, value, size);
3623 if (fsp->fsp_flags.have_proc_fds) {
3624 const char *p = NULL;
3627 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3632 return getxattr(p, name, value, size);
3636 * This is no longer a handle based call.
3638 return getxattr(fsp->fsp_name->base_name, name, value, size);
3641 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
3642 const struct smb_filename *smb_fname,
3646 return listxattr(smb_fname->base_name, list, size);
3649 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
3651 int fd = fsp_get_pathref_fd(fsp);
3653 if (!fsp->fsp_flags.is_pathref) {
3654 return flistxattr(fd, list, size);
3657 if (fsp->fsp_flags.have_proc_fds) {
3658 const char *p = NULL;
3661 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3666 return listxattr(p, list, size);
3670 * This is no longer a handle based call.
3672 return listxattr(fsp->fsp_name->base_name, list, size);
3675 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
3676 const struct smb_filename *smb_fname,
3679 return removexattr(smb_fname->base_name, name);
3682 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
3684 int fd = fsp_get_pathref_fd(fsp);
3686 if (!fsp->fsp_flags.is_pathref) {
3687 return fremovexattr(fd, name);
3690 if (fsp->fsp_flags.have_proc_fds) {
3691 const char *p = NULL;
3694 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3699 return removexattr(p, name);
3703 * This is no longer a handle based call.
3705 return removexattr(fsp->fsp_name->base_name, name);
3708 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
3709 const struct smb_filename *smb_fname,
3715 return setxattr(smb_fname->base_name, name, value, size, flags);
3718 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
3720 int fd = fsp_get_pathref_fd(fsp);
3722 if (!fsp->fsp_flags.is_pathref) {
3723 return fsetxattr(fd, name, value, size, flags);
3726 if (fsp->fsp_flags.have_proc_fds) {
3727 const char *p = NULL;
3730 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3735 return setxattr(p, name, value, size, flags);
3739 * This is no longer a handle based call.
3741 return setxattr(fsp->fsp_name->base_name, name, value, size, flags);
3744 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
3749 static bool vfswrap_is_offline(struct connection_struct *conn,
3750 const struct smb_filename *fname)
3754 bool offline = false;
3756 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
3760 if (!lp_dmapi_support(SNUM(conn)) || !dmapi_have_session()) {
3761 #if defined(ENOTSUP)
3767 status = get_full_smb_filename(talloc_tos(), fname, &path);
3768 if (!NT_STATUS_IS_OK(status)) {
3769 errno = map_errno_from_nt_status(status);
3773 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
3780 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
3781 struct files_struct *fsp,
3782 TALLOC_CTX *mem_ctx,
3785 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
3788 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
3789 struct files_struct *fsp,
3790 const DATA_BLOB old_cookie,
3791 TALLOC_CTX *mem_ctx,
3792 DATA_BLOB *new_cookie)
3794 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
3798 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
3799 struct smb_request *smb1req,
3800 struct smbXsrv_open *op,
3801 const DATA_BLOB old_cookie,
3802 TALLOC_CTX *mem_ctx,
3803 struct files_struct **fsp,
3804 DATA_BLOB *new_cookie)
3806 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
3807 old_cookie, mem_ctx,
3811 static struct vfs_fn_pointers vfs_default_fns = {
3812 /* Disk operations */
3814 .connect_fn = vfswrap_connect,
3815 .disconnect_fn = vfswrap_disconnect,
3816 .disk_free_fn = vfswrap_disk_free,
3817 .get_quota_fn = vfswrap_get_quota,
3818 .set_quota_fn = vfswrap_set_quota,
3819 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3820 .statvfs_fn = vfswrap_statvfs,
3821 .fs_capabilities_fn = vfswrap_fs_capabilities,
3822 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3823 .create_dfs_pathat_fn = vfswrap_create_dfs_pathat,
3824 .read_dfs_pathat_fn = vfswrap_read_dfs_pathat,
3825 .snap_check_path_fn = vfswrap_snap_check_path,
3826 .snap_create_fn = vfswrap_snap_create,
3827 .snap_delete_fn = vfswrap_snap_delete,
3829 /* Directory operations */
3831 .fdopendir_fn = vfswrap_fdopendir,
3832 .readdir_fn = vfswrap_readdir,
3833 .readdir_attr_fn = vfswrap_readdir_attr,
3834 .seekdir_fn = vfswrap_seekdir,
3835 .telldir_fn = vfswrap_telldir,
3836 .rewind_dir_fn = vfswrap_rewinddir,
3837 .mkdirat_fn = vfswrap_mkdirat,
3838 .closedir_fn = vfswrap_closedir,
3840 /* File operations */
3842 .openat_fn = vfswrap_openat,
3843 .create_file_fn = vfswrap_create_file,
3844 .close_fn = vfswrap_close,
3845 .pread_fn = vfswrap_pread,
3846 .pread_send_fn = vfswrap_pread_send,
3847 .pread_recv_fn = vfswrap_pread_recv,
3848 .pwrite_fn = vfswrap_pwrite,
3849 .pwrite_send_fn = vfswrap_pwrite_send,
3850 .pwrite_recv_fn = vfswrap_pwrite_recv,
3851 .lseek_fn = vfswrap_lseek,
3852 .sendfile_fn = vfswrap_sendfile,
3853 .recvfile_fn = vfswrap_recvfile,
3854 .renameat_fn = vfswrap_renameat,
3855 .fsync_send_fn = vfswrap_fsync_send,
3856 .fsync_recv_fn = vfswrap_fsync_recv,
3857 .stat_fn = vfswrap_stat,
3858 .fstat_fn = vfswrap_fstat,
3859 .lstat_fn = vfswrap_lstat,
3860 .get_alloc_size_fn = vfswrap_get_alloc_size,
3861 .unlinkat_fn = vfswrap_unlinkat,
3862 .chmod_fn = vfswrap_chmod,
3863 .fchmod_fn = vfswrap_fchmod,
3864 .fchown_fn = vfswrap_fchown,
3865 .lchown_fn = vfswrap_lchown,
3866 .chdir_fn = vfswrap_chdir,
3867 .getwd_fn = vfswrap_getwd,
3868 .ntimes_fn = vfswrap_ntimes,
3869 .ftruncate_fn = vfswrap_ftruncate,
3870 .fallocate_fn = vfswrap_fallocate,
3871 .lock_fn = vfswrap_lock,
3872 .kernel_flock_fn = vfswrap_kernel_flock,
3873 .fcntl_fn = vfswrap_fcntl,
3874 .linux_setlease_fn = vfswrap_linux_setlease,
3875 .getlock_fn = vfswrap_getlock,
3876 .symlinkat_fn = vfswrap_symlinkat,
3877 .readlinkat_fn = vfswrap_readlinkat,
3878 .linkat_fn = vfswrap_linkat,
3879 .mknodat_fn = vfswrap_mknodat,
3880 .realpath_fn = vfswrap_realpath,
3881 .chflags_fn = vfswrap_chflags,
3882 .file_id_create_fn = vfswrap_file_id_create,
3883 .fs_file_id_fn = vfswrap_fs_file_id,
3884 .streaminfo_fn = vfswrap_streaminfo,
3885 .get_real_filename_fn = vfswrap_get_real_filename,
3886 .connectpath_fn = vfswrap_connectpath,
3887 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
3888 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3889 .strict_lock_check_fn = vfswrap_strict_lock_check,
3890 .translate_name_fn = vfswrap_translate_name,
3891 .fsctl_fn = vfswrap_fsctl,
3892 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
3893 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
3894 .get_dos_attributes_send_fn = vfswrap_get_dos_attributes_send,
3895 .get_dos_attributes_recv_fn = vfswrap_get_dos_attributes_recv,
3896 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
3897 .offload_read_send_fn = vfswrap_offload_read_send,
3898 .offload_read_recv_fn = vfswrap_offload_read_recv,
3899 .offload_write_send_fn = vfswrap_offload_write_send,
3900 .offload_write_recv_fn = vfswrap_offload_write_recv,
3901 .fget_compression_fn = vfswrap_fget_compression,
3902 .set_compression_fn = vfswrap_set_compression,
3904 /* NT ACL operations. */
3906 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
3907 .get_nt_acl_at_fn = vfswrap_get_nt_acl_at,
3908 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
3909 .audit_file_fn = vfswrap_audit_file,
3911 /* POSIX ACL operations. */
3913 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
3914 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3915 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
3916 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3917 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
3918 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3919 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
3921 /* EA operations. */
3922 .getxattr_fn = vfswrap_getxattr,
3923 .getxattrat_send_fn = vfswrap_getxattrat_send,
3924 .getxattrat_recv_fn = vfswrap_getxattrat_recv,
3925 .fgetxattr_fn = vfswrap_fgetxattr,
3926 .listxattr_fn = vfswrap_listxattr,
3927 .flistxattr_fn = vfswrap_flistxattr,
3928 .removexattr_fn = vfswrap_removexattr,
3929 .fremovexattr_fn = vfswrap_fremovexattr,
3930 .setxattr_fn = vfswrap_setxattr,
3931 .fsetxattr_fn = vfswrap_fsetxattr,
3933 /* aio operations */
3934 .aio_force_fn = vfswrap_aio_force,
3936 /* durable handle operations */
3937 .durable_cookie_fn = vfswrap_durable_cookie,
3938 .durable_disconnect_fn = vfswrap_durable_disconnect,
3939 .durable_reconnect_fn = vfswrap_durable_reconnect,
3943 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3946 * Here we need to implement every call!
3948 * As this is the end of the vfs module chain.
3950 smb_vfs_assert_all_fns(&vfs_default_fns, DEFAULT_VFS_MODULE_NAME);
3951 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3952 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);