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,
674 START_PROFILE(syscall_mkdirat);
676 result = mkdirat(fsp_get_pathref_fd(dirfsp), smb_fname->base_name, mode);
678 END_PROFILE(syscall_mkdirat);
682 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
686 START_PROFILE(syscall_closedir);
687 result = closedir(dirp);
688 END_PROFILE(syscall_closedir);
692 /* File operations */
694 static int vfswrap_openat(vfs_handle_struct *handle,
695 const struct files_struct *dirfsp,
696 const struct smb_filename *smb_fname,
701 bool have_opath = false;
702 bool became_root = false;
705 START_PROFILE(syscall_openat);
707 if (is_named_stream(smb_fname)) {
715 if (fsp->fsp_flags.is_pathref) {
720 if (fsp->fsp_flags.is_pathref && !have_opath) {
725 result = openat(fsp_get_pathref_fd(dirfsp),
726 smb_fname->base_name,
734 fsp->fsp_flags.have_proc_fds = fsp->conn->have_proc_fds;
737 END_PROFILE(syscall_openat);
740 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
741 struct smb_request *req,
742 struct smb_filename *smb_fname,
743 uint32_t access_mask,
744 uint32_t share_access,
745 uint32_t create_disposition,
746 uint32_t create_options,
747 uint32_t file_attributes,
748 uint32_t oplock_request,
749 const struct smb2_lease *lease,
750 uint64_t allocation_size,
751 uint32_t private_flags,
752 struct security_descriptor *sd,
753 struct ea_list *ea_list,
754 files_struct **result,
756 const struct smb2_create_blobs *in_context_blobs,
757 struct smb2_create_blobs *out_context_blobs)
759 return create_file_default(handle->conn, req, smb_fname,
760 access_mask, share_access,
761 create_disposition, create_options,
762 file_attributes, oplock_request, lease,
763 allocation_size, private_flags,
765 pinfo, in_context_blobs, out_context_blobs);
768 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
772 START_PROFILE(syscall_close);
773 result = fd_close_posix(fsp);
774 END_PROFILE(syscall_close);
778 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
779 size_t n, off_t offset)
783 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
784 START_PROFILE_BYTES(syscall_pread, n);
785 result = sys_pread_full(fsp_get_io_fd(fsp), data, n, offset);
786 END_PROFILE_BYTES(syscall_pread);
788 if (result == -1 && errno == ESPIPE) {
789 /* Maintain the fiction that pipes can be seeked (sought?) on. */
790 result = sys_read(fsp_get_io_fd(fsp), data, n);
791 fh_set_pos(fsp->fh, 0);
794 #else /* HAVE_PREAD */
797 #endif /* HAVE_PREAD */
802 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
803 size_t n, off_t offset)
807 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
808 START_PROFILE_BYTES(syscall_pwrite, n);
809 result = sys_pwrite_full(fsp_get_io_fd(fsp), data, n, offset);
810 END_PROFILE_BYTES(syscall_pwrite);
812 if (result == -1 && errno == ESPIPE) {
813 /* Maintain the fiction that pipes can be sought on. */
814 result = sys_write(fsp_get_io_fd(fsp), data, n);
817 #else /* HAVE_PWRITE */
820 #endif /* HAVE_PWRITE */
825 struct vfswrap_pread_state {
832 struct vfs_aio_state vfs_aio_state;
833 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
836 static void vfs_pread_do(void *private_data);
837 static void vfs_pread_done(struct tevent_req *subreq);
838 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state);
840 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
842 struct tevent_context *ev,
843 struct files_struct *fsp,
845 size_t n, off_t offset)
847 struct tevent_req *req, *subreq;
848 struct vfswrap_pread_state *state;
850 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
856 state->fd = fsp_get_io_fd(fsp);
859 state->offset = offset;
861 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
862 state->profile_bytes, n);
863 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
865 subreq = pthreadpool_tevent_job_send(
866 state, ev, handle->conn->sconn->pool,
867 vfs_pread_do, state);
868 if (tevent_req_nomem(subreq, req)) {
869 return tevent_req_post(req, ev);
871 tevent_req_set_callback(subreq, vfs_pread_done, req);
873 talloc_set_destructor(state, vfs_pread_state_destructor);
878 static void vfs_pread_do(void *private_data)
880 struct vfswrap_pread_state *state = talloc_get_type_abort(
881 private_data, struct vfswrap_pread_state);
882 struct timespec start_time;
883 struct timespec end_time;
885 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
887 PROFILE_TIMESTAMP(&start_time);
889 state->ret = sys_pread_full(state->fd,
894 if (state->ret == -1) {
895 state->vfs_aio_state.error = errno;
898 PROFILE_TIMESTAMP(&end_time);
900 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
902 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
905 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state)
910 static void vfs_pread_done(struct tevent_req *subreq)
912 struct tevent_req *req = tevent_req_callback_data(
913 subreq, struct tevent_req);
914 struct vfswrap_pread_state *state = tevent_req_data(
915 req, struct vfswrap_pread_state);
918 ret = pthreadpool_tevent_job_recv(subreq);
920 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
921 talloc_set_destructor(state, NULL);
924 tevent_req_error(req, ret);
928 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
929 * means the lower level pthreadpool failed to create a new
930 * thread. Fallback to sync processing in that case to allow
931 * some progress for the client.
936 tevent_req_done(req);
939 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
940 struct vfs_aio_state *vfs_aio_state)
942 struct vfswrap_pread_state *state = tevent_req_data(
943 req, struct vfswrap_pread_state);
945 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
949 *vfs_aio_state = state->vfs_aio_state;
953 struct vfswrap_pwrite_state {
960 struct vfs_aio_state vfs_aio_state;
961 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
964 static void vfs_pwrite_do(void *private_data);
965 static void vfs_pwrite_done(struct tevent_req *subreq);
966 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state);
968 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
970 struct tevent_context *ev,
971 struct files_struct *fsp,
973 size_t n, off_t offset)
975 struct tevent_req *req, *subreq;
976 struct vfswrap_pwrite_state *state;
978 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
984 state->fd = fsp_get_io_fd(fsp);
987 state->offset = offset;
989 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
990 state->profile_bytes, n);
991 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
993 subreq = pthreadpool_tevent_job_send(
994 state, ev, handle->conn->sconn->pool,
995 vfs_pwrite_do, state);
996 if (tevent_req_nomem(subreq, req)) {
997 return tevent_req_post(req, ev);
999 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
1001 talloc_set_destructor(state, vfs_pwrite_state_destructor);
1006 static void vfs_pwrite_do(void *private_data)
1008 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
1009 private_data, struct vfswrap_pwrite_state);
1010 struct timespec start_time;
1011 struct timespec end_time;
1013 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
1015 PROFILE_TIMESTAMP(&start_time);
1017 state->ret = sys_pwrite_full(state->fd,
1022 if (state->ret == -1) {
1023 state->vfs_aio_state.error = errno;
1026 PROFILE_TIMESTAMP(&end_time);
1028 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1030 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1033 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state)
1038 static void vfs_pwrite_done(struct tevent_req *subreq)
1040 struct tevent_req *req = tevent_req_callback_data(
1041 subreq, struct tevent_req);
1042 struct vfswrap_pwrite_state *state = tevent_req_data(
1043 req, struct vfswrap_pwrite_state);
1046 ret = pthreadpool_tevent_job_recv(subreq);
1047 TALLOC_FREE(subreq);
1048 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1049 talloc_set_destructor(state, NULL);
1051 if (ret != EAGAIN) {
1052 tevent_req_error(req, ret);
1056 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1057 * means the lower level pthreadpool failed to create a new
1058 * thread. Fallback to sync processing in that case to allow
1059 * some progress for the client.
1061 vfs_pwrite_do(state);
1064 tevent_req_done(req);
1067 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
1068 struct vfs_aio_state *vfs_aio_state)
1070 struct vfswrap_pwrite_state *state = tevent_req_data(
1071 req, struct vfswrap_pwrite_state);
1073 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1077 *vfs_aio_state = state->vfs_aio_state;
1081 struct vfswrap_fsync_state {
1085 struct vfs_aio_state vfs_aio_state;
1086 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
1089 static void vfs_fsync_do(void *private_data);
1090 static void vfs_fsync_done(struct tevent_req *subreq);
1091 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state);
1093 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
1094 TALLOC_CTX *mem_ctx,
1095 struct tevent_context *ev,
1096 struct files_struct *fsp)
1098 struct tevent_req *req, *subreq;
1099 struct vfswrap_fsync_state *state;
1101 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
1107 state->fd = fsp_get_io_fd(fsp);
1109 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_fsync, profile_p,
1110 state->profile_bytes, 0);
1111 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1113 subreq = pthreadpool_tevent_job_send(
1114 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
1115 if (tevent_req_nomem(subreq, req)) {
1116 return tevent_req_post(req, ev);
1118 tevent_req_set_callback(subreq, vfs_fsync_done, req);
1120 talloc_set_destructor(state, vfs_fsync_state_destructor);
1125 static void vfs_fsync_do(void *private_data)
1127 struct vfswrap_fsync_state *state = talloc_get_type_abort(
1128 private_data, struct vfswrap_fsync_state);
1129 struct timespec start_time;
1130 struct timespec end_time;
1132 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
1134 PROFILE_TIMESTAMP(&start_time);
1137 state->ret = fsync(state->fd);
1138 } while ((state->ret == -1) && (errno == EINTR));
1140 if (state->ret == -1) {
1141 state->vfs_aio_state.error = errno;
1144 PROFILE_TIMESTAMP(&end_time);
1146 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1148 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1151 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state)
1156 static void vfs_fsync_done(struct tevent_req *subreq)
1158 struct tevent_req *req = tevent_req_callback_data(
1159 subreq, struct tevent_req);
1160 struct vfswrap_fsync_state *state = tevent_req_data(
1161 req, struct vfswrap_fsync_state);
1164 ret = pthreadpool_tevent_job_recv(subreq);
1165 TALLOC_FREE(subreq);
1166 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1167 talloc_set_destructor(state, NULL);
1169 if (ret != EAGAIN) {
1170 tevent_req_error(req, ret);
1174 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1175 * means the lower level pthreadpool failed to create a new
1176 * thread. Fallback to sync processing in that case to allow
1177 * some progress for the client.
1179 vfs_fsync_do(state);
1182 tevent_req_done(req);
1185 static int vfswrap_fsync_recv(struct tevent_req *req,
1186 struct vfs_aio_state *vfs_aio_state)
1188 struct vfswrap_fsync_state *state = tevent_req_data(
1189 req, struct vfswrap_fsync_state);
1191 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1195 *vfs_aio_state = state->vfs_aio_state;
1199 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1203 START_PROFILE(syscall_lseek);
1205 result = lseek(fsp_get_io_fd(fsp), offset, whence);
1207 * We want to maintain the fiction that we can seek
1208 * on a fifo for file system purposes. This allows
1209 * people to set up UNIX fifo's that feed data to Windows
1210 * applications. JRA.
1213 if((result == -1) && (errno == ESPIPE)) {
1218 END_PROFILE(syscall_lseek);
1222 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1223 off_t offset, size_t n)
1227 START_PROFILE_BYTES(syscall_sendfile, n);
1228 result = sys_sendfile(tofd, fsp_get_io_fd(fromfsp), hdr, offset, n);
1229 END_PROFILE_BYTES(syscall_sendfile);
1233 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1235 files_struct *tofsp,
1241 START_PROFILE_BYTES(syscall_recvfile, n);
1242 result = sys_recvfile(fromfd, fsp_get_io_fd(tofsp), offset, n);
1243 END_PROFILE_BYTES(syscall_recvfile);
1247 static int vfswrap_renameat(vfs_handle_struct *handle,
1248 files_struct *srcfsp,
1249 const struct smb_filename *smb_fname_src,
1250 files_struct *dstfsp,
1251 const struct smb_filename *smb_fname_dst)
1255 START_PROFILE(syscall_renameat);
1257 if (is_named_stream(smb_fname_src) || is_named_stream(smb_fname_dst)) {
1262 result = renameat(fsp_get_pathref_fd(srcfsp),
1263 smb_fname_src->base_name,
1264 fsp_get_pathref_fd(dstfsp),
1265 smb_fname_dst->base_name);
1268 END_PROFILE(syscall_renameat);
1272 static int vfswrap_stat(vfs_handle_struct *handle,
1273 struct smb_filename *smb_fname)
1277 START_PROFILE(syscall_stat);
1279 if (is_named_stream(smb_fname)) {
1284 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1285 lp_fake_directory_create_times(SNUM(handle->conn)));
1287 END_PROFILE(syscall_stat);
1291 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1295 START_PROFILE(syscall_fstat);
1296 result = sys_fstat(fsp_get_pathref_fd(fsp),
1297 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1298 END_PROFILE(syscall_fstat);
1302 static int vfswrap_lstat(vfs_handle_struct *handle,
1303 struct smb_filename *smb_fname)
1307 START_PROFILE(syscall_lstat);
1309 if (is_named_stream(smb_fname)) {
1314 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1315 lp_fake_directory_create_times(SNUM(handle->conn)));
1317 END_PROFILE(syscall_lstat);
1321 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1323 enum vfs_translate_direction direction,
1324 TALLOC_CTX *mem_ctx,
1327 return NT_STATUS_NONE_MAPPED;
1331 * Implement the default fsctl operation.
1333 static bool vfswrap_logged_ioctl_message = false;
1335 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1336 struct files_struct *fsp,
1339 uint16_t req_flags, /* Needed for UNICODE ... */
1340 const uint8_t *_in_data,
1342 uint8_t **_out_data,
1343 uint32_t max_out_len,
1346 const char *in_data = (const char *)_in_data;
1347 char **out_data = (char **)_out_data;
1351 case FSCTL_SET_SPARSE:
1353 bool set_sparse = true;
1355 if (in_len >= 1 && in_data[0] == 0) {
1359 status = file_set_sparse(handle->conn, fsp, set_sparse);
1361 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1362 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1363 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1364 nt_errstr(status)));
1369 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1371 unsigned char objid[16];
1372 char *return_data = NULL;
1374 /* This should return the object-id on this file.
1375 * I think I'll make this be the inode+dev. JRA.
1378 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1379 fsp_fnum_dbg(fsp)));
1381 *out_len = MIN(max_out_len, 64);
1383 /* Hmmm, will this cause problems if less data asked for? */
1384 return_data = talloc_array(ctx, char, 64);
1385 if (return_data == NULL) {
1386 return NT_STATUS_NO_MEMORY;
1389 /* For backwards compatibility only store the dev/inode. */
1390 push_file_id_16(return_data, &fsp->file_id);
1391 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1392 push_file_id_16(return_data+32, &fsp->file_id);
1393 memset(return_data+48, 0, 16);
1394 *out_data = return_data;
1395 return NT_STATUS_OK;
1398 case FSCTL_GET_REPARSE_POINT:
1400 status = fsctl_get_reparse_point(
1401 fsp, ctx, out_data, max_out_len, out_len);
1405 case FSCTL_SET_REPARSE_POINT:
1407 status = fsctl_set_reparse_point(fsp, ctx, _in_data, in_len);
1411 case FSCTL_DELETE_REPARSE_POINT:
1413 status = fsctl_del_reparse_point(fsp, ctx, _in_data, in_len);
1417 case FSCTL_GET_SHADOW_COPY_DATA:
1420 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1421 * and return their volume names. If max_data_count is 16, then it is just
1422 * asking for the number of volumes and length of the combined names.
1424 * pdata is the data allocated by our caller, but that uses
1425 * total_data_count (which is 0 in our case) rather than max_data_count.
1426 * Allocate the correct amount and return the pointer to let
1427 * it be deallocated when we return.
1429 struct shadow_copy_data *shadow_data = NULL;
1430 bool labels = False;
1431 uint32_t labels_data_count = 0;
1433 char *cur_pdata = NULL;
1435 if (max_out_len < 16) {
1436 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1438 return NT_STATUS_INVALID_PARAMETER;
1441 if (max_out_len > 16) {
1445 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1446 if (shadow_data == NULL) {
1447 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1448 return NT_STATUS_NO_MEMORY;
1452 * Call the VFS routine to actually do the work.
1454 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1457 /* broken module didn't set errno on error */
1458 status = NT_STATUS_UNSUCCESSFUL;
1460 status = map_nt_error_from_unix(errno);
1461 if (NT_STATUS_EQUAL(status,
1462 NT_STATUS_NOT_SUPPORTED)) {
1466 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1467 "connectpath %s, failed - %s.\n",
1468 fsp->conn->connectpath,
1469 nt_errstr(status)));
1470 TALLOC_FREE(shadow_data);
1474 labels_data_count = (shadow_data->num_volumes * 2 *
1475 sizeof(SHADOW_COPY_LABEL)) + 2;
1480 *out_len = 12 + labels_data_count;
1483 if (max_out_len < *out_len) {
1484 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1485 max_out_len, *out_len));
1486 TALLOC_FREE(shadow_data);
1487 return NT_STATUS_BUFFER_TOO_SMALL;
1490 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1491 if (cur_pdata == NULL) {
1492 TALLOC_FREE(shadow_data);
1493 return NT_STATUS_NO_MEMORY;
1496 *out_data = cur_pdata;
1498 /* num_volumes 4 bytes */
1499 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1502 /* num_labels 4 bytes */
1503 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1506 /* needed_data_count 4 bytes */
1507 SIVAL(cur_pdata, 8, labels_data_count);
1511 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1512 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1513 if (labels && shadow_data->labels) {
1514 for (i=0; i<shadow_data->num_volumes; i++) {
1516 status = srvstr_push(cur_pdata, req_flags,
1517 cur_pdata, shadow_data->labels[i],
1518 2 * sizeof(SHADOW_COPY_LABEL),
1519 STR_UNICODE|STR_TERMINATE, &len);
1520 if (!NT_STATUS_IS_OK(status)) {
1521 TALLOC_FREE(*out_data);
1522 TALLOC_FREE(shadow_data);
1525 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1526 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1530 TALLOC_FREE(shadow_data);
1532 return NT_STATUS_OK;
1535 case FSCTL_FIND_FILES_BY_SID:
1537 /* pretend this succeeded -
1539 * we have to send back a list with all files owned by this SID
1541 * but I have to check that --metze
1545 struct dom_sid_buf buf;
1549 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1550 fsp_fnum_dbg(fsp)));
1553 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1554 return NT_STATUS_INVALID_PARAMETER;
1557 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1559 /* unknown 4 bytes: this is not the length of the sid :-( */
1560 /*unknown = IVAL(pdata,0);*/
1562 ret = sid_parse(_in_data + 4, sid_len, &sid);
1564 return NT_STATUS_INVALID_PARAMETER;
1566 DEBUGADD(10, ("for SID: %s\n",
1567 dom_sid_str_buf(&sid, &buf)));
1569 if (!sid_to_uid(&sid, &uid)) {
1570 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1571 dom_sid_str_buf(&sid, &buf),
1572 (unsigned long)sid_len));
1576 /* we can take a look at the find source :-)
1578 * find ./ -uid $uid -name '*' is what we need here
1581 * and send 4bytes len and then NULL terminated unicode strings
1584 * but I don't know how to deal with the paged results
1585 * (maybe we can hang the result anywhere in the fsp struct)
1587 * but I don't know how to deal with the paged results
1588 * (maybe we can hang the result anywhere in the fsp struct)
1590 * we don't send all files at once
1591 * and at the next we should *not* start from the beginning,
1592 * so we have to cache the result
1597 /* this works for now... */
1598 return NT_STATUS_OK;
1601 case FSCTL_QUERY_ALLOCATED_RANGES:
1603 /* FIXME: This is just a dummy reply, telling that all of the
1604 * file is allocated. MKS cp needs that.
1605 * Adding the real allocated ranges via FIEMAP on Linux
1606 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1607 * this FSCTL correct for sparse files.
1609 uint64_t offset, length;
1610 char *out_data_tmp = NULL;
1613 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1615 return NT_STATUS_INVALID_PARAMETER;
1618 if (max_out_len < 16) {
1619 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1621 return NT_STATUS_INVALID_PARAMETER;
1624 offset = BVAL(in_data,0);
1625 length = BVAL(in_data,8);
1627 if (offset + length < offset) {
1628 /* No 64-bit integer wrap. */
1629 return NT_STATUS_INVALID_PARAMETER;
1632 /* Shouldn't this be SMB_VFS_STAT ... ? */
1633 status = vfs_stat_fsp(fsp);
1634 if (!NT_STATUS_IS_OK(status)) {
1639 out_data_tmp = talloc_array(ctx, char, *out_len);
1640 if (out_data_tmp == NULL) {
1641 DEBUG(10, ("unable to allocate memory for response\n"));
1642 return NT_STATUS_NO_MEMORY;
1645 if (offset > fsp->fsp_name->st.st_ex_size ||
1646 fsp->fsp_name->st.st_ex_size == 0 ||
1648 memset(out_data_tmp, 0, *out_len);
1650 uint64_t end = offset + length;
1651 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1652 SBVAL(out_data_tmp, 0, 0);
1653 SBVAL(out_data_tmp, 8, end);
1656 *out_data = out_data_tmp;
1658 return NT_STATUS_OK;
1661 case FSCTL_IS_VOLUME_DIRTY:
1663 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1664 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1666 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1667 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1669 return NT_STATUS_INVALID_PARAMETER;
1674 * Only print once ... unfortunately there could be lots of
1675 * different FSCTLs that are called.
1677 if (!vfswrap_logged_ioctl_message) {
1678 vfswrap_logged_ioctl_message = true;
1679 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1680 __func__, function));
1684 return NT_STATUS_NOT_SUPPORTED;
1687 static bool vfswrap_is_offline(struct connection_struct *conn,
1688 const struct smb_filename *fname);
1690 struct vfswrap_get_dos_attributes_state {
1691 struct vfs_aio_state aio_state;
1692 connection_struct *conn;
1693 TALLOC_CTX *mem_ctx;
1694 struct tevent_context *ev;
1695 files_struct *dir_fsp;
1696 struct smb_filename *smb_fname;
1701 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq);
1703 static struct tevent_req *vfswrap_get_dos_attributes_send(
1704 TALLOC_CTX *mem_ctx,
1705 struct tevent_context *ev,
1706 struct vfs_handle_struct *handle,
1707 files_struct *dir_fsp,
1708 struct smb_filename *smb_fname)
1710 struct tevent_req *req = NULL;
1711 struct tevent_req *subreq = NULL;
1712 struct vfswrap_get_dos_attributes_state *state = NULL;
1714 req = tevent_req_create(mem_ctx, &state,
1715 struct vfswrap_get_dos_attributes_state);
1720 *state = (struct vfswrap_get_dos_attributes_state) {
1721 .conn = dir_fsp->conn,
1725 .smb_fname = smb_fname,
1728 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1732 SAMBA_XATTR_DOS_ATTRIB,
1734 if (tevent_req_nomem(subreq, req)) {
1735 return tevent_req_post(req, ev);
1737 tevent_req_set_callback(subreq,
1738 vfswrap_get_dos_attributes_getxattr_done,
1744 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq)
1746 struct tevent_req *req =
1747 tevent_req_callback_data(subreq,
1749 struct vfswrap_get_dos_attributes_state *state =
1750 tevent_req_data(req,
1751 struct vfswrap_get_dos_attributes_state);
1753 DATA_BLOB blob = {0};
1755 char *tofree = NULL;
1756 char pathbuf[PATH_MAX+1];
1758 struct smb_filename smb_fname;
1762 xattr_size = SMB_VFS_GETXATTRAT_RECV(subreq,
1766 TALLOC_FREE(subreq);
1767 if (xattr_size == -1) {
1768 status = map_nt_error_from_unix(state->aio_state.error);
1770 if (state->as_root) {
1771 tevent_req_nterror(req, status);
1774 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1775 tevent_req_nterror(req, status);
1779 state->as_root = true;
1782 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1786 SAMBA_XATTR_DOS_ATTRIB,
1789 if (tevent_req_nomem(subreq, req)) {
1792 tevent_req_set_callback(subreq,
1793 vfswrap_get_dos_attributes_getxattr_done,
1798 blob.length = xattr_size;
1800 status = parse_dos_attribute_blob(state->smb_fname,
1803 if (!NT_STATUS_IS_OK(status)) {
1804 tevent_req_nterror(req, status);
1808 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
1809 state->smb_fname->base_name,
1814 if (pathlen == -1) {
1815 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1819 smb_fname = (struct smb_filename) {
1821 .st = state->smb_fname->st,
1822 .flags = state->smb_fname->flags,
1823 .twrp = state->smb_fname->twrp,
1826 offline = vfswrap_is_offline(state->conn, &smb_fname);
1828 state->dosmode |= FILE_ATTRIBUTE_OFFLINE;
1830 TALLOC_FREE(tofree);
1832 tevent_req_done(req);
1836 static NTSTATUS vfswrap_get_dos_attributes_recv(struct tevent_req *req,
1837 struct vfs_aio_state *aio_state,
1840 struct vfswrap_get_dos_attributes_state *state =
1841 tevent_req_data(req,
1842 struct vfswrap_get_dos_attributes_state);
1845 if (tevent_req_is_nterror(req, &status)) {
1846 tevent_req_received(req);
1850 *aio_state = state->aio_state;
1851 *dosmode = state->dosmode;
1852 tevent_req_received(req);
1853 return NT_STATUS_OK;
1856 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1857 struct files_struct *fsp,
1862 offline = vfswrap_is_offline(handle->conn, fsp->fsp_name);
1864 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1867 return fget_ea_dos_attribute(fsp, dosmode);
1870 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1871 const struct smb_filename *smb_fname,
1874 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1877 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1878 struct files_struct *fsp,
1881 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1884 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1886 struct vfswrap_offload_read_state {
1890 static struct tevent_req *vfswrap_offload_read_send(
1891 TALLOC_CTX *mem_ctx,
1892 struct tevent_context *ev,
1893 struct vfs_handle_struct *handle,
1894 struct files_struct *fsp,
1900 struct tevent_req *req = NULL;
1901 struct vfswrap_offload_read_state *state = NULL;
1904 req = tevent_req_create(mem_ctx, &state,
1905 struct vfswrap_offload_read_state);
1910 status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1911 &vfswrap_offload_ctx);
1912 if (tevent_req_nterror(req, status)) {
1913 return tevent_req_post(req, ev);
1916 if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1917 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1918 return tevent_req_post(req, ev);
1921 status = vfs_offload_token_create_blob(state, fsp, fsctl,
1923 if (tevent_req_nterror(req, status)) {
1924 return tevent_req_post(req, ev);
1927 status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1929 if (tevent_req_nterror(req, status)) {
1930 return tevent_req_post(req, ev);
1933 tevent_req_done(req);
1934 return tevent_req_post(req, ev);
1937 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
1938 struct vfs_handle_struct *handle,
1939 TALLOC_CTX *mem_ctx,
1942 struct vfswrap_offload_read_state *state = tevent_req_data(
1943 req, struct vfswrap_offload_read_state);
1946 if (tevent_req_is_nterror(req, &status)) {
1947 tevent_req_received(req);
1951 token->length = state->token.length;
1952 token->data = talloc_move(mem_ctx, &state->token.data);
1954 tevent_req_received(req);
1955 return NT_STATUS_OK;
1958 struct vfswrap_offload_write_state {
1960 bool read_lck_locked;
1961 bool write_lck_locked;
1963 struct tevent_context *src_ev;
1964 struct files_struct *src_fsp;
1966 struct tevent_context *dst_ev;
1967 struct files_struct *dst_fsp;
1971 size_t next_io_size;
1974 static void vfswrap_offload_write_cleanup(struct tevent_req *req,
1975 enum tevent_req_state req_state)
1977 struct vfswrap_offload_write_state *state = tevent_req_data(
1978 req, struct vfswrap_offload_write_state);
1981 if (state->dst_fsp == NULL) {
1985 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
1987 state->dst_fsp = NULL;
1990 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
1992 static struct tevent_req *vfswrap_offload_write_send(
1993 struct vfs_handle_struct *handle,
1994 TALLOC_CTX *mem_ctx,
1995 struct tevent_context *ev,
1998 off_t transfer_offset,
1999 struct files_struct *dest_fsp,
2003 struct tevent_req *req;
2004 struct vfswrap_offload_write_state *state = NULL;
2005 /* off_t is signed! */
2006 off_t max_offset = INT64_MAX - to_copy;
2007 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
2008 files_struct *src_fsp = NULL;
2012 req = tevent_req_create(mem_ctx, &state,
2013 struct vfswrap_offload_write_state);
2018 *state = (struct vfswrap_offload_write_state) {
2020 .src_off = transfer_offset,
2022 .dst_fsp = dest_fsp,
2023 .dst_off = dest_off,
2025 .remaining = to_copy,
2028 tevent_req_set_cleanup_fn(req, vfswrap_offload_write_cleanup);
2031 case FSCTL_SRV_COPYCHUNK:
2032 case FSCTL_SRV_COPYCHUNK_WRITE:
2035 case FSCTL_OFFLOAD_WRITE:
2036 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
2037 return tevent_req_post(req, ev);
2039 case FSCTL_DUP_EXTENTS_TO_FILE:
2040 DBG_DEBUG("COW clones not supported by vfs_default\n");
2041 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2042 return tevent_req_post(req, ev);
2045 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2046 return tevent_req_post(req, ev);
2050 * From here on we assume a copy-chunk fsctl
2054 tevent_req_done(req);
2055 return tevent_req_post(req, ev);
2058 if (state->src_off > max_offset) {
2060 * Protect integer checks below.
2062 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2063 return tevent_req_post(req, ev);
2065 if (state->src_off < 0) {
2067 * Protect integer checks below.
2069 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2070 return tevent_req_post(req, ev);
2072 if (state->dst_off > max_offset) {
2074 * Protect integer checks below.
2076 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2077 return tevent_req_post(req, ev);
2079 if (state->dst_off < 0) {
2081 * Protect integer checks below.
2083 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2084 return tevent_req_post(req, ev);
2087 status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
2089 if (tevent_req_nterror(req, status)) {
2090 return tevent_req_post(req, ev);
2093 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
2095 status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
2096 if (!NT_STATUS_IS_OK(status)) {
2097 tevent_req_nterror(req, status);
2098 return tevent_req_post(req, ev);
2101 ok = change_to_user_and_service_by_fsp(src_fsp);
2103 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2104 return tevent_req_post(req, ev);
2107 state->src_ev = src_fsp->conn->sconn->ev_ctx;
2108 state->src_fsp = src_fsp;
2110 status = vfs_stat_fsp(src_fsp);
2111 if (tevent_req_nterror(req, status)) {
2112 return tevent_req_post(req, ev);
2115 if (src_fsp->fsp_name->st.st_ex_size < state->src_off + to_copy) {
2117 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
2118 * If the SourceOffset or SourceOffset + Length extends beyond
2119 * the end of file, the server SHOULD<240> treat this as a
2120 * STATUS_END_OF_FILE error.
2122 * <240> Section 3.3.5.15.6: Windows servers will return
2123 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
2125 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
2126 return tevent_req_post(req, ev);
2129 state->buf = talloc_array(state, uint8_t, num);
2130 if (tevent_req_nomem(state->buf, req)) {
2131 return tevent_req_post(req, ev);
2134 status = vfswrap_offload_write_loop(req);
2135 if (!NT_STATUS_IS_OK(status)) {
2136 tevent_req_nterror(req, status);
2137 return tevent_req_post(req, ev);
2143 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
2145 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
2147 struct vfswrap_offload_write_state *state = tevent_req_data(
2148 req, struct vfswrap_offload_write_state);
2149 struct tevent_req *subreq = NULL;
2150 struct lock_struct read_lck;
2154 * This is called under the context of state->src_fsp.
2157 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
2159 init_strict_lock_struct(state->src_fsp,
2160 state->src_fsp->op->global->open_persistent_id,
2162 state->next_io_size,
2166 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
2170 return NT_STATUS_FILE_LOCK_CONFLICT;
2173 subreq = SMB_VFS_PREAD_SEND(state,
2177 state->next_io_size,
2179 if (subreq == NULL) {
2180 return NT_STATUS_NO_MEMORY;
2182 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
2184 return NT_STATUS_OK;
2187 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
2189 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
2191 struct tevent_req *req = tevent_req_callback_data(
2192 subreq, struct tevent_req);
2193 struct vfswrap_offload_write_state *state = tevent_req_data(
2194 req, struct vfswrap_offload_write_state);
2195 struct vfs_aio_state aio_state;
2196 struct lock_struct write_lck;
2200 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
2201 TALLOC_FREE(subreq);
2203 DBG_ERR("read failed: %s\n", strerror(aio_state.error));
2204 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2207 if (nread != state->next_io_size) {
2208 DBG_ERR("Short read, only %zd of %zu\n",
2209 nread, state->next_io_size);
2210 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2214 state->src_off += nread;
2216 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2218 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2222 init_strict_lock_struct(state->dst_fsp,
2223 state->dst_fsp->op->global->open_persistent_id,
2225 state->next_io_size,
2229 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
2233 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
2237 subreq = SMB_VFS_PWRITE_SEND(state,
2241 state->next_io_size,
2243 if (subreq == NULL) {
2244 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2247 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
2250 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
2252 struct tevent_req *req = tevent_req_callback_data(
2253 subreq, struct tevent_req);
2254 struct vfswrap_offload_write_state *state = tevent_req_data(
2255 req, struct vfswrap_offload_write_state);
2256 struct vfs_aio_state aio_state;
2261 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
2262 TALLOC_FREE(subreq);
2263 if (nwritten == -1) {
2264 DBG_ERR("write failed: %s\n", strerror(aio_state.error));
2265 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2268 if (nwritten != state->next_io_size) {
2269 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
2270 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2274 state->dst_off += nwritten;
2276 if (state->remaining < nwritten) {
2277 /* Paranoia check */
2278 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2281 state->remaining -= nwritten;
2282 if (state->remaining == 0) {
2283 tevent_req_done(req);
2287 ok = change_to_user_and_service_by_fsp(state->src_fsp);
2289 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2293 status = vfswrap_offload_write_loop(req);
2294 if (!NT_STATUS_IS_OK(status)) {
2295 tevent_req_nterror(req, status);
2302 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
2303 struct tevent_req *req,
2306 struct vfswrap_offload_write_state *state = tevent_req_data(
2307 req, struct vfswrap_offload_write_state);
2310 if (tevent_req_is_nterror(req, &status)) {
2311 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
2313 tevent_req_received(req);
2317 *copied = state->to_copy;
2318 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
2319 tevent_req_received(req);
2321 return NT_STATUS_OK;
2324 static NTSTATUS vfswrap_fget_compression(struct vfs_handle_struct *handle,
2325 TALLOC_CTX *mem_ctx,
2326 struct files_struct *fsp,
2327 uint16_t *_compression_fmt)
2329 return NT_STATUS_INVALID_DEVICE_REQUEST;
2332 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
2333 TALLOC_CTX *mem_ctx,
2334 struct files_struct *fsp,
2335 uint16_t compression_fmt)
2337 return NT_STATUS_INVALID_DEVICE_REQUEST;
2340 /********************************************************************
2341 Given a stat buffer return the allocated size on disk, taking into
2342 account sparse files.
2343 ********************************************************************/
2344 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
2345 struct files_struct *fsp,
2346 const SMB_STRUCT_STAT *sbuf)
2350 START_PROFILE(syscall_get_alloc_size);
2352 if(S_ISDIR(sbuf->st_ex_mode)) {
2357 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2358 /* The type of st_blocksize is blkcnt_t which *MUST* be
2359 signed (according to POSIX) and can be less than 64-bits.
2360 Ensure when we're converting to 64 bits wide we don't
2362 #if defined(SIZEOF_BLKCNT_T_8)
2363 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2364 #elif defined(SIZEOF_BLKCNT_T_4)
2366 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2367 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2370 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2374 * Some file systems do not allocate a block for very
2375 * small files. But for non-empty file should report a
2379 uint64_t filesize = get_file_size_stat(sbuf);
2381 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2385 result = get_file_size_stat(sbuf);
2388 if (fsp && fsp->initial_allocation_size)
2389 result = MAX(result,fsp->initial_allocation_size);
2391 result = smb_roundup(handle->conn, result);
2394 END_PROFILE(syscall_get_alloc_size);
2398 static int vfswrap_unlinkat(vfs_handle_struct *handle,
2399 struct files_struct *dirfsp,
2400 const struct smb_filename *smb_fname,
2405 START_PROFILE(syscall_unlinkat);
2407 if (is_named_stream(smb_fname)) {
2411 result = unlinkat(fsp_get_pathref_fd(dirfsp),
2412 smb_fname->base_name,
2416 END_PROFILE(syscall_unlinkat);
2420 static int vfswrap_chmod(vfs_handle_struct *handle,
2421 const struct smb_filename *smb_fname,
2426 START_PROFILE(syscall_chmod);
2427 result = chmod(smb_fname->base_name, mode);
2428 END_PROFILE(syscall_chmod);
2432 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2436 START_PROFILE(syscall_fchmod);
2437 #if defined(HAVE_FCHMOD)
2438 result = fchmod(fsp_get_io_fd(fsp), mode);
2444 END_PROFILE(syscall_fchmod);
2448 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2453 START_PROFILE(syscall_fchown);
2454 result = fchown(fsp_get_io_fd(fsp), uid, gid);
2455 END_PROFILE(syscall_fchown);
2463 static int vfswrap_lchown(vfs_handle_struct *handle,
2464 const struct smb_filename *smb_fname,
2470 START_PROFILE(syscall_lchown);
2471 result = lchown(smb_fname->base_name, uid, gid);
2472 END_PROFILE(syscall_lchown);
2476 static int vfswrap_chdir(vfs_handle_struct *handle,
2477 const struct smb_filename *smb_fname)
2481 START_PROFILE(syscall_chdir);
2482 result = chdir(smb_fname->base_name);
2483 END_PROFILE(syscall_chdir);
2487 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2491 struct smb_filename *smb_fname = NULL;
2493 START_PROFILE(syscall_getwd);
2494 result = sys_getwd();
2495 END_PROFILE(syscall_getwd);
2497 if (result == NULL) {
2500 smb_fname = synthetic_smb_fname(ctx,
2507 * sys_getwd() *always* returns malloced memory.
2508 * We must free here to avoid leaks:
2509 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2515 /*********************************************************************
2516 nsec timestamp resolution call. Convert down to whatever the underlying
2517 system will support.
2518 **********************************************************************/
2520 static int vfswrap_ntimes(vfs_handle_struct *handle,
2521 const struct smb_filename *smb_fname,
2522 struct smb_file_time *ft)
2526 START_PROFILE(syscall_ntimes);
2528 if (is_named_stream(smb_fname)) {
2534 if (is_omit_timespec(&ft->atime)) {
2535 ft->atime= smb_fname->st.st_ex_atime;
2538 if (is_omit_timespec(&ft->mtime)) {
2539 ft->mtime = smb_fname->st.st_ex_mtime;
2542 if (!is_omit_timespec(&ft->create_time)) {
2543 set_create_timespec_ea(handle->conn,
2548 if ((timespec_compare(&ft->atime,
2549 &smb_fname->st.st_ex_atime) == 0) &&
2550 (timespec_compare(&ft->mtime,
2551 &smb_fname->st.st_ex_mtime) == 0)) {
2556 #if defined(HAVE_UTIMENSAT)
2558 struct timespec ts[2];
2561 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2563 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2565 if (!((result == -1) && (errno == ENOSYS))) {
2569 #if defined(HAVE_UTIMES)
2571 struct timeval tv[2];
2572 tv[0] = convert_timespec_to_timeval(ft->atime);
2573 tv[1] = convert_timespec_to_timeval(ft->mtime);
2574 result = utimes(smb_fname->base_name, tv);
2576 result = utimes(smb_fname->base_name, NULL);
2578 if (!((result == -1) && (errno == ENOSYS))) {
2582 #if defined(HAVE_UTIME)
2584 struct utimbuf times;
2585 times.actime = convert_timespec_to_time_t(ft->atime);
2586 times.modtime = convert_timespec_to_time_t(ft->mtime);
2587 result = utime(smb_fname->base_name, ×);
2589 result = utime(smb_fname->base_name, NULL);
2591 if (!((result == -1) && (errno == ENOSYS))) {
2599 END_PROFILE(syscall_ntimes);
2603 /*********************************************************************
2604 A version of ftruncate that will write the space on disk if strict
2606 **********************************************************************/
2608 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2610 off_t space_to_write;
2611 uint64_t space_avail;
2612 uint64_t bsize,dfree,dsize;
2615 SMB_STRUCT_STAT *pst;
2618 ok = vfs_valid_pwrite_range(len, 0);
2624 status = vfs_stat_fsp(fsp);
2625 if (!NT_STATUS_IS_OK(status)) {
2628 pst = &fsp->fsp_name->st;
2631 if (S_ISFIFO(pst->st_ex_mode))
2635 if (pst->st_ex_size == len)
2638 /* Shrink - just ftruncate. */
2639 if (pst->st_ex_size > len)
2640 return ftruncate(fsp_get_io_fd(fsp), len);
2642 space_to_write = len - pst->st_ex_size;
2644 /* for allocation try fallocate first. This can fail on some
2645 platforms e.g. when the filesystem doesn't support it and no
2646 emulation is being done by the libc (like on AIX with JFS1). In that
2647 case we do our own emulation. fallocate implementations can
2648 return ENOTSUP or EINVAL in cases like that. */
2649 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2650 if (ret == -1 && errno == ENOSPC) {
2656 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2657 "error %d. Falling back to slow manual allocation\n", errno));
2659 /* available disk space is enough or not? */
2661 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2662 /* space_avail is 1k blocks */
2663 if (space_avail == (uint64_t)-1 ||
2664 ((uint64_t)space_to_write/1024 > space_avail) ) {
2669 /* Write out the real space on disk. */
2670 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2678 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2681 SMB_STRUCT_STAT *pst;
2685 START_PROFILE(syscall_ftruncate);
2687 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->fsp_flags.is_sparse) {
2688 result = strict_allocate_ftruncate(handle, fsp, len);
2689 END_PROFILE(syscall_ftruncate);
2693 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2694 ftruncate if the system supports it. Then I discovered that
2695 you can have some filesystems that support ftruncate
2696 expansion and some that don't! On Linux fat can't do
2697 ftruncate extend but ext2 can. */
2699 result = ftruncate(fsp_get_io_fd(fsp), len);
2701 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2702 extend a file with ftruncate. Provide alternate implementation
2705 /* Do an fstat to see if the file is longer than the requested
2706 size in which case the ftruncate above should have
2707 succeeded or shorter, in which case seek to len - 1 and
2708 write 1 byte of zero */
2709 status = vfs_stat_fsp(fsp);
2710 if (!NT_STATUS_IS_OK(status)) {
2714 /* We need to update the files_struct after successful ftruncate */
2719 pst = &fsp->fsp_name->st;
2722 if (S_ISFIFO(pst->st_ex_mode)) {
2728 if (pst->st_ex_size == len) {
2733 if (pst->st_ex_size > len) {
2734 /* the ftruncate should have worked */
2738 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2746 END_PROFILE(syscall_ftruncate);
2750 static int vfswrap_fallocate(vfs_handle_struct *handle,
2758 START_PROFILE(syscall_fallocate);
2760 result = sys_posix_fallocate(fsp_get_io_fd(fsp), offset, len);
2762 * posix_fallocate returns 0 on success, errno on error
2763 * and doesn't set errno. Make it behave like fallocate()
2764 * which returns -1, and sets errno on failure.
2771 /* sys_fallocate handles filtering of unsupported mode flags */
2772 result = sys_fallocate(fsp_get_io_fd(fsp), mode, offset, len);
2774 END_PROFILE(syscall_fallocate);
2778 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2782 START_PROFILE(syscall_fcntl_lock);
2784 if (fsp->fsp_flags.use_ofd_locks) {
2785 op = map_process_lock_to_ofd_lock(op);
2788 result = fcntl_lock(fsp_get_io_fd(fsp), op, offset, count, type);
2789 END_PROFILE(syscall_fcntl_lock);
2793 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2794 uint32_t share_access, uint32_t access_mask)
2796 START_PROFILE(syscall_kernel_flock);
2797 kernel_flock(fsp_get_io_fd(fsp), share_access, access_mask);
2798 END_PROFILE(syscall_kernel_flock);
2802 static int vfswrap_fcntl(vfs_handle_struct *handle, files_struct *fsp, int cmd,
2806 va_list dup_cmd_arg;
2810 START_PROFILE(syscall_fcntl);
2812 va_copy(dup_cmd_arg, cmd_arg);
2818 #if defined(HAVE_OFD_LOCKS)
2823 #if defined(HAVE_F_OWNER_EX)
2827 #if defined(HAVE_RW_HINTS)
2830 case F_GET_FILE_RW_HINT:
2831 case F_SET_FILE_RW_HINT:
2833 argp = va_arg(dup_cmd_arg, void *);
2834 result = sys_fcntl_ptr(fsp_get_io_fd(fsp), cmd, argp);
2837 val = va_arg(dup_cmd_arg, int);
2838 result = sys_fcntl_int(fsp_get_io_fd(fsp), cmd, val);
2841 va_end(dup_cmd_arg);
2843 END_PROFILE(syscall_fcntl);
2847 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2852 START_PROFILE(syscall_fcntl_getlock);
2854 if (fsp->fsp_flags.use_ofd_locks) {
2855 op = map_process_lock_to_ofd_lock(op);
2858 result = fcntl_getlock(fsp_get_io_fd(fsp), op, poffset, pcount, ptype, ppid);
2859 END_PROFILE(syscall_fcntl_getlock);
2863 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2868 START_PROFILE(syscall_linux_setlease);
2870 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2871 result = linux_setlease(fsp_get_io_fd(fsp), leasetype);
2875 END_PROFILE(syscall_linux_setlease);
2879 static int vfswrap_symlinkat(vfs_handle_struct *handle,
2880 const struct smb_filename *link_target,
2881 struct files_struct *dirfsp,
2882 const struct smb_filename *new_smb_fname)
2886 START_PROFILE(syscall_symlinkat);
2888 result = symlinkat(link_target->base_name,
2889 fsp_get_pathref_fd(dirfsp),
2890 new_smb_fname->base_name);
2891 END_PROFILE(syscall_symlinkat);
2895 static int vfswrap_readlinkat(vfs_handle_struct *handle,
2896 const struct files_struct *dirfsp,
2897 const struct smb_filename *smb_fname,
2903 START_PROFILE(syscall_readlinkat);
2905 result = readlinkat(fsp_get_pathref_fd(dirfsp),
2906 smb_fname->base_name,
2910 END_PROFILE(syscall_readlinkat);
2914 static int vfswrap_linkat(vfs_handle_struct *handle,
2915 files_struct *srcfsp,
2916 const struct smb_filename *old_smb_fname,
2917 files_struct *dstfsp,
2918 const struct smb_filename *new_smb_fname,
2923 START_PROFILE(syscall_linkat);
2925 result = linkat(fsp_get_pathref_fd(srcfsp),
2926 old_smb_fname->base_name,
2927 fsp_get_pathref_fd(dstfsp),
2928 new_smb_fname->base_name,
2931 END_PROFILE(syscall_linkat);
2935 static int vfswrap_mknodat(vfs_handle_struct *handle,
2936 files_struct *dirfsp,
2937 const struct smb_filename *smb_fname,
2943 START_PROFILE(syscall_mknodat);
2945 result = sys_mknodat(fsp_get_pathref_fd(dirfsp),
2946 smb_fname->base_name,
2950 END_PROFILE(syscall_mknodat);
2954 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2956 const struct smb_filename *smb_fname)
2959 struct smb_filename *result_fname = NULL;
2961 START_PROFILE(syscall_realpath);
2962 result = sys_realpath(smb_fname->base_name);
2963 END_PROFILE(syscall_realpath);
2965 result_fname = synthetic_smb_fname(ctx,
2973 return result_fname;
2976 static int vfswrap_chflags(vfs_handle_struct *handle,
2977 const struct smb_filename *smb_fname,
2981 return chflags(smb_fname->base_name, flags);
2988 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2989 const SMB_STRUCT_STAT *sbuf)
2993 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2997 key.devid = sbuf->st_ex_dev;
2998 key.inode = sbuf->st_ex_ino;
2999 /* key.extid is unused by default. */
3004 static uint64_t vfswrap_fs_file_id(struct vfs_handle_struct *handle,
3005 const SMB_STRUCT_STAT *psbuf)
3009 if (!(psbuf->st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)) {
3010 return psbuf->st_ex_file_id;
3013 if (handle->conn->base_share_dev == psbuf->st_ex_dev) {
3014 return (uint64_t)psbuf->st_ex_ino;
3018 file_id = ((psbuf->st_ex_ino) & UINT32_MAX);
3021 file_id |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32;
3026 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
3027 struct files_struct *fsp,
3028 const struct smb_filename *smb_fname,
3029 TALLOC_CTX *mem_ctx,
3030 unsigned int *pnum_streams,
3031 struct stream_struct **pstreams)
3033 SMB_STRUCT_STAT sbuf;
3034 struct stream_struct *tmp_streams = NULL;
3037 if ((fsp != NULL) && (fsp->fsp_flags.is_directory)) {
3039 * No default streams on directories
3044 if ((fsp != NULL) && (fsp_get_pathref_fd(fsp) != -1)) {
3045 ret = SMB_VFS_FSTAT(fsp, &sbuf);
3048 struct smb_filename *smb_fname_cp = NULL;
3050 smb_fname_cp = cp_smb_filename_nostream(talloc_tos(), smb_fname);
3051 if (smb_fname_cp == NULL) {
3052 return NT_STATUS_NO_MEMORY;
3055 ret = vfs_stat(handle->conn, smb_fname_cp);
3056 sbuf = smb_fname_cp->st;
3057 TALLOC_FREE(smb_fname_cp);
3061 return map_nt_error_from_unix(errno);
3064 if (S_ISDIR(sbuf.st_ex_mode)) {
3068 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
3069 (*pnum_streams) + 1);
3070 if (tmp_streams == NULL) {
3071 return NT_STATUS_NO_MEMORY;
3073 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
3074 if (tmp_streams[*pnum_streams].name == NULL) {
3075 return NT_STATUS_NO_MEMORY;
3077 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
3078 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
3081 *pstreams = tmp_streams;
3083 return NT_STATUS_OK;
3086 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
3087 const struct smb_filename *path,
3089 TALLOC_CTX *mem_ctx,
3093 * Don't fall back to get_real_filename so callers can differentiate
3094 * between a full directory scan and an actual case-insensitive stat.
3100 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
3101 const struct smb_filename *smb_fname)
3103 return handle->conn->connectpath;
3106 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
3107 struct byte_range_lock *br_lck,
3108 struct lock_struct *plock)
3110 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3112 /* Note: blr is not used in the default implementation. */
3113 return brl_lock_windows_default(br_lck, plock);
3116 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
3117 struct byte_range_lock *br_lck,
3118 const struct lock_struct *plock)
3120 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3122 return brl_unlock_windows_default(br_lck, plock);
3125 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
3127 struct lock_struct *plock)
3129 SMB_ASSERT(plock->lock_type == READ_LOCK ||
3130 plock->lock_type == WRITE_LOCK);
3132 return strict_lock_check_default(fsp, plock);
3135 /* NT ACL operations. */
3137 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
3139 uint32_t security_info,
3140 TALLOC_CTX *mem_ctx,
3141 struct security_descriptor **ppdesc)
3145 START_PROFILE(fget_nt_acl);
3146 result = posix_fget_nt_acl(fsp, security_info,
3148 END_PROFILE(fget_nt_acl);
3152 static NTSTATUS vfswrap_get_nt_acl_at(vfs_handle_struct *handle,
3153 struct files_struct *dirfsp,
3154 const struct smb_filename *smb_fname,
3155 uint32_t security_info,
3156 TALLOC_CTX *mem_ctx,
3157 struct security_descriptor **ppdesc)
3161 START_PROFILE(get_nt_acl_at);
3163 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
3165 result = posix_get_nt_acl(handle->conn,
3170 END_PROFILE(get_nt_acl_at);
3174 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
3178 START_PROFILE(fset_nt_acl);
3179 result = set_nt_acl(fsp, security_info_sent, psd);
3180 END_PROFILE(fset_nt_acl);
3184 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
3185 struct smb_filename *file,
3186 struct security_acl *sacl,
3187 uint32_t access_requested,
3188 uint32_t access_denied)
3190 return NT_STATUS_OK; /* Nothing to do here ... */
3193 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
3194 const struct smb_filename *smb_fname,
3195 SMB_ACL_TYPE_T type,
3196 TALLOC_CTX *mem_ctx)
3198 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
3201 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
3203 TALLOC_CTX *mem_ctx)
3205 return sys_acl_get_fd(handle, fsp, mem_ctx);
3208 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle,
3210 SMB_ACL_TYPE_T type,
3213 if (!fsp->fsp_flags.is_pathref &&
3214 type == SMB_ACL_TYPE_ACCESS)
3216 return sys_acl_set_fd(handle, fsp, theacl);
3219 if (fsp->fsp_flags.have_proc_fds) {
3220 int fd = fsp_get_pathref_fd(fsp);
3221 struct smb_filename smb_fname;
3222 const char *p = NULL;
3225 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3230 smb_fname = (struct smb_filename) {
3234 return sys_acl_set_file(handle,
3241 * This is no longer a handle based call.
3243 return sys_acl_set_file(handle,
3249 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
3250 const struct smb_filename *smb_fname)
3252 return sys_acl_delete_def_file(handle, smb_fname);
3255 /****************************************************************
3256 Extended attribute operations.
3257 *****************************************************************/
3259 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
3260 const struct smb_filename *smb_fname,
3265 return getxattr(smb_fname->base_name, name, value, size);
3268 struct vfswrap_getxattrat_state {
3269 struct tevent_context *ev;
3270 files_struct *dir_fsp;
3271 const struct smb_filename *smb_fname;
3274 * The following variables are talloced off "state" which is protected
3275 * by a destructor and thus are guaranteed to be safe to be used in the
3276 * job function in the worker thread.
3279 const char *xattr_name;
3280 uint8_t *xattr_value;
3281 struct security_unix_token *token;
3284 struct vfs_aio_state vfs_aio_state;
3285 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
3288 static int vfswrap_getxattrat_state_destructor(
3289 struct vfswrap_getxattrat_state *state)
3294 static void vfswrap_getxattrat_do_sync(struct tevent_req *req);
3295 static void vfswrap_getxattrat_do_async(void *private_data);
3296 static void vfswrap_getxattrat_done(struct tevent_req *subreq);
3298 static struct tevent_req *vfswrap_getxattrat_send(
3299 TALLOC_CTX *mem_ctx,
3300 struct tevent_context *ev,
3301 struct vfs_handle_struct *handle,
3302 files_struct *dir_fsp,
3303 const struct smb_filename *smb_fname,
3304 const char *xattr_name,
3307 struct tevent_req *req = NULL;
3308 struct tevent_req *subreq = NULL;
3309 struct vfswrap_getxattrat_state *state = NULL;
3310 size_t max_threads = 0;
3311 bool have_per_thread_cwd = false;
3312 bool have_per_thread_creds = false;
3313 bool do_async = false;
3315 req = tevent_req_create(mem_ctx, &state,
3316 struct vfswrap_getxattrat_state);
3320 *state = (struct vfswrap_getxattrat_state) {
3323 .smb_fname = smb_fname,
3326 max_threads = pthreadpool_tevent_max_threads(dir_fsp->conn->sconn->pool);
3327 if (max_threads >= 1) {
3329 * We need a non sync threadpool!
3331 have_per_thread_cwd = per_thread_cwd_supported();
3333 #ifdef HAVE_LINUX_THREAD_CREDENTIALS
3334 have_per_thread_creds = true;
3336 if (have_per_thread_cwd && have_per_thread_creds) {
3340 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat, profile_p,
3341 state->profile_bytes, 0);
3343 if (fsp_get_pathref_fd(dir_fsp) == -1) {
3344 DBG_ERR("Need a valid directory fd\n");
3345 tevent_req_error(req, EINVAL);
3346 return tevent_req_post(req, ev);
3349 if (alloc_hint > 0) {
3350 state->xattr_value = talloc_zero_array(state,
3353 if (tevent_req_nomem(state->xattr_value, req)) {
3354 return tevent_req_post(req, ev);
3359 vfswrap_getxattrat_do_sync(req);
3360 return tevent_req_post(req, ev);
3364 * Now allocate all parameters from a memory context that won't go away
3365 * no matter what. These paremeters will get used in threads and we
3366 * can't reliably cancel threads, so all buffers passed to the threads
3367 * must not be freed before all referencing threads terminate.
3370 state->name = talloc_strdup(state, smb_fname->base_name);
3371 if (tevent_req_nomem(state->name, req)) {
3372 return tevent_req_post(req, ev);
3375 state->xattr_name = talloc_strdup(state, xattr_name);
3376 if (tevent_req_nomem(state->xattr_name, req)) {
3377 return tevent_req_post(req, ev);
3381 * This is a hot codepath so at first glance one might think we should
3382 * somehow optimize away the token allocation and do a
3383 * talloc_reference() or similar black magic instead. But due to the
3384 * talloc_stackframe pool per SMB2 request this should be a simple copy
3385 * without a malloc in most cases.
3387 if (geteuid() == sec_initial_uid()) {
3388 state->token = root_unix_token(state);
3390 state->token = copy_unix_token(
3392 dir_fsp->conn->session_info->unix_token);
3394 if (tevent_req_nomem(state->token, req)) {
3395 return tevent_req_post(req, ev);
3398 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3400 subreq = pthreadpool_tevent_job_send(
3403 dir_fsp->conn->sconn->pool,
3404 vfswrap_getxattrat_do_async,
3406 if (tevent_req_nomem(subreq, req)) {
3407 return tevent_req_post(req, ev);
3409 tevent_req_set_callback(subreq, vfswrap_getxattrat_done, req);
3411 talloc_set_destructor(state, vfswrap_getxattrat_state_destructor);
3416 static void vfswrap_getxattrat_do_sync(struct tevent_req *req)
3418 struct vfswrap_getxattrat_state *state = tevent_req_data(
3419 req, struct vfswrap_getxattrat_state);
3421 char *tofree = NULL;
3422 char pathbuf[PATH_MAX+1];
3426 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
3427 state->smb_fname->base_name,
3432 if (pathlen == -1) {
3433 tevent_req_error(req, ENOMEM);
3437 state->xattr_size = getxattr(path,
3440 talloc_array_length(state->xattr_value));
3442 TALLOC_FREE(tofree);
3443 if (state->xattr_size == -1) {
3444 tevent_req_error(req, err);
3448 tevent_req_done(req);
3452 static void vfswrap_getxattrat_do_async(void *private_data)
3454 struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3455 private_data, struct vfswrap_getxattrat_state);
3456 struct timespec start_time;
3457 struct timespec end_time;
3460 PROFILE_TIMESTAMP(&start_time);
3461 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
3464 * Here we simulate a getxattrat()
3465 * call using fchdir();getxattr()
3468 per_thread_cwd_activate();
3470 /* Become the correct credential on this thread. */
3471 ret = set_thread_credentials(state->token->uid,
3473 (size_t)state->token->ngroups,
3474 state->token->groups);
3476 state->xattr_size = -1;
3477 state->vfs_aio_state.error = errno;
3481 ret = fchdir(fsp_get_pathref_fd(state->dir_fsp));
3483 state->xattr_size = -1;
3484 state->vfs_aio_state.error = errno;
3488 state->xattr_size = getxattr(state->name,
3491 talloc_array_length(state->xattr_value));
3492 if (state->xattr_size == -1) {
3493 state->vfs_aio_state.error = errno;
3497 PROFILE_TIMESTAMP(&end_time);
3498 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
3499 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3502 static void vfswrap_getxattrat_done(struct tevent_req *subreq)
3504 struct tevent_req *req = tevent_req_callback_data(
3505 subreq, struct tevent_req);
3506 struct vfswrap_getxattrat_state *state = tevent_req_data(
3507 req, struct vfswrap_getxattrat_state);
3512 * Make sure we run as the user again
3514 ok = change_to_user_and_service_by_fsp(state->dir_fsp);
3517 ret = pthreadpool_tevent_job_recv(subreq);
3518 TALLOC_FREE(subreq);
3519 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
3520 talloc_set_destructor(state, NULL);
3522 if (ret != EAGAIN) {
3523 tevent_req_error(req, ret);
3527 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
3528 * means the lower level pthreadpool failed to create a new
3529 * thread. Fallback to sync processing in that case to allow
3530 * some progress for the client.
3532 vfswrap_getxattrat_do_sync(req);
3536 if (state->xattr_size == -1) {
3537 tevent_req_error(req, state->vfs_aio_state.error);
3541 if (state->xattr_value == NULL) {
3543 * The caller only wanted the size.
3545 tevent_req_done(req);
3550 * shrink the buffer to the returned size.
3551 * (can't fail). It means NULL if size is 0.
3553 state->xattr_value = talloc_realloc(state,
3558 tevent_req_done(req);
3561 static ssize_t vfswrap_getxattrat_recv(struct tevent_req *req,
3562 struct vfs_aio_state *aio_state,
3563 TALLOC_CTX *mem_ctx,
3564 uint8_t **xattr_value)
3566 struct vfswrap_getxattrat_state *state = tevent_req_data(
3567 req, struct vfswrap_getxattrat_state);
3570 if (tevent_req_is_unix_error(req, &aio_state->error)) {
3571 tevent_req_received(req);
3575 *aio_state = state->vfs_aio_state;
3576 xattr_size = state->xattr_size;
3577 if (xattr_value != NULL) {
3578 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
3581 tevent_req_received(req);
3585 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle,
3586 struct files_struct *fsp,
3591 int fd = fsp_get_pathref_fd(fsp);
3593 if (!fsp->fsp_flags.is_pathref) {
3594 return fgetxattr(fd, name, value, size);
3597 if (fsp->fsp_flags.have_proc_fds) {
3598 const char *p = NULL;
3601 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3606 return getxattr(p, name, value, size);
3610 * This is no longer a handle based call.
3612 return getxattr(fsp->fsp_name->base_name, name, value, size);
3615 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
3617 int fd = fsp_get_pathref_fd(fsp);
3619 if (!fsp->fsp_flags.is_pathref) {
3620 return flistxattr(fd, list, 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 listxattr(p, list, size);
3636 * This is no longer a handle based call.
3638 return listxattr(fsp->fsp_name->base_name, list, size);
3641 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
3642 const struct smb_filename *smb_fname,
3645 return removexattr(smb_fname->base_name, name);
3648 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
3650 int fd = fsp_get_pathref_fd(fsp);
3652 if (!fsp->fsp_flags.is_pathref) {
3653 return fremovexattr(fd, name);
3656 if (fsp->fsp_flags.have_proc_fds) {
3657 const char *p = NULL;
3660 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3665 return removexattr(p, name);
3669 * This is no longer a handle based call.
3671 return removexattr(fsp->fsp_name->base_name, name);
3674 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
3675 const struct smb_filename *smb_fname,
3681 return setxattr(smb_fname->base_name, name, value, size, flags);
3684 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
3686 int fd = fsp_get_pathref_fd(fsp);
3688 if (!fsp->fsp_flags.is_pathref) {
3689 return fsetxattr(fd, name, value, size, flags);
3692 if (fsp->fsp_flags.have_proc_fds) {
3693 const char *p = NULL;
3696 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3701 return setxattr(p, name, value, size, flags);
3705 * This is no longer a handle based call.
3707 return setxattr(fsp->fsp_name->base_name, name, value, size, flags);
3710 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
3715 static bool vfswrap_is_offline(struct connection_struct *conn,
3716 const struct smb_filename *fname)
3720 bool offline = false;
3722 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
3726 if (!lp_dmapi_support(SNUM(conn)) || !dmapi_have_session()) {
3727 #if defined(ENOTSUP)
3733 status = get_full_smb_filename(talloc_tos(), fname, &path);
3734 if (!NT_STATUS_IS_OK(status)) {
3735 errno = map_errno_from_nt_status(status);
3739 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
3746 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
3747 struct files_struct *fsp,
3748 TALLOC_CTX *mem_ctx,
3751 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
3754 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
3755 struct files_struct *fsp,
3756 const DATA_BLOB old_cookie,
3757 TALLOC_CTX *mem_ctx,
3758 DATA_BLOB *new_cookie)
3760 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
3764 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
3765 struct smb_request *smb1req,
3766 struct smbXsrv_open *op,
3767 const DATA_BLOB old_cookie,
3768 TALLOC_CTX *mem_ctx,
3769 struct files_struct **fsp,
3770 DATA_BLOB *new_cookie)
3772 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
3773 old_cookie, mem_ctx,
3777 static struct vfs_fn_pointers vfs_default_fns = {
3778 /* Disk operations */
3780 .connect_fn = vfswrap_connect,
3781 .disconnect_fn = vfswrap_disconnect,
3782 .disk_free_fn = vfswrap_disk_free,
3783 .get_quota_fn = vfswrap_get_quota,
3784 .set_quota_fn = vfswrap_set_quota,
3785 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3786 .statvfs_fn = vfswrap_statvfs,
3787 .fs_capabilities_fn = vfswrap_fs_capabilities,
3788 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3789 .create_dfs_pathat_fn = vfswrap_create_dfs_pathat,
3790 .read_dfs_pathat_fn = vfswrap_read_dfs_pathat,
3791 .snap_check_path_fn = vfswrap_snap_check_path,
3792 .snap_create_fn = vfswrap_snap_create,
3793 .snap_delete_fn = vfswrap_snap_delete,
3795 /* Directory operations */
3797 .fdopendir_fn = vfswrap_fdopendir,
3798 .readdir_fn = vfswrap_readdir,
3799 .readdir_attr_fn = vfswrap_readdir_attr,
3800 .seekdir_fn = vfswrap_seekdir,
3801 .telldir_fn = vfswrap_telldir,
3802 .rewind_dir_fn = vfswrap_rewinddir,
3803 .mkdirat_fn = vfswrap_mkdirat,
3804 .closedir_fn = vfswrap_closedir,
3806 /* File operations */
3808 .openat_fn = vfswrap_openat,
3809 .create_file_fn = vfswrap_create_file,
3810 .close_fn = vfswrap_close,
3811 .pread_fn = vfswrap_pread,
3812 .pread_send_fn = vfswrap_pread_send,
3813 .pread_recv_fn = vfswrap_pread_recv,
3814 .pwrite_fn = vfswrap_pwrite,
3815 .pwrite_send_fn = vfswrap_pwrite_send,
3816 .pwrite_recv_fn = vfswrap_pwrite_recv,
3817 .lseek_fn = vfswrap_lseek,
3818 .sendfile_fn = vfswrap_sendfile,
3819 .recvfile_fn = vfswrap_recvfile,
3820 .renameat_fn = vfswrap_renameat,
3821 .fsync_send_fn = vfswrap_fsync_send,
3822 .fsync_recv_fn = vfswrap_fsync_recv,
3823 .stat_fn = vfswrap_stat,
3824 .fstat_fn = vfswrap_fstat,
3825 .lstat_fn = vfswrap_lstat,
3826 .get_alloc_size_fn = vfswrap_get_alloc_size,
3827 .unlinkat_fn = vfswrap_unlinkat,
3828 .chmod_fn = vfswrap_chmod,
3829 .fchmod_fn = vfswrap_fchmod,
3830 .fchown_fn = vfswrap_fchown,
3831 .lchown_fn = vfswrap_lchown,
3832 .chdir_fn = vfswrap_chdir,
3833 .getwd_fn = vfswrap_getwd,
3834 .ntimes_fn = vfswrap_ntimes,
3835 .ftruncate_fn = vfswrap_ftruncate,
3836 .fallocate_fn = vfswrap_fallocate,
3837 .lock_fn = vfswrap_lock,
3838 .kernel_flock_fn = vfswrap_kernel_flock,
3839 .fcntl_fn = vfswrap_fcntl,
3840 .linux_setlease_fn = vfswrap_linux_setlease,
3841 .getlock_fn = vfswrap_getlock,
3842 .symlinkat_fn = vfswrap_symlinkat,
3843 .readlinkat_fn = vfswrap_readlinkat,
3844 .linkat_fn = vfswrap_linkat,
3845 .mknodat_fn = vfswrap_mknodat,
3846 .realpath_fn = vfswrap_realpath,
3847 .chflags_fn = vfswrap_chflags,
3848 .file_id_create_fn = vfswrap_file_id_create,
3849 .fs_file_id_fn = vfswrap_fs_file_id,
3850 .streaminfo_fn = vfswrap_streaminfo,
3851 .get_real_filename_fn = vfswrap_get_real_filename,
3852 .connectpath_fn = vfswrap_connectpath,
3853 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
3854 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3855 .strict_lock_check_fn = vfswrap_strict_lock_check,
3856 .translate_name_fn = vfswrap_translate_name,
3857 .fsctl_fn = vfswrap_fsctl,
3858 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
3859 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
3860 .get_dos_attributes_send_fn = vfswrap_get_dos_attributes_send,
3861 .get_dos_attributes_recv_fn = vfswrap_get_dos_attributes_recv,
3862 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
3863 .offload_read_send_fn = vfswrap_offload_read_send,
3864 .offload_read_recv_fn = vfswrap_offload_read_recv,
3865 .offload_write_send_fn = vfswrap_offload_write_send,
3866 .offload_write_recv_fn = vfswrap_offload_write_recv,
3867 .fget_compression_fn = vfswrap_fget_compression,
3868 .set_compression_fn = vfswrap_set_compression,
3870 /* NT ACL operations. */
3872 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
3873 .get_nt_acl_at_fn = vfswrap_get_nt_acl_at,
3874 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
3875 .audit_file_fn = vfswrap_audit_file,
3877 /* POSIX ACL operations. */
3879 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
3880 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3881 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
3882 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3883 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3884 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
3886 /* EA operations. */
3887 .getxattr_fn = vfswrap_getxattr,
3888 .getxattrat_send_fn = vfswrap_getxattrat_send,
3889 .getxattrat_recv_fn = vfswrap_getxattrat_recv,
3890 .fgetxattr_fn = vfswrap_fgetxattr,
3891 .flistxattr_fn = vfswrap_flistxattr,
3892 .removexattr_fn = vfswrap_removexattr,
3893 .fremovexattr_fn = vfswrap_fremovexattr,
3894 .setxattr_fn = vfswrap_setxattr,
3895 .fsetxattr_fn = vfswrap_fsetxattr,
3897 /* aio operations */
3898 .aio_force_fn = vfswrap_aio_force,
3900 /* durable handle operations */
3901 .durable_cookie_fn = vfswrap_durable_cookie,
3902 .durable_disconnect_fn = vfswrap_durable_disconnect,
3903 .durable_reconnect_fn = vfswrap_durable_reconnect,
3907 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3910 * Here we need to implement every call!
3912 * As this is the end of the vfs module chain.
3914 smb_vfs_assert_all_fns(&vfs_default_fns, DEFAULT_VFS_MODULE_NAME);
3915 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3916 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);