2 Unix SMB/CIFS implementation.
3 Wrap disk only vfs functions to sidestep dodgy compilers.
4 Copyright (C) Tim Potter 1998
5 Copyright (C) Jeremy Allison 2007
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "system/time.h"
23 #include "system/filesys.h"
24 #include "smbd/smbd.h"
25 #include "smbd/globals.h"
27 #include "smbprofile.h"
28 #include "../libcli/security/security.h"
29 #include "passdb/lookup_sid.h"
30 #include "source3/include/msdfs.h"
31 #include "librpc/gen_ndr/ndr_dfsblobs.h"
32 #include "lib/util/tevent_unix.h"
33 #include "lib/util/tevent_ntstatus.h"
34 #include "lib/util/sys_rw.h"
35 #include "lib/pthreadpool/pthreadpool_tevent.h"
36 #include "librpc/gen_ndr/ndr_ioctl.h"
37 #include "offload_token.h"
38 #include "util_reparse.h"
39 #include "lib/util/string_wrappers.h"
42 #define DBGC_CLASS DBGC_VFS
44 /* Check for NULL pointer parameters in vfswrap_* functions */
46 /* We don't want to have NULL function pointers lying around. Someone
47 is sure to try and execute them. These stubs are used to prevent
50 static int vfswrap_connect(vfs_handle_struct *handle, const char *service, const char *user)
52 handle->conn->have_proc_fds = sys_have_proc_fds();
53 return 0; /* Return >= 0 for success */
56 static void vfswrap_disconnect(vfs_handle_struct *handle)
62 static uint64_t vfswrap_disk_free(vfs_handle_struct *handle,
63 const struct smb_filename *smb_fname,
68 if (sys_fsusage(smb_fname->base_name, dfree, dsize) != 0) {
76 static int vfswrap_get_quota(struct vfs_handle_struct *handle,
77 const struct smb_filename *smb_fname,
78 enum SMB_QUOTA_TYPE qtype,
82 #ifdef HAVE_SYS_QUOTAS
85 START_PROFILE(syscall_get_quota);
86 result = sys_get_quota(smb_fname->base_name, qtype, id, qt);
87 END_PROFILE(syscall_get_quota);
95 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
97 #ifdef HAVE_SYS_QUOTAS
100 START_PROFILE(syscall_set_quota);
101 result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
102 END_PROFILE(syscall_set_quota);
110 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
111 struct files_struct *fsp,
112 struct shadow_copy_data *shadow_copy_data,
116 return -1; /* Not implemented. */
119 static int vfswrap_statvfs(struct vfs_handle_struct *handle,
120 const struct smb_filename *smb_fname,
121 vfs_statvfs_struct *statbuf)
123 return sys_statvfs(smb_fname->base_name, statbuf);
126 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
127 enum timestamp_set_resolution *p_ts_res)
129 const struct loadparm_substitution *lp_sub =
130 loadparm_s3_global_substitution();
131 connection_struct *conn = handle->conn;
132 uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
133 struct smb_filename *smb_fname_cpath = NULL;
134 struct vfs_statvfs_struct statbuf;
137 smb_fname_cpath = synthetic_smb_fname(talloc_tos(),
143 if (smb_fname_cpath == NULL) {
147 ZERO_STRUCT(statbuf);
148 ret = SMB_VFS_STATVFS(conn, smb_fname_cpath, &statbuf);
150 caps = statbuf.FsCapabilities;
153 *p_ts_res = TIMESTAMP_SET_SECONDS;
155 /* Work out what timestamp resolution we can
156 * use when setting a timestamp. */
158 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
160 TALLOC_FREE(smb_fname_cpath);
164 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
165 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
166 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
167 /* If any of the normal UNIX directory timestamps
168 * have a non-zero tv_nsec component assume
169 * we might be able to set sub-second timestamps.
170 * See what filetime set primitives we have.
172 #if defined(HAVE_UTIMENSAT)
173 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
174 #elif defined(HAVE_UTIMES)
175 /* utimes allows msec timestamps to be set. */
176 *p_ts_res = TIMESTAMP_SET_MSEC;
177 #elif defined(HAVE_UTIME)
178 /* utime only allows sec timestamps to be set. */
179 *p_ts_res = TIMESTAMP_SET_SECONDS;
182 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
184 "available on share %s, directory %s\n",
185 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
186 lp_servicename(talloc_tos(), lp_sub, conn->params->service),
187 conn->connectpath ));
189 TALLOC_FREE(smb_fname_cpath);
193 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
194 struct dfs_GetDFSReferral *r)
196 struct junction_map *junction = NULL;
198 bool self_referral = false;
199 char *pathnamep = NULL;
200 char *local_dfs_path = NULL;
203 uint16_t max_referral_level = r->in.req.max_referral_level;
206 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
209 /* get the junction entry */
210 if (r->in.req.servername == NULL) {
211 return NT_STATUS_NOT_FOUND;
215 * Trim pathname sent by client so it begins with only one backslash.
216 * Two backslashes confuse some dfs clients
219 local_dfs_path = talloc_strdup(r, r->in.req.servername);
220 if (local_dfs_path == NULL) {
221 return NT_STATUS_NO_MEMORY;
223 pathnamep = local_dfs_path;
224 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
225 IS_DIRECTORY_SEP(pathnamep[1])) {
229 junction = talloc_zero(r, struct junction_map);
230 if (junction == NULL) {
231 return NT_STATUS_NO_MEMORY;
234 /* The following call can change cwd. */
235 status = get_referred_path(r,
236 handle->conn->session_info,
238 handle->conn->sconn->remote_address,
239 handle->conn->sconn->local_address,
240 !handle->conn->sconn->using_smb2,
241 junction, &consumedcnt, &self_referral);
242 if (!NT_STATUS_IS_OK(status)) {
243 struct smb_filename connectpath_fname = {
244 .base_name = handle->conn->connectpath
246 vfs_ChDir(handle->conn, &connectpath_fname);
250 struct smb_filename connectpath_fname = {
251 .base_name = handle->conn->connectpath
253 vfs_ChDir(handle->conn, &connectpath_fname);
256 if (!self_referral) {
257 pathnamep[consumedcnt] = '\0';
260 dbgtext("Path %s to alternate path(s):",
262 for (i=0; i < junction->referral_count; i++) {
264 junction->referral_list[i].alternate_path);
270 if (r->in.req.max_referral_level <= 2) {
271 max_referral_level = 2;
273 if (r->in.req.max_referral_level >= 3) {
274 max_referral_level = 3;
277 r->out.resp = talloc_zero(r, struct dfs_referral_resp);
278 if (r->out.resp == NULL) {
279 return NT_STATUS_NO_MEMORY;
282 r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
283 r->out.resp->nb_referrals = junction->referral_count;
285 r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
287 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
290 r->out.resp->referral_entries = talloc_zero_array(r,
291 struct dfs_referral_type,
292 r->out.resp->nb_referrals);
293 if (r->out.resp->referral_entries == NULL) {
294 return NT_STATUS_NO_MEMORY;
297 switch (max_referral_level) {
299 for(i=0; i < junction->referral_count; i++) {
300 struct referral *ref = &junction->referral_list[i];
301 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
302 struct dfs_referral_type *t =
303 &r->out.resp->referral_entries[i];
304 struct dfs_referral_v2 *v2 = &t->referral.v2;
307 v2->size = VERSION2_REFERRAL_SIZE;
309 v2->server_type = DFS_SERVER_ROOT;
311 v2->server_type = DFS_SERVER_NON_ROOT;
314 v2->proximity = ref->proximity;
316 v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
317 if (v2->DFS_path == NULL) {
318 return NT_STATUS_NO_MEMORY;
320 v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
321 if (v2->DFS_alt_path == NULL) {
322 return NT_STATUS_NO_MEMORY;
324 v2->netw_address = talloc_strdup(mem_ctx,
325 ref->alternate_path);
326 if (v2->netw_address == NULL) {
327 return NT_STATUS_NO_MEMORY;
333 for(i=0; i < junction->referral_count; i++) {
334 struct referral *ref = &junction->referral_list[i];
335 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
336 struct dfs_referral_type *t =
337 &r->out.resp->referral_entries[i];
338 struct dfs_referral_v3 *v3 = &t->referral.v3;
339 struct dfs_normal_referral *r1 = &v3->referrals.r1;
342 v3->size = VERSION3_REFERRAL_SIZE;
344 v3->server_type = DFS_SERVER_ROOT;
346 v3->server_type = DFS_SERVER_NON_ROOT;
350 r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
351 if (r1->DFS_path == NULL) {
352 return NT_STATUS_NO_MEMORY;
354 r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
355 if (r1->DFS_alt_path == NULL) {
356 return NT_STATUS_NO_MEMORY;
358 r1->netw_address = talloc_strdup(mem_ctx,
359 ref->alternate_path);
360 if (r1->netw_address == NULL) {
361 return NT_STATUS_NO_MEMORY;
366 DEBUG(0,("Invalid dfs referral version: %d\n",
367 max_referral_level));
368 return NT_STATUS_INVALID_LEVEL;
372 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
378 static NTSTATUS vfswrap_create_dfs_pathat(struct vfs_handle_struct *handle,
379 struct files_struct *dirfsp,
380 const struct smb_filename *smb_fname,
381 const struct referral *reflist,
382 size_t referral_count)
384 TALLOC_CTX *frame = talloc_stackframe();
385 NTSTATUS status = NT_STATUS_NO_MEMORY;
387 char *msdfs_link = NULL;
389 /* Form the msdfs_link contents */
390 msdfs_link = msdfs_link_string(frame,
393 if (msdfs_link == NULL) {
397 ret = symlinkat(msdfs_link,
398 fsp_get_pathref_fd(dirfsp),
399 smb_fname->base_name);
401 status = NT_STATUS_OK;
403 status = map_nt_error_from_unix(errno);
413 * Read and return the contents of a DFS redirect given a
414 * pathname. A caller can pass in NULL for ppreflist and
415 * preferral_count but still determine if this was a
416 * DFS redirect point by getting NT_STATUS_OK back
417 * without incurring the overhead of reading and parsing
418 * the referral contents.
421 static NTSTATUS vfswrap_read_dfs_pathat(struct vfs_handle_struct *handle,
423 struct files_struct *dirfsp,
424 struct smb_filename *smb_fname,
425 struct referral **ppreflist,
426 size_t *preferral_count)
428 NTSTATUS status = NT_STATUS_NO_MEMORY;
430 char *link_target = NULL;
433 #if defined(HAVE_BROKEN_READLINK)
434 char link_target_buf[PATH_MAX];
436 char link_target_buf[7];
440 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
442 if (is_named_stream(smb_fname)) {
443 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
447 if (ppreflist == NULL && preferral_count == NULL) {
449 * We're only checking if this is a DFS
450 * redirect. We don't need to return data.
452 bufsize = sizeof(link_target_buf);
453 link_target = link_target_buf;
456 link_target = talloc_array(mem_ctx, char, bufsize);
462 referral_len = readlinkat(fsp_get_io_fd(dirfsp),
463 smb_fname->base_name,
466 if (referral_len == -1) {
467 if (errno == EINVAL) {
469 * If the path isn't a link, readlinkat
470 * returns EINVAL. Allow the caller to
473 DBG_INFO("%s is not a link.\n", smb_fname->base_name);
474 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
476 status = map_nt_error_from_unix(errno);
477 DBG_ERR("Error reading "
478 "msdfs link %s: %s\n",
479 smb_fname->base_name,
484 link_target[referral_len] = '\0';
486 DBG_INFO("%s -> %s\n",
487 smb_fname->base_name,
490 if (!strnequal(link_target, "msdfs:", 6)) {
491 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
495 ret = sys_lstat(smb_fname->base_name,
497 lp_fake_directory_create_times(SNUM(handle->conn)));
499 status = map_nt_error_from_unix(errno);
503 if (ppreflist == NULL && preferral_count == NULL) {
504 /* Early return for checking if this is a DFS link. */
508 ok = parse_msdfs_symlink(mem_ctx,
509 lp_msdfs_shuffle_referrals(SNUM(handle->conn)),
515 status = NT_STATUS_OK;
517 status = NT_STATUS_NO_MEMORY;
522 if (link_target != link_target_buf) {
523 TALLOC_FREE(link_target);
528 static NTSTATUS vfswrap_snap_check_path(struct vfs_handle_struct *handle,
530 const char *service_path,
533 return NT_STATUS_NOT_SUPPORTED;
536 static NTSTATUS vfswrap_snap_create(struct vfs_handle_struct *handle,
538 const char *base_volume,
544 return NT_STATUS_NOT_SUPPORTED;
547 static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle,
552 return NT_STATUS_NOT_SUPPORTED;
555 /* Directory operations */
557 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
564 START_PROFILE(syscall_fdopendir);
565 result = sys_fdopendir(fsp_get_io_fd(fsp));
566 END_PROFILE(syscall_fdopendir);
571 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
572 struct files_struct *dirfsp,
574 SMB_STRUCT_STAT *sbuf)
576 struct dirent *result;
577 bool do_stat = false;
578 bool fake_ctime = lp_fake_directory_create_times(SNUM(handle->conn));
579 int flags = AT_SYMLINK_NOFOLLOW;
583 START_PROFILE(syscall_readdir);
585 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
589 result = readdir(dirp);
590 END_PROFILE(syscall_readdir);
595 if (result == NULL) {
600 * Default Posix readdir() does not give us stat info.
601 * Set to invalid to indicate we didn't return this info.
603 SET_STAT_INVALID(*sbuf);
605 /* See if we can efficiently return this. */
610 ret = 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_mode) &&
625 !(dirfsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH))
629 init_stat_ex_from_stat(sbuf, &st, fake_ctime);
634 static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
635 const struct smb_filename *fname,
637 struct readdir_attr_data **attr_data)
639 return NT_STATUS_NOT_SUPPORTED;
642 static NTSTATUS vfswrap_freaddir_attr(struct vfs_handle_struct *handle,
643 struct files_struct *fsp,
645 struct readdir_attr_data **attr_data)
647 return NT_STATUS_NOT_SUPPORTED;
650 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
652 START_PROFILE(syscall_seekdir);
653 seekdir(dirp, offset);
654 END_PROFILE(syscall_seekdir);
657 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
660 START_PROFILE(syscall_telldir);
661 result = telldir(dirp);
662 END_PROFILE(syscall_telldir);
666 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
668 START_PROFILE(syscall_rewinddir);
670 END_PROFILE(syscall_rewinddir);
673 static int vfswrap_mkdirat(vfs_handle_struct *handle,
674 struct files_struct *dirfsp,
675 const struct smb_filename *smb_fname,
680 START_PROFILE(syscall_mkdirat);
682 result = mkdirat(fsp_get_pathref_fd(dirfsp), smb_fname->base_name, mode);
684 END_PROFILE(syscall_mkdirat);
688 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
692 START_PROFILE(syscall_closedir);
693 result = closedir(dirp);
694 END_PROFILE(syscall_closedir);
698 /* File operations */
700 static int vfswrap_openat(vfs_handle_struct *handle,
701 const struct files_struct *dirfsp,
702 const struct smb_filename *smb_fname,
707 bool have_opath = false;
708 bool became_root = false;
711 START_PROFILE(syscall_openat);
713 if (is_named_stream(smb_fname)) {
721 if (fsp->fsp_flags.is_pathref) {
726 if (fsp->fsp_flags.is_pathref && !have_opath) {
731 result = openat(fsp_get_pathref_fd(dirfsp),
732 smb_fname->base_name,
740 fsp->fsp_flags.have_proc_fds = fsp->conn->have_proc_fds;
743 END_PROFILE(syscall_openat);
746 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
747 struct smb_request *req,
748 struct smb_filename *smb_fname,
749 uint32_t access_mask,
750 uint32_t share_access,
751 uint32_t create_disposition,
752 uint32_t create_options,
753 uint32_t file_attributes,
754 uint32_t oplock_request,
755 const struct smb2_lease *lease,
756 uint64_t allocation_size,
757 uint32_t private_flags,
758 struct security_descriptor *sd,
759 struct ea_list *ea_list,
760 files_struct **result,
762 const struct smb2_create_blobs *in_context_blobs,
763 struct smb2_create_blobs *out_context_blobs)
765 return create_file_default(handle->conn, req, smb_fname,
766 access_mask, share_access,
767 create_disposition, create_options,
768 file_attributes, oplock_request, lease,
769 allocation_size, private_flags,
771 pinfo, in_context_blobs, out_context_blobs);
774 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
778 START_PROFILE(syscall_close);
779 result = fd_close_posix(fsp);
780 END_PROFILE(syscall_close);
784 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
785 size_t n, off_t offset)
789 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
790 START_PROFILE_BYTES(syscall_pread, n);
791 result = sys_pread_full(fsp_get_io_fd(fsp), data, n, offset);
792 END_PROFILE_BYTES(syscall_pread);
794 if (result == -1 && errno == ESPIPE) {
795 /* Maintain the fiction that pipes can be seeked (sought?) on. */
796 result = sys_read(fsp_get_io_fd(fsp), data, n);
797 fh_set_pos(fsp->fh, 0);
800 #else /* HAVE_PREAD */
803 #endif /* HAVE_PREAD */
808 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
809 size_t n, off_t offset)
813 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
814 START_PROFILE_BYTES(syscall_pwrite, n);
815 result = sys_pwrite_full(fsp_get_io_fd(fsp), data, n, offset);
816 END_PROFILE_BYTES(syscall_pwrite);
818 if (result == -1 && errno == ESPIPE) {
819 /* Maintain the fiction that pipes can be sought on. */
820 result = sys_write(fsp_get_io_fd(fsp), data, n);
823 #else /* HAVE_PWRITE */
826 #endif /* HAVE_PWRITE */
831 struct vfswrap_pread_state {
838 struct vfs_aio_state vfs_aio_state;
839 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
842 static void vfs_pread_do(void *private_data);
843 static void vfs_pread_done(struct tevent_req *subreq);
844 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state);
846 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
848 struct tevent_context *ev,
849 struct files_struct *fsp,
851 size_t n, off_t offset)
853 struct tevent_req *req, *subreq;
854 struct vfswrap_pread_state *state;
856 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
862 state->fd = fsp_get_io_fd(fsp);
865 state->offset = offset;
867 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
868 state->profile_bytes, n);
869 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
871 subreq = pthreadpool_tevent_job_send(
872 state, ev, handle->conn->sconn->pool,
873 vfs_pread_do, state);
874 if (tevent_req_nomem(subreq, req)) {
875 return tevent_req_post(req, ev);
877 tevent_req_set_callback(subreq, vfs_pread_done, req);
879 talloc_set_destructor(state, vfs_pread_state_destructor);
884 static void vfs_pread_do(void *private_data)
886 struct vfswrap_pread_state *state = talloc_get_type_abort(
887 private_data, struct vfswrap_pread_state);
888 struct timespec start_time;
889 struct timespec end_time;
891 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
893 PROFILE_TIMESTAMP(&start_time);
895 state->ret = sys_pread_full(state->fd,
900 if (state->ret == -1) {
901 state->vfs_aio_state.error = errno;
904 PROFILE_TIMESTAMP(&end_time);
906 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
908 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
911 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state)
916 static void vfs_pread_done(struct tevent_req *subreq)
918 struct tevent_req *req = tevent_req_callback_data(
919 subreq, struct tevent_req);
920 struct vfswrap_pread_state *state = tevent_req_data(
921 req, struct vfswrap_pread_state);
924 ret = pthreadpool_tevent_job_recv(subreq);
926 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
927 talloc_set_destructor(state, NULL);
930 tevent_req_error(req, ret);
934 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
935 * means the lower level pthreadpool failed to create a new
936 * thread. Fallback to sync processing in that case to allow
937 * some progress for the client.
942 tevent_req_done(req);
945 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
946 struct vfs_aio_state *vfs_aio_state)
948 struct vfswrap_pread_state *state = tevent_req_data(
949 req, struct vfswrap_pread_state);
951 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
955 *vfs_aio_state = state->vfs_aio_state;
959 struct vfswrap_pwrite_state {
966 struct vfs_aio_state vfs_aio_state;
967 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
970 static void vfs_pwrite_do(void *private_data);
971 static void vfs_pwrite_done(struct tevent_req *subreq);
972 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state);
974 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
976 struct tevent_context *ev,
977 struct files_struct *fsp,
979 size_t n, off_t offset)
981 struct tevent_req *req, *subreq;
982 struct vfswrap_pwrite_state *state;
984 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
990 state->fd = fsp_get_io_fd(fsp);
993 state->offset = offset;
995 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
996 state->profile_bytes, n);
997 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
999 subreq = pthreadpool_tevent_job_send(
1000 state, ev, handle->conn->sconn->pool,
1001 vfs_pwrite_do, state);
1002 if (tevent_req_nomem(subreq, req)) {
1003 return tevent_req_post(req, ev);
1005 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
1007 talloc_set_destructor(state, vfs_pwrite_state_destructor);
1012 static void vfs_pwrite_do(void *private_data)
1014 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
1015 private_data, struct vfswrap_pwrite_state);
1016 struct timespec start_time;
1017 struct timespec end_time;
1019 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
1021 PROFILE_TIMESTAMP(&start_time);
1023 state->ret = sys_pwrite_full(state->fd,
1028 if (state->ret == -1) {
1029 state->vfs_aio_state.error = errno;
1032 PROFILE_TIMESTAMP(&end_time);
1034 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1036 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1039 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state)
1044 static void vfs_pwrite_done(struct tevent_req *subreq)
1046 struct tevent_req *req = tevent_req_callback_data(
1047 subreq, struct tevent_req);
1048 struct vfswrap_pwrite_state *state = tevent_req_data(
1049 req, struct vfswrap_pwrite_state);
1052 ret = pthreadpool_tevent_job_recv(subreq);
1053 TALLOC_FREE(subreq);
1054 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1055 talloc_set_destructor(state, NULL);
1057 if (ret != EAGAIN) {
1058 tevent_req_error(req, ret);
1062 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1063 * means the lower level pthreadpool failed to create a new
1064 * thread. Fallback to sync processing in that case to allow
1065 * some progress for the client.
1067 vfs_pwrite_do(state);
1070 tevent_req_done(req);
1073 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
1074 struct vfs_aio_state *vfs_aio_state)
1076 struct vfswrap_pwrite_state *state = tevent_req_data(
1077 req, struct vfswrap_pwrite_state);
1079 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1083 *vfs_aio_state = state->vfs_aio_state;
1087 struct vfswrap_fsync_state {
1091 struct vfs_aio_state vfs_aio_state;
1092 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
1095 static void vfs_fsync_do(void *private_data);
1096 static void vfs_fsync_done(struct tevent_req *subreq);
1097 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state);
1099 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
1100 TALLOC_CTX *mem_ctx,
1101 struct tevent_context *ev,
1102 struct files_struct *fsp)
1104 struct tevent_req *req, *subreq;
1105 struct vfswrap_fsync_state *state;
1107 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
1113 state->fd = fsp_get_io_fd(fsp);
1115 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_fsync, profile_p,
1116 state->profile_bytes, 0);
1117 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1119 subreq = pthreadpool_tevent_job_send(
1120 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
1121 if (tevent_req_nomem(subreq, req)) {
1122 return tevent_req_post(req, ev);
1124 tevent_req_set_callback(subreq, vfs_fsync_done, req);
1126 talloc_set_destructor(state, vfs_fsync_state_destructor);
1131 static void vfs_fsync_do(void *private_data)
1133 struct vfswrap_fsync_state *state = talloc_get_type_abort(
1134 private_data, struct vfswrap_fsync_state);
1135 struct timespec start_time;
1136 struct timespec end_time;
1138 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
1140 PROFILE_TIMESTAMP(&start_time);
1143 state->ret = fsync(state->fd);
1144 } while ((state->ret == -1) && (errno == EINTR));
1146 if (state->ret == -1) {
1147 state->vfs_aio_state.error = errno;
1150 PROFILE_TIMESTAMP(&end_time);
1152 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1154 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1157 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state)
1162 static void vfs_fsync_done(struct tevent_req *subreq)
1164 struct tevent_req *req = tevent_req_callback_data(
1165 subreq, struct tevent_req);
1166 struct vfswrap_fsync_state *state = tevent_req_data(
1167 req, struct vfswrap_fsync_state);
1170 ret = pthreadpool_tevent_job_recv(subreq);
1171 TALLOC_FREE(subreq);
1172 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1173 talloc_set_destructor(state, NULL);
1175 if (ret != EAGAIN) {
1176 tevent_req_error(req, ret);
1180 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1181 * means the lower level pthreadpool failed to create a new
1182 * thread. Fallback to sync processing in that case to allow
1183 * some progress for the client.
1185 vfs_fsync_do(state);
1188 tevent_req_done(req);
1191 static int vfswrap_fsync_recv(struct tevent_req *req,
1192 struct vfs_aio_state *vfs_aio_state)
1194 struct vfswrap_fsync_state *state = tevent_req_data(
1195 req, struct vfswrap_fsync_state);
1197 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1201 *vfs_aio_state = state->vfs_aio_state;
1205 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1209 START_PROFILE(syscall_lseek);
1211 result = lseek(fsp_get_io_fd(fsp), offset, whence);
1213 * We want to maintain the fiction that we can seek
1214 * on a fifo for file system purposes. This allows
1215 * people to set up UNIX fifo's that feed data to Windows
1216 * applications. JRA.
1219 if((result == -1) && (errno == ESPIPE)) {
1224 END_PROFILE(syscall_lseek);
1228 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1229 off_t offset, size_t n)
1233 START_PROFILE_BYTES(syscall_sendfile, n);
1234 result = sys_sendfile(tofd, fsp_get_io_fd(fromfsp), hdr, offset, n);
1235 END_PROFILE_BYTES(syscall_sendfile);
1239 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1241 files_struct *tofsp,
1247 START_PROFILE_BYTES(syscall_recvfile, n);
1248 result = sys_recvfile(fromfd, fsp_get_io_fd(tofsp), offset, n);
1249 END_PROFILE_BYTES(syscall_recvfile);
1253 static int vfswrap_renameat(vfs_handle_struct *handle,
1254 files_struct *srcfsp,
1255 const struct smb_filename *smb_fname_src,
1256 files_struct *dstfsp,
1257 const struct smb_filename *smb_fname_dst)
1261 START_PROFILE(syscall_renameat);
1263 if (is_named_stream(smb_fname_src) || is_named_stream(smb_fname_dst)) {
1268 result = renameat(fsp_get_pathref_fd(srcfsp),
1269 smb_fname_src->base_name,
1270 fsp_get_pathref_fd(dstfsp),
1271 smb_fname_dst->base_name);
1274 END_PROFILE(syscall_renameat);
1278 static int vfswrap_stat(vfs_handle_struct *handle,
1279 struct smb_filename *smb_fname)
1283 START_PROFILE(syscall_stat);
1285 if (is_named_stream(smb_fname)) {
1290 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1291 lp_fake_directory_create_times(SNUM(handle->conn)));
1293 END_PROFILE(syscall_stat);
1297 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1301 START_PROFILE(syscall_fstat);
1302 result = sys_fstat(fsp_get_pathref_fd(fsp),
1303 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1304 END_PROFILE(syscall_fstat);
1308 static int vfswrap_lstat(vfs_handle_struct *handle,
1309 struct smb_filename *smb_fname)
1313 START_PROFILE(syscall_lstat);
1315 if (is_named_stream(smb_fname)) {
1320 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1321 lp_fake_directory_create_times(SNUM(handle->conn)));
1323 END_PROFILE(syscall_lstat);
1327 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1329 enum vfs_translate_direction direction,
1330 TALLOC_CTX *mem_ctx,
1333 return NT_STATUS_NONE_MAPPED;
1337 * Implement the default fsctl operation.
1339 static bool vfswrap_logged_ioctl_message = false;
1341 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1342 struct files_struct *fsp,
1345 uint16_t req_flags, /* Needed for UNICODE ... */
1346 const uint8_t *_in_data,
1348 uint8_t **_out_data,
1349 uint32_t max_out_len,
1352 const char *in_data = (const char *)_in_data;
1353 char **out_data = (char **)_out_data;
1357 case FSCTL_SET_SPARSE:
1359 bool set_sparse = true;
1361 if (in_len >= 1 && in_data[0] == 0) {
1365 status = file_set_sparse(handle->conn, fsp, set_sparse);
1367 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1368 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1369 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1370 nt_errstr(status)));
1375 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1377 unsigned char objid[16];
1378 char *return_data = NULL;
1380 /* This should return the object-id on this file.
1381 * I think I'll make this be the inode+dev. JRA.
1384 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1385 fsp_fnum_dbg(fsp)));
1387 *out_len = MIN(max_out_len, 64);
1389 /* Hmmm, will this cause problems if less data asked for? */
1390 return_data = talloc_array(ctx, char, 64);
1391 if (return_data == NULL) {
1392 return NT_STATUS_NO_MEMORY;
1395 /* For backwards compatibility only store the dev/inode. */
1396 push_file_id_16(return_data, &fsp->file_id);
1397 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1398 push_file_id_16(return_data+32, &fsp->file_id);
1399 memset(return_data+48, 0, 16);
1400 *out_data = return_data;
1401 return NT_STATUS_OK;
1404 case FSCTL_GET_REPARSE_POINT:
1406 status = fsctl_get_reparse_point(
1407 fsp, ctx, out_data, max_out_len, out_len);
1411 case FSCTL_SET_REPARSE_POINT:
1413 status = fsctl_set_reparse_point(fsp, ctx, _in_data, in_len);
1417 case FSCTL_DELETE_REPARSE_POINT:
1419 status = fsctl_del_reparse_point(fsp, ctx, _in_data, in_len);
1423 case FSCTL_GET_SHADOW_COPY_DATA:
1426 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1427 * and return their volume names. If max_data_count is 16, then it is just
1428 * asking for the number of volumes and length of the combined names.
1430 * pdata is the data allocated by our caller, but that uses
1431 * total_data_count (which is 0 in our case) rather than max_data_count.
1432 * Allocate the correct amount and return the pointer to let
1433 * it be deallocated when we return.
1435 struct shadow_copy_data *shadow_data = NULL;
1436 bool labels = False;
1437 uint32_t labels_data_count = 0;
1439 char *cur_pdata = NULL;
1441 if (max_out_len < 16) {
1442 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1444 return NT_STATUS_INVALID_PARAMETER;
1447 if (max_out_len > 16) {
1451 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1452 if (shadow_data == NULL) {
1453 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1454 return NT_STATUS_NO_MEMORY;
1458 * Call the VFS routine to actually do the work.
1460 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1463 /* broken module didn't set errno on error */
1464 status = NT_STATUS_UNSUCCESSFUL;
1466 status = map_nt_error_from_unix(errno);
1467 if (NT_STATUS_EQUAL(status,
1468 NT_STATUS_NOT_SUPPORTED)) {
1472 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1473 "connectpath %s, failed - %s.\n",
1474 fsp->conn->connectpath,
1475 nt_errstr(status)));
1476 TALLOC_FREE(shadow_data);
1480 labels_data_count = (shadow_data->num_volumes * 2 *
1481 sizeof(SHADOW_COPY_LABEL)) + 2;
1486 *out_len = 12 + labels_data_count;
1489 if (max_out_len < *out_len) {
1490 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1491 max_out_len, *out_len));
1492 TALLOC_FREE(shadow_data);
1493 return NT_STATUS_BUFFER_TOO_SMALL;
1496 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1497 if (cur_pdata == NULL) {
1498 TALLOC_FREE(shadow_data);
1499 return NT_STATUS_NO_MEMORY;
1502 *out_data = cur_pdata;
1504 /* num_volumes 4 bytes */
1505 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1508 /* num_labels 4 bytes */
1509 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1512 /* needed_data_count 4 bytes */
1513 SIVAL(cur_pdata, 8, labels_data_count);
1517 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1518 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1519 if (labels && shadow_data->labels) {
1520 for (i=0; i<shadow_data->num_volumes; i++) {
1522 status = srvstr_push(cur_pdata, req_flags,
1523 cur_pdata, shadow_data->labels[i],
1524 2 * sizeof(SHADOW_COPY_LABEL),
1525 STR_UNICODE|STR_TERMINATE, &len);
1526 if (!NT_STATUS_IS_OK(status)) {
1527 TALLOC_FREE(*out_data);
1528 TALLOC_FREE(shadow_data);
1531 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1532 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1536 TALLOC_FREE(shadow_data);
1538 return NT_STATUS_OK;
1541 case FSCTL_FIND_FILES_BY_SID:
1543 /* pretend this succeeded -
1545 * we have to send back a list with all files owned by this SID
1547 * but I have to check that --metze
1551 struct dom_sid_buf buf;
1555 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1556 fsp_fnum_dbg(fsp)));
1559 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1560 return NT_STATUS_INVALID_PARAMETER;
1563 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1565 /* unknown 4 bytes: this is not the length of the sid :-( */
1566 /*unknown = IVAL(pdata,0);*/
1568 ret = sid_parse(_in_data + 4, sid_len, &sid);
1570 return NT_STATUS_INVALID_PARAMETER;
1572 DEBUGADD(10, ("for SID: %s\n",
1573 dom_sid_str_buf(&sid, &buf)));
1575 if (!sid_to_uid(&sid, &uid)) {
1576 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1577 dom_sid_str_buf(&sid, &buf),
1578 (unsigned long)sid_len));
1582 /* we can take a look at the find source :-)
1584 * find ./ -uid $uid -name '*' is what we need here
1587 * and send 4bytes len and then NULL terminated unicode strings
1590 * but I don't know how to deal with the paged results
1591 * (maybe we can hang the result anywhere in the fsp struct)
1593 * but I don't know how to deal with the paged results
1594 * (maybe we can hang the result anywhere in the fsp struct)
1596 * we don't send all files at once
1597 * and at the next we should *not* start from the beginning,
1598 * so we have to cache the result
1603 /* this works for now... */
1604 return NT_STATUS_OK;
1607 case FSCTL_QUERY_ALLOCATED_RANGES:
1609 /* FIXME: This is just a dummy reply, telling that all of the
1610 * file is allocated. MKS cp needs that.
1611 * Adding the real allocated ranges via FIEMAP on Linux
1612 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1613 * this FSCTL correct for sparse files.
1615 uint64_t offset, length;
1616 char *out_data_tmp = NULL;
1619 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1621 return NT_STATUS_INVALID_PARAMETER;
1624 if (max_out_len < 16) {
1625 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1627 return NT_STATUS_INVALID_PARAMETER;
1630 offset = BVAL(in_data,0);
1631 length = BVAL(in_data,8);
1633 if (offset + length < offset) {
1634 /* No 64-bit integer wrap. */
1635 return NT_STATUS_INVALID_PARAMETER;
1638 /* Shouldn't this be SMB_VFS_STAT ... ? */
1639 status = vfs_stat_fsp(fsp);
1640 if (!NT_STATUS_IS_OK(status)) {
1645 out_data_tmp = talloc_array(ctx, char, *out_len);
1646 if (out_data_tmp == NULL) {
1647 DEBUG(10, ("unable to allocate memory for response\n"));
1648 return NT_STATUS_NO_MEMORY;
1651 if (offset > fsp->fsp_name->st.st_ex_size ||
1652 fsp->fsp_name->st.st_ex_size == 0 ||
1654 memset(out_data_tmp, 0, *out_len);
1656 uint64_t end = offset + length;
1657 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1658 SBVAL(out_data_tmp, 0, 0);
1659 SBVAL(out_data_tmp, 8, end);
1662 *out_data = out_data_tmp;
1664 return NT_STATUS_OK;
1667 case FSCTL_IS_VOLUME_DIRTY:
1669 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1670 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1672 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1673 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1675 return NT_STATUS_INVALID_PARAMETER;
1680 * Only print once ... unfortunately there could be lots of
1681 * different FSCTLs that are called.
1683 if (!vfswrap_logged_ioctl_message) {
1684 vfswrap_logged_ioctl_message = true;
1685 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1686 __func__, function));
1690 return NT_STATUS_NOT_SUPPORTED;
1693 static bool vfswrap_is_offline(struct connection_struct *conn,
1694 const struct smb_filename *fname);
1696 struct vfswrap_get_dos_attributes_state {
1697 struct vfs_aio_state aio_state;
1698 connection_struct *conn;
1699 TALLOC_CTX *mem_ctx;
1700 struct tevent_context *ev;
1701 files_struct *dir_fsp;
1702 struct smb_filename *smb_fname;
1707 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq);
1709 static struct tevent_req *vfswrap_get_dos_attributes_send(
1710 TALLOC_CTX *mem_ctx,
1711 struct tevent_context *ev,
1712 struct vfs_handle_struct *handle,
1713 files_struct *dir_fsp,
1714 struct smb_filename *smb_fname)
1716 struct tevent_req *req = NULL;
1717 struct tevent_req *subreq = NULL;
1718 struct vfswrap_get_dos_attributes_state *state = NULL;
1720 req = tevent_req_create(mem_ctx, &state,
1721 struct vfswrap_get_dos_attributes_state);
1726 *state = (struct vfswrap_get_dos_attributes_state) {
1727 .conn = dir_fsp->conn,
1731 .smb_fname = smb_fname,
1734 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1738 SAMBA_XATTR_DOS_ATTRIB,
1740 if (tevent_req_nomem(subreq, req)) {
1741 return tevent_req_post(req, ev);
1743 tevent_req_set_callback(subreq,
1744 vfswrap_get_dos_attributes_getxattr_done,
1750 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq)
1752 struct tevent_req *req =
1753 tevent_req_callback_data(subreq,
1755 struct vfswrap_get_dos_attributes_state *state =
1756 tevent_req_data(req,
1757 struct vfswrap_get_dos_attributes_state);
1759 DATA_BLOB blob = {0};
1761 char *tofree = NULL;
1762 char pathbuf[PATH_MAX+1];
1764 struct smb_filename smb_fname;
1768 xattr_size = SMB_VFS_GETXATTRAT_RECV(subreq,
1772 TALLOC_FREE(subreq);
1773 if (xattr_size == -1) {
1774 status = map_nt_error_from_unix(state->aio_state.error);
1776 if (state->as_root) {
1777 tevent_req_nterror(req, status);
1780 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1781 tevent_req_nterror(req, status);
1785 state->as_root = true;
1788 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1792 SAMBA_XATTR_DOS_ATTRIB,
1795 if (tevent_req_nomem(subreq, req)) {
1798 tevent_req_set_callback(subreq,
1799 vfswrap_get_dos_attributes_getxattr_done,
1804 blob.length = xattr_size;
1806 status = parse_dos_attribute_blob(state->smb_fname,
1809 if (!NT_STATUS_IS_OK(status)) {
1810 tevent_req_nterror(req, status);
1814 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
1815 state->smb_fname->base_name,
1820 if (pathlen == -1) {
1821 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1825 smb_fname = (struct smb_filename) {
1827 .st = state->smb_fname->st,
1828 .flags = state->smb_fname->flags,
1829 .twrp = state->smb_fname->twrp,
1832 offline = vfswrap_is_offline(state->conn, &smb_fname);
1834 state->dosmode |= FILE_ATTRIBUTE_OFFLINE;
1836 TALLOC_FREE(tofree);
1838 tevent_req_done(req);
1842 static NTSTATUS vfswrap_get_dos_attributes_recv(struct tevent_req *req,
1843 struct vfs_aio_state *aio_state,
1846 struct vfswrap_get_dos_attributes_state *state =
1847 tevent_req_data(req,
1848 struct vfswrap_get_dos_attributes_state);
1851 if (tevent_req_is_nterror(req, &status)) {
1852 tevent_req_received(req);
1856 *aio_state = state->aio_state;
1857 *dosmode = state->dosmode;
1858 tevent_req_received(req);
1859 return NT_STATUS_OK;
1862 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1863 struct files_struct *fsp,
1868 offline = vfswrap_is_offline(handle->conn, fsp->fsp_name);
1870 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1873 return fget_ea_dos_attribute(fsp, dosmode);
1876 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1877 struct files_struct *fsp,
1880 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1883 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1885 struct vfswrap_offload_read_state {
1889 static struct tevent_req *vfswrap_offload_read_send(
1890 TALLOC_CTX *mem_ctx,
1891 struct tevent_context *ev,
1892 struct vfs_handle_struct *handle,
1893 struct files_struct *fsp,
1899 struct tevent_req *req = NULL;
1900 struct vfswrap_offload_read_state *state = NULL;
1903 req = tevent_req_create(mem_ctx, &state,
1904 struct vfswrap_offload_read_state);
1909 status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1910 &vfswrap_offload_ctx);
1911 if (tevent_req_nterror(req, status)) {
1912 return tevent_req_post(req, ev);
1915 if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1916 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1917 return tevent_req_post(req, ev);
1920 status = vfs_offload_token_create_blob(state, fsp, fsctl,
1922 if (tevent_req_nterror(req, status)) {
1923 return tevent_req_post(req, ev);
1926 status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1928 if (tevent_req_nterror(req, status)) {
1929 return tevent_req_post(req, ev);
1932 tevent_req_done(req);
1933 return tevent_req_post(req, ev);
1936 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
1937 struct vfs_handle_struct *handle,
1938 TALLOC_CTX *mem_ctx,
1941 struct vfswrap_offload_read_state *state = tevent_req_data(
1942 req, struct vfswrap_offload_read_state);
1945 if (tevent_req_is_nterror(req, &status)) {
1946 tevent_req_received(req);
1950 token->length = state->token.length;
1951 token->data = talloc_move(mem_ctx, &state->token.data);
1953 tevent_req_received(req);
1954 return NT_STATUS_OK;
1957 struct vfswrap_offload_write_state {
1959 bool read_lck_locked;
1960 bool write_lck_locked;
1962 struct tevent_context *src_ev;
1963 struct files_struct *src_fsp;
1965 struct tevent_context *dst_ev;
1966 struct files_struct *dst_fsp;
1970 size_t next_io_size;
1973 static void vfswrap_offload_write_cleanup(struct tevent_req *req,
1974 enum tevent_req_state req_state)
1976 struct vfswrap_offload_write_state *state = tevent_req_data(
1977 req, struct vfswrap_offload_write_state);
1980 if (state->dst_fsp == NULL) {
1984 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
1986 state->dst_fsp = NULL;
1989 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
1991 static struct tevent_req *vfswrap_offload_write_send(
1992 struct vfs_handle_struct *handle,
1993 TALLOC_CTX *mem_ctx,
1994 struct tevent_context *ev,
1997 off_t transfer_offset,
1998 struct files_struct *dest_fsp,
2002 struct tevent_req *req;
2003 struct vfswrap_offload_write_state *state = NULL;
2004 /* off_t is signed! */
2005 off_t max_offset = INT64_MAX - to_copy;
2006 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
2007 files_struct *src_fsp = NULL;
2011 req = tevent_req_create(mem_ctx, &state,
2012 struct vfswrap_offload_write_state);
2017 *state = (struct vfswrap_offload_write_state) {
2019 .src_off = transfer_offset,
2021 .dst_fsp = dest_fsp,
2022 .dst_off = dest_off,
2024 .remaining = to_copy,
2027 tevent_req_set_cleanup_fn(req, vfswrap_offload_write_cleanup);
2030 case FSCTL_SRV_COPYCHUNK:
2031 case FSCTL_SRV_COPYCHUNK_WRITE:
2034 case FSCTL_OFFLOAD_WRITE:
2035 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
2036 return tevent_req_post(req, ev);
2038 case FSCTL_DUP_EXTENTS_TO_FILE:
2039 DBG_DEBUG("COW clones not supported by vfs_default\n");
2040 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2041 return tevent_req_post(req, ev);
2044 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2045 return tevent_req_post(req, ev);
2049 * From here on we assume a copy-chunk fsctl
2053 tevent_req_done(req);
2054 return tevent_req_post(req, ev);
2057 if (state->src_off > max_offset) {
2059 * Protect integer checks below.
2061 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2062 return tevent_req_post(req, ev);
2064 if (state->src_off < 0) {
2066 * Protect integer checks below.
2068 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2069 return tevent_req_post(req, ev);
2071 if (state->dst_off > max_offset) {
2073 * Protect integer checks below.
2075 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2076 return tevent_req_post(req, ev);
2078 if (state->dst_off < 0) {
2080 * Protect integer checks below.
2082 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2083 return tevent_req_post(req, ev);
2086 status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
2088 if (tevent_req_nterror(req, status)) {
2089 return tevent_req_post(req, ev);
2092 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
2094 status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
2095 if (!NT_STATUS_IS_OK(status)) {
2096 tevent_req_nterror(req, status);
2097 return tevent_req_post(req, ev);
2100 ok = change_to_user_and_service_by_fsp(src_fsp);
2102 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2103 return tevent_req_post(req, ev);
2106 state->src_ev = src_fsp->conn->sconn->ev_ctx;
2107 state->src_fsp = src_fsp;
2109 status = vfs_stat_fsp(src_fsp);
2110 if (tevent_req_nterror(req, status)) {
2111 return tevent_req_post(req, ev);
2114 if (src_fsp->fsp_name->st.st_ex_size < state->src_off + to_copy) {
2116 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
2117 * If the SourceOffset or SourceOffset + Length extends beyond
2118 * the end of file, the server SHOULD<240> treat this as a
2119 * STATUS_END_OF_FILE error.
2121 * <240> Section 3.3.5.15.6: Windows servers will return
2122 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
2124 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
2125 return tevent_req_post(req, ev);
2128 state->buf = talloc_array(state, uint8_t, num);
2129 if (tevent_req_nomem(state->buf, req)) {
2130 return tevent_req_post(req, ev);
2133 status = vfswrap_offload_write_loop(req);
2134 if (!NT_STATUS_IS_OK(status)) {
2135 tevent_req_nterror(req, status);
2136 return tevent_req_post(req, ev);
2142 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
2144 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
2146 struct vfswrap_offload_write_state *state = tevent_req_data(
2147 req, struct vfswrap_offload_write_state);
2148 struct tevent_req *subreq = NULL;
2149 struct lock_struct read_lck;
2153 * This is called under the context of state->src_fsp.
2156 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
2158 init_strict_lock_struct(state->src_fsp,
2159 state->src_fsp->op->global->open_persistent_id,
2161 state->next_io_size,
2165 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
2169 return NT_STATUS_FILE_LOCK_CONFLICT;
2172 subreq = SMB_VFS_PREAD_SEND(state,
2176 state->next_io_size,
2178 if (subreq == NULL) {
2179 return NT_STATUS_NO_MEMORY;
2181 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
2183 return NT_STATUS_OK;
2186 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
2188 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
2190 struct tevent_req *req = tevent_req_callback_data(
2191 subreq, struct tevent_req);
2192 struct vfswrap_offload_write_state *state = tevent_req_data(
2193 req, struct vfswrap_offload_write_state);
2194 struct vfs_aio_state aio_state;
2195 struct lock_struct write_lck;
2199 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
2200 TALLOC_FREE(subreq);
2202 DBG_ERR("read failed: %s\n", strerror(aio_state.error));
2203 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2206 if (nread != state->next_io_size) {
2207 DBG_ERR("Short read, only %zd of %zu\n",
2208 nread, state->next_io_size);
2209 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2213 state->src_off += nread;
2215 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2217 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2221 init_strict_lock_struct(state->dst_fsp,
2222 state->dst_fsp->op->global->open_persistent_id,
2224 state->next_io_size,
2228 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
2232 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
2236 subreq = SMB_VFS_PWRITE_SEND(state,
2240 state->next_io_size,
2242 if (subreq == NULL) {
2243 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2246 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
2249 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
2251 struct tevent_req *req = tevent_req_callback_data(
2252 subreq, struct tevent_req);
2253 struct vfswrap_offload_write_state *state = tevent_req_data(
2254 req, struct vfswrap_offload_write_state);
2255 struct vfs_aio_state aio_state;
2260 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
2261 TALLOC_FREE(subreq);
2262 if (nwritten == -1) {
2263 DBG_ERR("write failed: %s\n", strerror(aio_state.error));
2264 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2267 if (nwritten != state->next_io_size) {
2268 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
2269 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2273 state->dst_off += nwritten;
2275 if (state->remaining < nwritten) {
2276 /* Paranoia check */
2277 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2280 state->remaining -= nwritten;
2281 if (state->remaining == 0) {
2282 tevent_req_done(req);
2286 ok = change_to_user_and_service_by_fsp(state->src_fsp);
2288 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2292 status = vfswrap_offload_write_loop(req);
2293 if (!NT_STATUS_IS_OK(status)) {
2294 tevent_req_nterror(req, status);
2301 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
2302 struct tevent_req *req,
2305 struct vfswrap_offload_write_state *state = tevent_req_data(
2306 req, struct vfswrap_offload_write_state);
2309 if (tevent_req_is_nterror(req, &status)) {
2310 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
2312 tevent_req_received(req);
2316 *copied = state->to_copy;
2317 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
2318 tevent_req_received(req);
2320 return NT_STATUS_OK;
2323 static NTSTATUS vfswrap_fget_compression(struct vfs_handle_struct *handle,
2324 TALLOC_CTX *mem_ctx,
2325 struct files_struct *fsp,
2326 uint16_t *_compression_fmt)
2328 return NT_STATUS_INVALID_DEVICE_REQUEST;
2331 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
2332 TALLOC_CTX *mem_ctx,
2333 struct files_struct *fsp,
2334 uint16_t compression_fmt)
2336 return NT_STATUS_INVALID_DEVICE_REQUEST;
2339 /********************************************************************
2340 Given a stat buffer return the allocated size on disk, taking into
2341 account sparse files.
2342 ********************************************************************/
2343 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
2344 struct files_struct *fsp,
2345 const SMB_STRUCT_STAT *sbuf)
2349 START_PROFILE(syscall_get_alloc_size);
2351 if(S_ISDIR(sbuf->st_ex_mode)) {
2356 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2357 /* The type of st_blocksize is blkcnt_t which *MUST* be
2358 signed (according to POSIX) and can be less than 64-bits.
2359 Ensure when we're converting to 64 bits wide we don't
2361 #if defined(SIZEOF_BLKCNT_T_8)
2362 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2363 #elif defined(SIZEOF_BLKCNT_T_4)
2365 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2366 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2369 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2373 * Some file systems do not allocate a block for very
2374 * small files. But for non-empty file should report a
2378 uint64_t filesize = get_file_size_stat(sbuf);
2380 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2384 result = get_file_size_stat(sbuf);
2387 if (fsp && fsp->initial_allocation_size)
2388 result = MAX(result,fsp->initial_allocation_size);
2390 result = smb_roundup(handle->conn, result);
2393 END_PROFILE(syscall_get_alloc_size);
2397 static int vfswrap_unlinkat(vfs_handle_struct *handle,
2398 struct files_struct *dirfsp,
2399 const struct smb_filename *smb_fname,
2404 START_PROFILE(syscall_unlinkat);
2406 if (is_named_stream(smb_fname)) {
2410 result = unlinkat(fsp_get_pathref_fd(dirfsp),
2411 smb_fname->base_name,
2415 END_PROFILE(syscall_unlinkat);
2419 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2423 START_PROFILE(syscall_fchmod);
2425 if (!fsp->fsp_flags.is_pathref) {
2426 result = fchmod(fsp_get_io_fd(fsp), mode);
2427 END_PROFILE(syscall_fchmod);
2431 if (fsp->fsp_flags.have_proc_fds) {
2432 int fd = fsp_get_pathref_fd(fsp);
2433 const char *p = NULL;
2436 p = sys_proc_fd_path(fd, buf, sizeof(buf));
2438 result = chmod(p, mode);
2442 END_PROFILE(syscall_fchmod);
2447 * This is no longer a handle based call.
2449 result = chmod(fsp->fsp_name->base_name, mode);
2451 END_PROFILE(syscall_fchmod);
2455 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2460 START_PROFILE(syscall_fchown);
2461 result = fchown(fsp_get_io_fd(fsp), uid, gid);
2462 END_PROFILE(syscall_fchown);
2470 static int vfswrap_lchown(vfs_handle_struct *handle,
2471 const struct smb_filename *smb_fname,
2477 START_PROFILE(syscall_lchown);
2478 result = lchown(smb_fname->base_name, uid, gid);
2479 END_PROFILE(syscall_lchown);
2483 static int vfswrap_chdir(vfs_handle_struct *handle,
2484 const struct smb_filename *smb_fname)
2488 START_PROFILE(syscall_chdir);
2489 result = chdir(smb_fname->base_name);
2490 END_PROFILE(syscall_chdir);
2494 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2498 struct smb_filename *smb_fname = NULL;
2500 START_PROFILE(syscall_getwd);
2501 result = sys_getwd();
2502 END_PROFILE(syscall_getwd);
2504 if (result == NULL) {
2507 smb_fname = synthetic_smb_fname(ctx,
2514 * sys_getwd() *always* returns malloced memory.
2515 * We must free here to avoid leaks:
2516 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2522 /*********************************************************************
2523 nsec timestamp resolution call. Convert down to whatever the underlying
2524 system will support.
2525 **********************************************************************/
2527 static int vfswrap_fntimes(vfs_handle_struct *handle,
2529 struct smb_file_time *ft)
2532 struct timespec ts[2];
2533 struct timespec *times = NULL;
2535 START_PROFILE(syscall_fntimes);
2537 if (is_named_stream(fsp->fsp_name)) {
2543 if (is_omit_timespec(&ft->atime)) {
2544 ft->atime = fsp->fsp_name->st.st_ex_atime;
2547 if (is_omit_timespec(&ft->mtime)) {
2548 ft->mtime = fsp->fsp_name->st.st_ex_mtime;
2551 if (!is_omit_timespec(&ft->create_time)) {
2552 set_create_timespec_ea(handle->conn,
2557 if ((timespec_compare(&ft->atime,
2558 &fsp->fsp_name->st.st_ex_atime) == 0) &&
2559 (timespec_compare(&ft->mtime,
2560 &fsp->fsp_name->st.st_ex_mtime) == 0)) {
2572 if (!fsp->fsp_flags.is_pathref) {
2573 result = futimens(fsp_get_io_fd(fsp), times);
2577 if (fsp->fsp_flags.have_proc_fds) {
2578 int fd = fsp_get_pathref_fd(fsp);
2579 const char *p = NULL;
2582 p = sys_proc_fd_path(fd, buf, sizeof(buf));
2585 * The dirfd argument of utimensat is ignored when
2586 * pathname is an absolute path
2588 result = utimensat(AT_FDCWD, p, times, 0);
2597 * The fd is a pathref (opened with O_PATH) and there isn't fd to
2598 * path translation mechanism. Fallback to path based call.
2600 result = utimensat(AT_FDCWD, fsp->fsp_name->base_name, times, 0);
2603 END_PROFILE(syscall_fntimes);
2609 /*********************************************************************
2610 A version of ftruncate that will write the space on disk if strict
2612 **********************************************************************/
2614 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2616 off_t space_to_write;
2617 uint64_t space_avail;
2618 uint64_t bsize,dfree,dsize;
2621 SMB_STRUCT_STAT *pst;
2624 ok = vfs_valid_pwrite_range(len, 0);
2630 status = vfs_stat_fsp(fsp);
2631 if (!NT_STATUS_IS_OK(status)) {
2634 pst = &fsp->fsp_name->st;
2637 if (S_ISFIFO(pst->st_ex_mode))
2641 if (pst->st_ex_size == len)
2644 /* Shrink - just ftruncate. */
2645 if (pst->st_ex_size > len)
2646 return ftruncate(fsp_get_io_fd(fsp), len);
2648 space_to_write = len - pst->st_ex_size;
2650 /* for allocation try fallocate first. This can fail on some
2651 platforms e.g. when the filesystem doesn't support it and no
2652 emulation is being done by the libc (like on AIX with JFS1). In that
2653 case we do our own emulation. fallocate implementations can
2654 return ENOTSUP or EINVAL in cases like that. */
2655 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2656 if (ret == -1 && errno == ENOSPC) {
2662 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2663 "error %d. Falling back to slow manual allocation\n", errno));
2665 /* available disk space is enough or not? */
2667 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2668 /* space_avail is 1k blocks */
2669 if (space_avail == (uint64_t)-1 ||
2670 ((uint64_t)space_to_write/1024 > space_avail) ) {
2675 /* Write out the real space on disk. */
2676 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2684 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2687 SMB_STRUCT_STAT *pst;
2691 START_PROFILE(syscall_ftruncate);
2693 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->fsp_flags.is_sparse) {
2694 result = strict_allocate_ftruncate(handle, fsp, len);
2695 END_PROFILE(syscall_ftruncate);
2699 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2700 ftruncate if the system supports it. Then I discovered that
2701 you can have some filesystems that support ftruncate
2702 expansion and some that don't! On Linux fat can't do
2703 ftruncate extend but ext2 can. */
2705 result = ftruncate(fsp_get_io_fd(fsp), len);
2707 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2708 extend a file with ftruncate. Provide alternate implementation
2711 /* Do an fstat to see if the file is longer than the requested
2712 size in which case the ftruncate above should have
2713 succeeded or shorter, in which case seek to len - 1 and
2714 write 1 byte of zero */
2715 status = vfs_stat_fsp(fsp);
2716 if (!NT_STATUS_IS_OK(status)) {
2720 /* We need to update the files_struct after successful ftruncate */
2725 pst = &fsp->fsp_name->st;
2728 if (S_ISFIFO(pst->st_ex_mode)) {
2734 if (pst->st_ex_size == len) {
2739 if (pst->st_ex_size > len) {
2740 /* the ftruncate should have worked */
2744 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2752 END_PROFILE(syscall_ftruncate);
2756 static int vfswrap_fallocate(vfs_handle_struct *handle,
2764 START_PROFILE(syscall_fallocate);
2766 result = sys_posix_fallocate(fsp_get_io_fd(fsp), offset, len);
2768 * posix_fallocate returns 0 on success, errno on error
2769 * and doesn't set errno. Make it behave like fallocate()
2770 * which returns -1, and sets errno on failure.
2777 /* sys_fallocate handles filtering of unsupported mode flags */
2778 result = sys_fallocate(fsp_get_io_fd(fsp), mode, offset, len);
2780 END_PROFILE(syscall_fallocate);
2784 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2788 START_PROFILE(syscall_fcntl_lock);
2790 if (fsp->fsp_flags.use_ofd_locks) {
2791 op = map_process_lock_to_ofd_lock(op);
2794 result = fcntl_lock(fsp_get_io_fd(fsp), op, offset, count, type);
2795 END_PROFILE(syscall_fcntl_lock);
2799 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2800 uint32_t share_access, uint32_t access_mask)
2802 START_PROFILE(syscall_kernel_flock);
2803 kernel_flock(fsp_get_io_fd(fsp), share_access, access_mask);
2804 END_PROFILE(syscall_kernel_flock);
2808 static int vfswrap_fcntl(vfs_handle_struct *handle, files_struct *fsp, int cmd,
2812 va_list dup_cmd_arg;
2816 START_PROFILE(syscall_fcntl);
2818 va_copy(dup_cmd_arg, cmd_arg);
2824 #if defined(HAVE_OFD_LOCKS)
2829 #if defined(HAVE_F_OWNER_EX)
2833 #if defined(HAVE_RW_HINTS)
2836 case F_GET_FILE_RW_HINT:
2837 case F_SET_FILE_RW_HINT:
2839 argp = va_arg(dup_cmd_arg, void *);
2840 result = sys_fcntl_ptr(fsp_get_io_fd(fsp), cmd, argp);
2843 val = va_arg(dup_cmd_arg, int);
2844 result = sys_fcntl_int(fsp_get_io_fd(fsp), cmd, val);
2847 va_end(dup_cmd_arg);
2849 END_PROFILE(syscall_fcntl);
2853 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2858 START_PROFILE(syscall_fcntl_getlock);
2860 if (fsp->fsp_flags.use_ofd_locks) {
2861 op = map_process_lock_to_ofd_lock(op);
2864 result = fcntl_getlock(fsp_get_io_fd(fsp), op, poffset, pcount, ptype, ppid);
2865 END_PROFILE(syscall_fcntl_getlock);
2869 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2874 START_PROFILE(syscall_linux_setlease);
2876 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2877 result = linux_setlease(fsp_get_io_fd(fsp), leasetype);
2881 END_PROFILE(syscall_linux_setlease);
2885 static int vfswrap_symlinkat(vfs_handle_struct *handle,
2886 const struct smb_filename *link_target,
2887 struct files_struct *dirfsp,
2888 const struct smb_filename *new_smb_fname)
2892 START_PROFILE(syscall_symlinkat);
2894 result = symlinkat(link_target->base_name,
2895 fsp_get_pathref_fd(dirfsp),
2896 new_smb_fname->base_name);
2897 END_PROFILE(syscall_symlinkat);
2901 static int vfswrap_readlinkat(vfs_handle_struct *handle,
2902 const struct files_struct *dirfsp,
2903 const struct smb_filename *smb_fname,
2909 START_PROFILE(syscall_readlinkat);
2911 result = readlinkat(fsp_get_pathref_fd(dirfsp),
2912 smb_fname->base_name,
2916 END_PROFILE(syscall_readlinkat);
2920 static int vfswrap_linkat(vfs_handle_struct *handle,
2921 files_struct *srcfsp,
2922 const struct smb_filename *old_smb_fname,
2923 files_struct *dstfsp,
2924 const struct smb_filename *new_smb_fname,
2929 START_PROFILE(syscall_linkat);
2931 result = linkat(fsp_get_pathref_fd(srcfsp),
2932 old_smb_fname->base_name,
2933 fsp_get_pathref_fd(dstfsp),
2934 new_smb_fname->base_name,
2937 END_PROFILE(syscall_linkat);
2941 static int vfswrap_mknodat(vfs_handle_struct *handle,
2942 files_struct *dirfsp,
2943 const struct smb_filename *smb_fname,
2949 START_PROFILE(syscall_mknodat);
2951 result = sys_mknodat(fsp_get_pathref_fd(dirfsp),
2952 smb_fname->base_name,
2956 END_PROFILE(syscall_mknodat);
2960 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2962 const struct smb_filename *smb_fname)
2965 struct smb_filename *result_fname = NULL;
2967 START_PROFILE(syscall_realpath);
2968 result = sys_realpath(smb_fname->base_name);
2969 END_PROFILE(syscall_realpath);
2971 result_fname = synthetic_smb_fname(ctx,
2979 return result_fname;
2982 static int vfswrap_chflags(vfs_handle_struct *handle,
2983 const struct smb_filename *smb_fname,
2987 return chflags(smb_fname->base_name, flags);
2994 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2995 const SMB_STRUCT_STAT *sbuf)
2999 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
3003 key.devid = sbuf->st_ex_dev;
3004 key.inode = sbuf->st_ex_ino;
3005 /* key.extid is unused by default. */
3010 static uint64_t vfswrap_fs_file_id(struct vfs_handle_struct *handle,
3011 const SMB_STRUCT_STAT *psbuf)
3015 if (!(psbuf->st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)) {
3016 return psbuf->st_ex_file_id;
3019 if (handle->conn->base_share_dev == psbuf->st_ex_dev) {
3020 return (uint64_t)psbuf->st_ex_ino;
3024 file_id = ((psbuf->st_ex_ino) & UINT32_MAX);
3027 file_id |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32;
3032 static NTSTATUS vfswrap_fstreaminfo(vfs_handle_struct *handle,
3033 struct files_struct *fsp,
3034 TALLOC_CTX *mem_ctx,
3035 unsigned int *pnum_streams,
3036 struct stream_struct **pstreams)
3038 struct stream_struct *tmp_streams = NULL;
3039 unsigned int num_streams = *pnum_streams;
3040 struct stream_struct *streams = *pstreams;
3043 if (fsp->fsp_flags.is_directory) {
3045 * No default streams on directories
3049 status = vfs_stat_fsp(fsp);
3050 if (!NT_STATUS_IS_OK(status)) {
3054 if (num_streams + 1 < 1) {
3056 return NT_STATUS_INVALID_PARAMETER;
3059 tmp_streams = talloc_realloc(mem_ctx,
3061 struct stream_struct,
3063 if (tmp_streams == NULL) {
3064 return NT_STATUS_NO_MEMORY;
3066 tmp_streams[num_streams].name = talloc_strdup(tmp_streams, "::$DATA");
3067 if (tmp_streams[num_streams].name == NULL) {
3068 return NT_STATUS_NO_MEMORY;
3070 tmp_streams[num_streams].size = fsp->fsp_name->st.st_ex_size;
3071 tmp_streams[num_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(
3074 &fsp->fsp_name->st);
3077 *pnum_streams = num_streams;
3078 *pstreams = tmp_streams;
3080 return NT_STATUS_OK;
3083 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
3084 const struct smb_filename *path,
3086 TALLOC_CTX *mem_ctx,
3090 * Don't fall back to get_real_filename so callers can differentiate
3091 * between a full directory scan and an actual case-insensitive stat.
3097 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
3098 const struct smb_filename *smb_fname)
3100 return handle->conn->connectpath;
3103 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
3104 struct byte_range_lock *br_lck,
3105 struct lock_struct *plock)
3107 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3109 /* Note: blr is not used in the default implementation. */
3110 return brl_lock_windows_default(br_lck, plock);
3113 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
3114 struct byte_range_lock *br_lck,
3115 const struct lock_struct *plock)
3117 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3119 return brl_unlock_windows_default(br_lck, plock);
3122 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
3124 struct lock_struct *plock)
3126 SMB_ASSERT(plock->lock_type == READ_LOCK ||
3127 plock->lock_type == WRITE_LOCK);
3129 return strict_lock_check_default(fsp, plock);
3132 /* NT ACL operations. */
3134 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
3136 uint32_t security_info,
3137 TALLOC_CTX *mem_ctx,
3138 struct security_descriptor **ppdesc)
3142 START_PROFILE(fget_nt_acl);
3143 result = posix_fget_nt_acl(fsp, security_info,
3145 END_PROFILE(fget_nt_acl);
3149 static NTSTATUS vfswrap_get_nt_acl_at(vfs_handle_struct *handle,
3150 struct files_struct *dirfsp,
3151 const struct smb_filename *smb_fname,
3152 uint32_t security_info,
3153 TALLOC_CTX *mem_ctx,
3154 struct security_descriptor **ppdesc)
3158 START_PROFILE(get_nt_acl_at);
3160 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
3162 result = posix_get_nt_acl(handle->conn,
3167 END_PROFILE(get_nt_acl_at);
3171 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
3175 START_PROFILE(fset_nt_acl);
3176 result = set_nt_acl(fsp, security_info_sent, psd);
3177 END_PROFILE(fset_nt_acl);
3181 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
3182 struct smb_filename *file,
3183 struct security_acl *sacl,
3184 uint32_t access_requested,
3185 uint32_t access_denied)
3187 return NT_STATUS_OK; /* Nothing to do here ... */
3190 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
3191 const struct smb_filename *smb_fname,
3192 SMB_ACL_TYPE_T type,
3193 TALLOC_CTX *mem_ctx)
3195 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
3198 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
3200 TALLOC_CTX *mem_ctx)
3202 return sys_acl_get_fd(handle, fsp, mem_ctx);
3205 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle,
3207 SMB_ACL_TYPE_T type,
3210 if (!fsp->fsp_flags.is_pathref &&
3211 type == SMB_ACL_TYPE_ACCESS)
3213 return sys_acl_set_fd(handle, fsp, theacl);
3216 if (fsp->fsp_flags.have_proc_fds) {
3217 int fd = fsp_get_pathref_fd(fsp);
3218 struct smb_filename smb_fname;
3219 const char *p = NULL;
3222 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3227 smb_fname = (struct smb_filename) {
3231 return sys_acl_set_file(handle,
3238 * This is no longer a handle based call.
3240 return sys_acl_set_file(handle,
3246 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
3247 const struct smb_filename *smb_fname)
3249 return sys_acl_delete_def_file(handle, smb_fname);
3252 /****************************************************************
3253 Extended attribute operations.
3254 *****************************************************************/
3256 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
3257 const struct smb_filename *smb_fname,
3262 return getxattr(smb_fname->base_name, name, value, size);
3265 struct vfswrap_getxattrat_state {
3266 struct tevent_context *ev;
3267 files_struct *dir_fsp;
3268 const struct smb_filename *smb_fname;
3271 * The following variables are talloced off "state" which is protected
3272 * by a destructor and thus are guaranteed to be safe to be used in the
3273 * job function in the worker thread.
3276 const char *xattr_name;
3277 uint8_t *xattr_value;
3278 struct security_unix_token *token;
3281 struct vfs_aio_state vfs_aio_state;
3282 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
3285 static int vfswrap_getxattrat_state_destructor(
3286 struct vfswrap_getxattrat_state *state)
3291 static void vfswrap_getxattrat_do_sync(struct tevent_req *req);
3292 static void vfswrap_getxattrat_do_async(void *private_data);
3293 static void vfswrap_getxattrat_done(struct tevent_req *subreq);
3295 static struct tevent_req *vfswrap_getxattrat_send(
3296 TALLOC_CTX *mem_ctx,
3297 struct tevent_context *ev,
3298 struct vfs_handle_struct *handle,
3299 files_struct *dir_fsp,
3300 const struct smb_filename *smb_fname,
3301 const char *xattr_name,
3304 struct tevent_req *req = NULL;
3305 struct tevent_req *subreq = NULL;
3306 struct vfswrap_getxattrat_state *state = NULL;
3307 size_t max_threads = 0;
3308 bool have_per_thread_cwd = false;
3309 bool have_per_thread_creds = false;
3310 bool do_async = false;
3312 req = tevent_req_create(mem_ctx, &state,
3313 struct vfswrap_getxattrat_state);
3317 *state = (struct vfswrap_getxattrat_state) {
3320 .smb_fname = smb_fname,
3323 max_threads = pthreadpool_tevent_max_threads(dir_fsp->conn->sconn->pool);
3324 if (max_threads >= 1) {
3326 * We need a non sync threadpool!
3328 have_per_thread_cwd = per_thread_cwd_supported();
3330 #ifdef HAVE_LINUX_THREAD_CREDENTIALS
3331 have_per_thread_creds = true;
3333 if (have_per_thread_cwd && have_per_thread_creds) {
3337 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat, profile_p,
3338 state->profile_bytes, 0);
3340 if (fsp_get_pathref_fd(dir_fsp) == -1) {
3341 DBG_ERR("Need a valid directory fd\n");
3342 tevent_req_error(req, EINVAL);
3343 return tevent_req_post(req, ev);
3346 if (alloc_hint > 0) {
3347 state->xattr_value = talloc_zero_array(state,
3350 if (tevent_req_nomem(state->xattr_value, req)) {
3351 return tevent_req_post(req, ev);
3356 vfswrap_getxattrat_do_sync(req);
3357 return tevent_req_post(req, ev);
3361 * Now allocate all parameters from a memory context that won't go away
3362 * no matter what. These paremeters will get used in threads and we
3363 * can't reliably cancel threads, so all buffers passed to the threads
3364 * must not be freed before all referencing threads terminate.
3367 state->name = talloc_strdup(state, smb_fname->base_name);
3368 if (tevent_req_nomem(state->name, req)) {
3369 return tevent_req_post(req, ev);
3372 state->xattr_name = talloc_strdup(state, xattr_name);
3373 if (tevent_req_nomem(state->xattr_name, req)) {
3374 return tevent_req_post(req, ev);
3378 * This is a hot codepath so at first glance one might think we should
3379 * somehow optimize away the token allocation and do a
3380 * talloc_reference() or similar black magic instead. But due to the
3381 * talloc_stackframe pool per SMB2 request this should be a simple copy
3382 * without a malloc in most cases.
3384 if (geteuid() == sec_initial_uid()) {
3385 state->token = root_unix_token(state);
3387 state->token = copy_unix_token(
3389 dir_fsp->conn->session_info->unix_token);
3391 if (tevent_req_nomem(state->token, req)) {
3392 return tevent_req_post(req, ev);
3395 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3397 subreq = pthreadpool_tevent_job_send(
3400 dir_fsp->conn->sconn->pool,
3401 vfswrap_getxattrat_do_async,
3403 if (tevent_req_nomem(subreq, req)) {
3404 return tevent_req_post(req, ev);
3406 tevent_req_set_callback(subreq, vfswrap_getxattrat_done, req);
3408 talloc_set_destructor(state, vfswrap_getxattrat_state_destructor);
3413 static void vfswrap_getxattrat_do_sync(struct tevent_req *req)
3415 struct vfswrap_getxattrat_state *state = tevent_req_data(
3416 req, struct vfswrap_getxattrat_state);
3418 char *tofree = NULL;
3419 char pathbuf[PATH_MAX+1];
3423 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
3424 state->smb_fname->base_name,
3429 if (pathlen == -1) {
3430 tevent_req_error(req, ENOMEM);
3434 state->xattr_size = getxattr(path,
3437 talloc_array_length(state->xattr_value));
3439 TALLOC_FREE(tofree);
3440 if (state->xattr_size == -1) {
3441 tevent_req_error(req, err);
3445 tevent_req_done(req);
3449 static void vfswrap_getxattrat_do_async(void *private_data)
3451 struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3452 private_data, struct vfswrap_getxattrat_state);
3453 struct timespec start_time;
3454 struct timespec end_time;
3457 PROFILE_TIMESTAMP(&start_time);
3458 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
3461 * Here we simulate a getxattrat()
3462 * call using fchdir();getxattr()
3465 per_thread_cwd_activate();
3467 /* Become the correct credential on this thread. */
3468 ret = set_thread_credentials(state->token->uid,
3470 (size_t)state->token->ngroups,
3471 state->token->groups);
3473 state->xattr_size = -1;
3474 state->vfs_aio_state.error = errno;
3478 ret = fchdir(fsp_get_pathref_fd(state->dir_fsp));
3480 state->xattr_size = -1;
3481 state->vfs_aio_state.error = errno;
3485 state->xattr_size = getxattr(state->name,
3488 talloc_array_length(state->xattr_value));
3489 if (state->xattr_size == -1) {
3490 state->vfs_aio_state.error = errno;
3494 PROFILE_TIMESTAMP(&end_time);
3495 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
3496 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3499 static void vfswrap_getxattrat_done(struct tevent_req *subreq)
3501 struct tevent_req *req = tevent_req_callback_data(
3502 subreq, struct tevent_req);
3503 struct vfswrap_getxattrat_state *state = tevent_req_data(
3504 req, struct vfswrap_getxattrat_state);
3509 * Make sure we run as the user again
3511 ok = change_to_user_and_service_by_fsp(state->dir_fsp);
3514 ret = pthreadpool_tevent_job_recv(subreq);
3515 TALLOC_FREE(subreq);
3516 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
3517 talloc_set_destructor(state, NULL);
3519 if (ret != EAGAIN) {
3520 tevent_req_error(req, ret);
3524 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
3525 * means the lower level pthreadpool failed to create a new
3526 * thread. Fallback to sync processing in that case to allow
3527 * some progress for the client.
3529 vfswrap_getxattrat_do_sync(req);
3533 if (state->xattr_size == -1) {
3534 tevent_req_error(req, state->vfs_aio_state.error);
3538 if (state->xattr_value == NULL) {
3540 * The caller only wanted the size.
3542 tevent_req_done(req);
3547 * shrink the buffer to the returned size.
3548 * (can't fail). It means NULL if size is 0.
3550 state->xattr_value = talloc_realloc(state,
3555 tevent_req_done(req);
3558 static ssize_t vfswrap_getxattrat_recv(struct tevent_req *req,
3559 struct vfs_aio_state *aio_state,
3560 TALLOC_CTX *mem_ctx,
3561 uint8_t **xattr_value)
3563 struct vfswrap_getxattrat_state *state = tevent_req_data(
3564 req, struct vfswrap_getxattrat_state);
3567 if (tevent_req_is_unix_error(req, &aio_state->error)) {
3568 tevent_req_received(req);
3572 *aio_state = state->vfs_aio_state;
3573 xattr_size = state->xattr_size;
3574 if (xattr_value != NULL) {
3575 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
3578 tevent_req_received(req);
3582 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle,
3583 struct files_struct *fsp,
3588 int fd = fsp_get_pathref_fd(fsp);
3590 if (!fsp->fsp_flags.is_pathref) {
3591 return fgetxattr(fd, name, value, size);
3594 if (fsp->fsp_flags.have_proc_fds) {
3595 const char *p = NULL;
3598 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3603 return getxattr(p, name, value, size);
3607 * This is no longer a handle based call.
3609 return getxattr(fsp->fsp_name->base_name, name, value, size);
3612 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
3614 int fd = fsp_get_pathref_fd(fsp);
3616 if (!fsp->fsp_flags.is_pathref) {
3617 return flistxattr(fd, list, size);
3620 if (fsp->fsp_flags.have_proc_fds) {
3621 const char *p = NULL;
3624 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3629 return listxattr(p, list, size);
3633 * This is no longer a handle based call.
3635 return listxattr(fsp->fsp_name->base_name, list, size);
3638 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
3640 int fd = fsp_get_pathref_fd(fsp);
3642 if (!fsp->fsp_flags.is_pathref) {
3643 return fremovexattr(fd, name);
3646 if (fsp->fsp_flags.have_proc_fds) {
3647 const char *p = NULL;
3650 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3655 return removexattr(p, name);
3659 * This is no longer a handle based call.
3661 return removexattr(fsp->fsp_name->base_name, name);
3664 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
3666 int fd = fsp_get_pathref_fd(fsp);
3668 if (!fsp->fsp_flags.is_pathref) {
3669 return fsetxattr(fd, name, value, size, flags);
3672 if (fsp->fsp_flags.have_proc_fds) {
3673 const char *p = NULL;
3676 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3681 return setxattr(p, name, value, size, flags);
3685 * This is no longer a handle based call.
3687 return setxattr(fsp->fsp_name->base_name, name, value, size, flags);
3690 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
3695 static bool vfswrap_is_offline(struct connection_struct *conn,
3696 const struct smb_filename *fname)
3700 bool offline = false;
3702 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
3706 if (!lp_dmapi_support(SNUM(conn)) || !dmapi_have_session()) {
3707 #if defined(ENOTSUP)
3713 status = get_full_smb_filename(talloc_tos(), fname, &path);
3714 if (!NT_STATUS_IS_OK(status)) {
3715 errno = map_errno_from_nt_status(status);
3719 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
3726 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
3727 struct files_struct *fsp,
3728 TALLOC_CTX *mem_ctx,
3731 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
3734 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
3735 struct files_struct *fsp,
3736 const DATA_BLOB old_cookie,
3737 TALLOC_CTX *mem_ctx,
3738 DATA_BLOB *new_cookie)
3740 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
3744 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
3745 struct smb_request *smb1req,
3746 struct smbXsrv_open *op,
3747 const DATA_BLOB old_cookie,
3748 TALLOC_CTX *mem_ctx,
3749 struct files_struct **fsp,
3750 DATA_BLOB *new_cookie)
3752 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
3753 old_cookie, mem_ctx,
3757 static struct vfs_fn_pointers vfs_default_fns = {
3758 /* Disk operations */
3760 .connect_fn = vfswrap_connect,
3761 .disconnect_fn = vfswrap_disconnect,
3762 .disk_free_fn = vfswrap_disk_free,
3763 .get_quota_fn = vfswrap_get_quota,
3764 .set_quota_fn = vfswrap_set_quota,
3765 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3766 .statvfs_fn = vfswrap_statvfs,
3767 .fs_capabilities_fn = vfswrap_fs_capabilities,
3768 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3769 .create_dfs_pathat_fn = vfswrap_create_dfs_pathat,
3770 .read_dfs_pathat_fn = vfswrap_read_dfs_pathat,
3771 .snap_check_path_fn = vfswrap_snap_check_path,
3772 .snap_create_fn = vfswrap_snap_create,
3773 .snap_delete_fn = vfswrap_snap_delete,
3775 /* Directory operations */
3777 .fdopendir_fn = vfswrap_fdopendir,
3778 .readdir_fn = vfswrap_readdir,
3779 .readdir_attr_fn = vfswrap_readdir_attr,
3780 .freaddir_attr_fn = vfswrap_freaddir_attr,
3781 .seekdir_fn = vfswrap_seekdir,
3782 .telldir_fn = vfswrap_telldir,
3783 .rewind_dir_fn = vfswrap_rewinddir,
3784 .mkdirat_fn = vfswrap_mkdirat,
3785 .closedir_fn = vfswrap_closedir,
3787 /* File operations */
3789 .openat_fn = vfswrap_openat,
3790 .create_file_fn = vfswrap_create_file,
3791 .close_fn = vfswrap_close,
3792 .pread_fn = vfswrap_pread,
3793 .pread_send_fn = vfswrap_pread_send,
3794 .pread_recv_fn = vfswrap_pread_recv,
3795 .pwrite_fn = vfswrap_pwrite,
3796 .pwrite_send_fn = vfswrap_pwrite_send,
3797 .pwrite_recv_fn = vfswrap_pwrite_recv,
3798 .lseek_fn = vfswrap_lseek,
3799 .sendfile_fn = vfswrap_sendfile,
3800 .recvfile_fn = vfswrap_recvfile,
3801 .renameat_fn = vfswrap_renameat,
3802 .fsync_send_fn = vfswrap_fsync_send,
3803 .fsync_recv_fn = vfswrap_fsync_recv,
3804 .stat_fn = vfswrap_stat,
3805 .fstat_fn = vfswrap_fstat,
3806 .lstat_fn = vfswrap_lstat,
3807 .get_alloc_size_fn = vfswrap_get_alloc_size,
3808 .unlinkat_fn = vfswrap_unlinkat,
3809 .fchmod_fn = vfswrap_fchmod,
3810 .fchown_fn = vfswrap_fchown,
3811 .lchown_fn = vfswrap_lchown,
3812 .chdir_fn = vfswrap_chdir,
3813 .getwd_fn = vfswrap_getwd,
3814 .fntimes_fn = vfswrap_fntimes,
3815 .ftruncate_fn = vfswrap_ftruncate,
3816 .fallocate_fn = vfswrap_fallocate,
3817 .lock_fn = vfswrap_lock,
3818 .kernel_flock_fn = vfswrap_kernel_flock,
3819 .fcntl_fn = vfswrap_fcntl,
3820 .linux_setlease_fn = vfswrap_linux_setlease,
3821 .getlock_fn = vfswrap_getlock,
3822 .symlinkat_fn = vfswrap_symlinkat,
3823 .readlinkat_fn = vfswrap_readlinkat,
3824 .linkat_fn = vfswrap_linkat,
3825 .mknodat_fn = vfswrap_mknodat,
3826 .realpath_fn = vfswrap_realpath,
3827 .chflags_fn = vfswrap_chflags,
3828 .file_id_create_fn = vfswrap_file_id_create,
3829 .fs_file_id_fn = vfswrap_fs_file_id,
3830 .fstreaminfo_fn = vfswrap_fstreaminfo,
3831 .get_real_filename_fn = vfswrap_get_real_filename,
3832 .connectpath_fn = vfswrap_connectpath,
3833 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
3834 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3835 .strict_lock_check_fn = vfswrap_strict_lock_check,
3836 .translate_name_fn = vfswrap_translate_name,
3837 .fsctl_fn = vfswrap_fsctl,
3838 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
3839 .get_dos_attributes_send_fn = vfswrap_get_dos_attributes_send,
3840 .get_dos_attributes_recv_fn = vfswrap_get_dos_attributes_recv,
3841 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
3842 .offload_read_send_fn = vfswrap_offload_read_send,
3843 .offload_read_recv_fn = vfswrap_offload_read_recv,
3844 .offload_write_send_fn = vfswrap_offload_write_send,
3845 .offload_write_recv_fn = vfswrap_offload_write_recv,
3846 .fget_compression_fn = vfswrap_fget_compression,
3847 .set_compression_fn = vfswrap_set_compression,
3849 /* NT ACL operations. */
3851 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
3852 .get_nt_acl_at_fn = vfswrap_get_nt_acl_at,
3853 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
3854 .audit_file_fn = vfswrap_audit_file,
3856 /* POSIX ACL operations. */
3858 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
3859 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3860 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
3861 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3862 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3863 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
3865 /* EA operations. */
3866 .getxattr_fn = vfswrap_getxattr,
3867 .getxattrat_send_fn = vfswrap_getxattrat_send,
3868 .getxattrat_recv_fn = vfswrap_getxattrat_recv,
3869 .fgetxattr_fn = vfswrap_fgetxattr,
3870 .flistxattr_fn = vfswrap_flistxattr,
3871 .fremovexattr_fn = vfswrap_fremovexattr,
3872 .fsetxattr_fn = vfswrap_fsetxattr,
3874 /* aio operations */
3875 .aio_force_fn = vfswrap_aio_force,
3877 /* durable handle operations */
3878 .durable_cookie_fn = vfswrap_durable_cookie,
3879 .durable_disconnect_fn = vfswrap_durable_disconnect,
3880 .durable_reconnect_fn = vfswrap_durable_reconnect,
3884 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3887 * Here we need to implement every call!
3889 * As this is the end of the vfs module chain.
3891 smb_vfs_assert_all_fns(&vfs_default_fns, DEFAULT_VFS_MODULE_NAME);
3892 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3893 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);