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. Make the caller do it again as we don't know if
623 * they wanted the link info, or its target info.
625 if (S_ISLNK(st.st_mode)) {
628 init_stat_ex_from_stat(sbuf, &st, fake_ctime);
633 static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
634 const struct smb_filename *fname,
636 struct readdir_attr_data **attr_data)
638 return NT_STATUS_NOT_SUPPORTED;
641 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
643 START_PROFILE(syscall_seekdir);
644 seekdir(dirp, offset);
645 END_PROFILE(syscall_seekdir);
648 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
651 START_PROFILE(syscall_telldir);
652 result = telldir(dirp);
653 END_PROFILE(syscall_telldir);
657 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
659 START_PROFILE(syscall_rewinddir);
661 END_PROFILE(syscall_rewinddir);
664 static int vfswrap_mkdirat(vfs_handle_struct *handle,
665 struct files_struct *dirfsp,
666 const struct smb_filename *smb_fname,
670 struct smb_filename *parent = NULL;
673 START_PROFILE(syscall_mkdirat);
675 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
677 if (lp_inherit_acls(SNUM(handle->conn))) {
678 ok = parent_smb_fname(talloc_tos(), smb_fname, &parent, NULL);
679 if (ok && directory_has_default_acl(handle->conn,
683 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
689 result = mkdirat(fsp_get_pathref_fd(dirfsp), smb_fname->base_name, mode);
691 END_PROFILE(syscall_mkdirat);
695 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
699 START_PROFILE(syscall_closedir);
700 result = closedir(dirp);
701 END_PROFILE(syscall_closedir);
705 /* File operations */
707 static int vfswrap_openat(vfs_handle_struct *handle,
708 const struct files_struct *dirfsp,
709 const struct smb_filename *smb_fname,
714 bool have_opath = false;
715 bool became_root = false;
718 START_PROFILE(syscall_openat);
720 if (is_named_stream(smb_fname)) {
728 if (fsp->fsp_flags.is_pathref) {
733 if (fsp->fsp_flags.is_pathref && !have_opath) {
738 result = openat(fsp_get_pathref_fd(dirfsp),
739 smb_fname->base_name,
747 fsp->fsp_flags.have_proc_fds = fsp->conn->have_proc_fds;
750 END_PROFILE(syscall_openat);
753 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
754 struct smb_request *req,
755 struct smb_filename *smb_fname,
756 uint32_t access_mask,
757 uint32_t share_access,
758 uint32_t create_disposition,
759 uint32_t create_options,
760 uint32_t file_attributes,
761 uint32_t oplock_request,
762 const struct smb2_lease *lease,
763 uint64_t allocation_size,
764 uint32_t private_flags,
765 struct security_descriptor *sd,
766 struct ea_list *ea_list,
767 files_struct **result,
769 const struct smb2_create_blobs *in_context_blobs,
770 struct smb2_create_blobs *out_context_blobs)
772 return create_file_default(handle->conn, req, smb_fname,
773 access_mask, share_access,
774 create_disposition, create_options,
775 file_attributes, oplock_request, lease,
776 allocation_size, private_flags,
778 pinfo, in_context_blobs, out_context_blobs);
781 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
785 START_PROFILE(syscall_close);
786 result = fd_close_posix(fsp);
787 END_PROFILE(syscall_close);
791 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
792 size_t n, off_t offset)
796 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
797 START_PROFILE_BYTES(syscall_pread, n);
798 result = sys_pread_full(fsp_get_io_fd(fsp), data, n, offset);
799 END_PROFILE_BYTES(syscall_pread);
801 if (result == -1 && errno == ESPIPE) {
802 /* Maintain the fiction that pipes can be seeked (sought?) on. */
803 result = sys_read(fsp_get_io_fd(fsp), data, n);
804 fh_set_pos(fsp->fh, 0);
807 #else /* HAVE_PREAD */
810 #endif /* HAVE_PREAD */
815 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
816 size_t n, off_t offset)
820 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
821 START_PROFILE_BYTES(syscall_pwrite, n);
822 result = sys_pwrite_full(fsp_get_io_fd(fsp), data, n, offset);
823 END_PROFILE_BYTES(syscall_pwrite);
825 if (result == -1 && errno == ESPIPE) {
826 /* Maintain the fiction that pipes can be sought on. */
827 result = sys_write(fsp_get_io_fd(fsp), data, n);
830 #else /* HAVE_PWRITE */
833 #endif /* HAVE_PWRITE */
838 struct vfswrap_pread_state {
845 struct vfs_aio_state vfs_aio_state;
846 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
849 static void vfs_pread_do(void *private_data);
850 static void vfs_pread_done(struct tevent_req *subreq);
851 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state);
853 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
855 struct tevent_context *ev,
856 struct files_struct *fsp,
858 size_t n, off_t offset)
860 struct tevent_req *req, *subreq;
861 struct vfswrap_pread_state *state;
863 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
869 state->fd = fsp_get_io_fd(fsp);
872 state->offset = offset;
874 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
875 state->profile_bytes, n);
876 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
878 subreq = pthreadpool_tevent_job_send(
879 state, ev, handle->conn->sconn->pool,
880 vfs_pread_do, state);
881 if (tevent_req_nomem(subreq, req)) {
882 return tevent_req_post(req, ev);
884 tevent_req_set_callback(subreq, vfs_pread_done, req);
886 talloc_set_destructor(state, vfs_pread_state_destructor);
891 static void vfs_pread_do(void *private_data)
893 struct vfswrap_pread_state *state = talloc_get_type_abort(
894 private_data, struct vfswrap_pread_state);
895 struct timespec start_time;
896 struct timespec end_time;
898 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
900 PROFILE_TIMESTAMP(&start_time);
902 state->ret = sys_pread_full(state->fd,
907 if (state->ret == -1) {
908 state->vfs_aio_state.error = errno;
911 PROFILE_TIMESTAMP(&end_time);
913 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
915 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
918 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state)
923 static void vfs_pread_done(struct tevent_req *subreq)
925 struct tevent_req *req = tevent_req_callback_data(
926 subreq, struct tevent_req);
927 struct vfswrap_pread_state *state = tevent_req_data(
928 req, struct vfswrap_pread_state);
931 ret = pthreadpool_tevent_job_recv(subreq);
933 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
934 talloc_set_destructor(state, NULL);
937 tevent_req_error(req, ret);
941 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
942 * means the lower level pthreadpool failed to create a new
943 * thread. Fallback to sync processing in that case to allow
944 * some progress for the client.
949 tevent_req_done(req);
952 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
953 struct vfs_aio_state *vfs_aio_state)
955 struct vfswrap_pread_state *state = tevent_req_data(
956 req, struct vfswrap_pread_state);
958 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
962 *vfs_aio_state = state->vfs_aio_state;
966 struct vfswrap_pwrite_state {
973 struct vfs_aio_state vfs_aio_state;
974 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
977 static void vfs_pwrite_do(void *private_data);
978 static void vfs_pwrite_done(struct tevent_req *subreq);
979 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state);
981 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
983 struct tevent_context *ev,
984 struct files_struct *fsp,
986 size_t n, off_t offset)
988 struct tevent_req *req, *subreq;
989 struct vfswrap_pwrite_state *state;
991 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
997 state->fd = fsp_get_io_fd(fsp);
1000 state->offset = offset;
1002 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
1003 state->profile_bytes, n);
1004 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1006 subreq = pthreadpool_tevent_job_send(
1007 state, ev, handle->conn->sconn->pool,
1008 vfs_pwrite_do, state);
1009 if (tevent_req_nomem(subreq, req)) {
1010 return tevent_req_post(req, ev);
1012 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
1014 talloc_set_destructor(state, vfs_pwrite_state_destructor);
1019 static void vfs_pwrite_do(void *private_data)
1021 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
1022 private_data, struct vfswrap_pwrite_state);
1023 struct timespec start_time;
1024 struct timespec end_time;
1026 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
1028 PROFILE_TIMESTAMP(&start_time);
1030 state->ret = sys_pwrite_full(state->fd,
1035 if (state->ret == -1) {
1036 state->vfs_aio_state.error = errno;
1039 PROFILE_TIMESTAMP(&end_time);
1041 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1043 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1046 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state)
1051 static void vfs_pwrite_done(struct tevent_req *subreq)
1053 struct tevent_req *req = tevent_req_callback_data(
1054 subreq, struct tevent_req);
1055 struct vfswrap_pwrite_state *state = tevent_req_data(
1056 req, struct vfswrap_pwrite_state);
1059 ret = pthreadpool_tevent_job_recv(subreq);
1060 TALLOC_FREE(subreq);
1061 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1062 talloc_set_destructor(state, NULL);
1064 if (ret != EAGAIN) {
1065 tevent_req_error(req, ret);
1069 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1070 * means the lower level pthreadpool failed to create a new
1071 * thread. Fallback to sync processing in that case to allow
1072 * some progress for the client.
1074 vfs_pwrite_do(state);
1077 tevent_req_done(req);
1080 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
1081 struct vfs_aio_state *vfs_aio_state)
1083 struct vfswrap_pwrite_state *state = tevent_req_data(
1084 req, struct vfswrap_pwrite_state);
1086 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1090 *vfs_aio_state = state->vfs_aio_state;
1094 struct vfswrap_fsync_state {
1098 struct vfs_aio_state vfs_aio_state;
1099 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
1102 static void vfs_fsync_do(void *private_data);
1103 static void vfs_fsync_done(struct tevent_req *subreq);
1104 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state);
1106 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
1107 TALLOC_CTX *mem_ctx,
1108 struct tevent_context *ev,
1109 struct files_struct *fsp)
1111 struct tevent_req *req, *subreq;
1112 struct vfswrap_fsync_state *state;
1114 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
1120 state->fd = fsp_get_io_fd(fsp);
1122 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_fsync, profile_p,
1123 state->profile_bytes, 0);
1124 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1126 subreq = pthreadpool_tevent_job_send(
1127 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
1128 if (tevent_req_nomem(subreq, req)) {
1129 return tevent_req_post(req, ev);
1131 tevent_req_set_callback(subreq, vfs_fsync_done, req);
1133 talloc_set_destructor(state, vfs_fsync_state_destructor);
1138 static void vfs_fsync_do(void *private_data)
1140 struct vfswrap_fsync_state *state = talloc_get_type_abort(
1141 private_data, struct vfswrap_fsync_state);
1142 struct timespec start_time;
1143 struct timespec end_time;
1145 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
1147 PROFILE_TIMESTAMP(&start_time);
1150 state->ret = fsync(state->fd);
1151 } while ((state->ret == -1) && (errno == EINTR));
1153 if (state->ret == -1) {
1154 state->vfs_aio_state.error = errno;
1157 PROFILE_TIMESTAMP(&end_time);
1159 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1161 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1164 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state)
1169 static void vfs_fsync_done(struct tevent_req *subreq)
1171 struct tevent_req *req = tevent_req_callback_data(
1172 subreq, struct tevent_req);
1173 struct vfswrap_fsync_state *state = tevent_req_data(
1174 req, struct vfswrap_fsync_state);
1177 ret = pthreadpool_tevent_job_recv(subreq);
1178 TALLOC_FREE(subreq);
1179 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1180 talloc_set_destructor(state, NULL);
1182 if (ret != EAGAIN) {
1183 tevent_req_error(req, ret);
1187 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1188 * means the lower level pthreadpool failed to create a new
1189 * thread. Fallback to sync processing in that case to allow
1190 * some progress for the client.
1192 vfs_fsync_do(state);
1195 tevent_req_done(req);
1198 static int vfswrap_fsync_recv(struct tevent_req *req,
1199 struct vfs_aio_state *vfs_aio_state)
1201 struct vfswrap_fsync_state *state = tevent_req_data(
1202 req, struct vfswrap_fsync_state);
1204 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1208 *vfs_aio_state = state->vfs_aio_state;
1212 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1216 START_PROFILE(syscall_lseek);
1218 result = lseek(fsp_get_io_fd(fsp), offset, whence);
1220 * We want to maintain the fiction that we can seek
1221 * on a fifo for file system purposes. This allows
1222 * people to set up UNIX fifo's that feed data to Windows
1223 * applications. JRA.
1226 if((result == -1) && (errno == ESPIPE)) {
1231 END_PROFILE(syscall_lseek);
1235 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1236 off_t offset, size_t n)
1240 START_PROFILE_BYTES(syscall_sendfile, n);
1241 result = sys_sendfile(tofd, fsp_get_io_fd(fromfsp), hdr, offset, n);
1242 END_PROFILE_BYTES(syscall_sendfile);
1246 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1248 files_struct *tofsp,
1254 START_PROFILE_BYTES(syscall_recvfile, n);
1255 result = sys_recvfile(fromfd, fsp_get_io_fd(tofsp), offset, n);
1256 END_PROFILE_BYTES(syscall_recvfile);
1260 static int vfswrap_renameat(vfs_handle_struct *handle,
1261 files_struct *srcfsp,
1262 const struct smb_filename *smb_fname_src,
1263 files_struct *dstfsp,
1264 const struct smb_filename *smb_fname_dst)
1268 START_PROFILE(syscall_renameat);
1270 if (is_named_stream(smb_fname_src) || is_named_stream(smb_fname_dst)) {
1275 result = renameat(fsp_get_pathref_fd(srcfsp),
1276 smb_fname_src->base_name,
1277 fsp_get_pathref_fd(dstfsp),
1278 smb_fname_dst->base_name);
1281 END_PROFILE(syscall_renameat);
1285 static int vfswrap_stat(vfs_handle_struct *handle,
1286 struct smb_filename *smb_fname)
1290 START_PROFILE(syscall_stat);
1292 if (is_named_stream(smb_fname)) {
1297 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1298 lp_fake_directory_create_times(SNUM(handle->conn)));
1300 END_PROFILE(syscall_stat);
1304 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1308 START_PROFILE(syscall_fstat);
1309 result = sys_fstat(fsp_get_pathref_fd(fsp),
1310 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1311 END_PROFILE(syscall_fstat);
1315 static int vfswrap_lstat(vfs_handle_struct *handle,
1316 struct smb_filename *smb_fname)
1320 START_PROFILE(syscall_lstat);
1322 if (is_named_stream(smb_fname)) {
1327 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1328 lp_fake_directory_create_times(SNUM(handle->conn)));
1330 END_PROFILE(syscall_lstat);
1334 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1336 enum vfs_translate_direction direction,
1337 TALLOC_CTX *mem_ctx,
1340 return NT_STATUS_NONE_MAPPED;
1344 * Implement the default fsctl operation.
1346 static bool vfswrap_logged_ioctl_message = false;
1348 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1349 struct files_struct *fsp,
1352 uint16_t req_flags, /* Needed for UNICODE ... */
1353 const uint8_t *_in_data,
1355 uint8_t **_out_data,
1356 uint32_t max_out_len,
1359 const char *in_data = (const char *)_in_data;
1360 char **out_data = (char **)_out_data;
1364 case FSCTL_SET_SPARSE:
1366 bool set_sparse = true;
1368 if (in_len >= 1 && in_data[0] == 0) {
1372 status = file_set_sparse(handle->conn, fsp, set_sparse);
1374 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1375 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1376 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1377 nt_errstr(status)));
1382 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1384 unsigned char objid[16];
1385 char *return_data = NULL;
1387 /* This should return the object-id on this file.
1388 * I think I'll make this be the inode+dev. JRA.
1391 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1392 fsp_fnum_dbg(fsp)));
1394 *out_len = MIN(max_out_len, 64);
1396 /* Hmmm, will this cause problems if less data asked for? */
1397 return_data = talloc_array(ctx, char, 64);
1398 if (return_data == NULL) {
1399 return NT_STATUS_NO_MEMORY;
1402 /* For backwards compatibility only store the dev/inode. */
1403 push_file_id_16(return_data, &fsp->file_id);
1404 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1405 push_file_id_16(return_data+32, &fsp->file_id);
1406 memset(return_data+48, 0, 16);
1407 *out_data = return_data;
1408 return NT_STATUS_OK;
1411 case FSCTL_GET_REPARSE_POINT:
1413 status = fsctl_get_reparse_point(
1414 fsp, ctx, out_data, max_out_len, out_len);
1418 case FSCTL_SET_REPARSE_POINT:
1420 status = fsctl_set_reparse_point(fsp, ctx, _in_data, in_len);
1424 case FSCTL_DELETE_REPARSE_POINT:
1426 status = fsctl_del_reparse_point(fsp, ctx, _in_data, in_len);
1430 case FSCTL_GET_SHADOW_COPY_DATA:
1433 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1434 * and return their volume names. If max_data_count is 16, then it is just
1435 * asking for the number of volumes and length of the combined names.
1437 * pdata is the data allocated by our caller, but that uses
1438 * total_data_count (which is 0 in our case) rather than max_data_count.
1439 * Allocate the correct amount and return the pointer to let
1440 * it be deallocated when we return.
1442 struct shadow_copy_data *shadow_data = NULL;
1443 bool labels = False;
1444 uint32_t labels_data_count = 0;
1446 char *cur_pdata = NULL;
1448 if (max_out_len < 16) {
1449 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1451 return NT_STATUS_INVALID_PARAMETER;
1454 if (max_out_len > 16) {
1458 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1459 if (shadow_data == NULL) {
1460 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1461 return NT_STATUS_NO_MEMORY;
1465 * Call the VFS routine to actually do the work.
1467 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1470 /* broken module didn't set errno on error */
1471 status = NT_STATUS_UNSUCCESSFUL;
1473 status = map_nt_error_from_unix(errno);
1474 if (NT_STATUS_EQUAL(status,
1475 NT_STATUS_NOT_SUPPORTED)) {
1479 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1480 "connectpath %s, failed - %s.\n",
1481 fsp->conn->connectpath,
1482 nt_errstr(status)));
1483 TALLOC_FREE(shadow_data);
1487 labels_data_count = (shadow_data->num_volumes * 2 *
1488 sizeof(SHADOW_COPY_LABEL)) + 2;
1493 *out_len = 12 + labels_data_count;
1496 if (max_out_len < *out_len) {
1497 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1498 max_out_len, *out_len));
1499 TALLOC_FREE(shadow_data);
1500 return NT_STATUS_BUFFER_TOO_SMALL;
1503 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1504 if (cur_pdata == NULL) {
1505 TALLOC_FREE(shadow_data);
1506 return NT_STATUS_NO_MEMORY;
1509 *out_data = cur_pdata;
1511 /* num_volumes 4 bytes */
1512 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1515 /* num_labels 4 bytes */
1516 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1519 /* needed_data_count 4 bytes */
1520 SIVAL(cur_pdata, 8, labels_data_count);
1524 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1525 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1526 if (labels && shadow_data->labels) {
1527 for (i=0; i<shadow_data->num_volumes; i++) {
1529 status = srvstr_push(cur_pdata, req_flags,
1530 cur_pdata, shadow_data->labels[i],
1531 2 * sizeof(SHADOW_COPY_LABEL),
1532 STR_UNICODE|STR_TERMINATE, &len);
1533 if (!NT_STATUS_IS_OK(status)) {
1534 TALLOC_FREE(*out_data);
1535 TALLOC_FREE(shadow_data);
1538 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1539 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1543 TALLOC_FREE(shadow_data);
1545 return NT_STATUS_OK;
1548 case FSCTL_FIND_FILES_BY_SID:
1550 /* pretend this succeeded -
1552 * we have to send back a list with all files owned by this SID
1554 * but I have to check that --metze
1558 struct dom_sid_buf buf;
1562 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1563 fsp_fnum_dbg(fsp)));
1566 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1567 return NT_STATUS_INVALID_PARAMETER;
1570 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1572 /* unknown 4 bytes: this is not the length of the sid :-( */
1573 /*unknown = IVAL(pdata,0);*/
1575 ret = sid_parse(_in_data + 4, sid_len, &sid);
1577 return NT_STATUS_INVALID_PARAMETER;
1579 DEBUGADD(10, ("for SID: %s\n",
1580 dom_sid_str_buf(&sid, &buf)));
1582 if (!sid_to_uid(&sid, &uid)) {
1583 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1584 dom_sid_str_buf(&sid, &buf),
1585 (unsigned long)sid_len));
1589 /* we can take a look at the find source :-)
1591 * find ./ -uid $uid -name '*' is what we need here
1594 * and send 4bytes len and then NULL terminated unicode strings
1597 * but I don't know how to deal with the paged results
1598 * (maybe we can hang the result anywhere in the fsp struct)
1600 * but I don't know how to deal with the paged results
1601 * (maybe we can hang the result anywhere in the fsp struct)
1603 * we don't send all files at once
1604 * and at the next we should *not* start from the beginning,
1605 * so we have to cache the result
1610 /* this works for now... */
1611 return NT_STATUS_OK;
1614 case FSCTL_QUERY_ALLOCATED_RANGES:
1616 /* FIXME: This is just a dummy reply, telling that all of the
1617 * file is allocated. MKS cp needs that.
1618 * Adding the real allocated ranges via FIEMAP on Linux
1619 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1620 * this FSCTL correct for sparse files.
1622 uint64_t offset, length;
1623 char *out_data_tmp = NULL;
1626 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1628 return NT_STATUS_INVALID_PARAMETER;
1631 if (max_out_len < 16) {
1632 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1634 return NT_STATUS_INVALID_PARAMETER;
1637 offset = BVAL(in_data,0);
1638 length = BVAL(in_data,8);
1640 if (offset + length < offset) {
1641 /* No 64-bit integer wrap. */
1642 return NT_STATUS_INVALID_PARAMETER;
1645 /* Shouldn't this be SMB_VFS_STAT ... ? */
1646 status = vfs_stat_fsp(fsp);
1647 if (!NT_STATUS_IS_OK(status)) {
1652 out_data_tmp = talloc_array(ctx, char, *out_len);
1653 if (out_data_tmp == NULL) {
1654 DEBUG(10, ("unable to allocate memory for response\n"));
1655 return NT_STATUS_NO_MEMORY;
1658 if (offset > fsp->fsp_name->st.st_ex_size ||
1659 fsp->fsp_name->st.st_ex_size == 0 ||
1661 memset(out_data_tmp, 0, *out_len);
1663 uint64_t end = offset + length;
1664 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1665 SBVAL(out_data_tmp, 0, 0);
1666 SBVAL(out_data_tmp, 8, end);
1669 *out_data = out_data_tmp;
1671 return NT_STATUS_OK;
1674 case FSCTL_IS_VOLUME_DIRTY:
1676 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1677 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1679 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1680 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1682 return NT_STATUS_INVALID_PARAMETER;
1687 * Only print once ... unfortunately there could be lots of
1688 * different FSCTLs that are called.
1690 if (!vfswrap_logged_ioctl_message) {
1691 vfswrap_logged_ioctl_message = true;
1692 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1693 __func__, function));
1697 return NT_STATUS_NOT_SUPPORTED;
1700 static bool vfswrap_is_offline(struct connection_struct *conn,
1701 const struct smb_filename *fname);
1703 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1704 struct smb_filename *smb_fname,
1709 offline = vfswrap_is_offline(handle->conn, smb_fname);
1711 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1714 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1717 struct vfswrap_get_dos_attributes_state {
1718 struct vfs_aio_state aio_state;
1719 connection_struct *conn;
1720 TALLOC_CTX *mem_ctx;
1721 struct tevent_context *ev;
1722 files_struct *dir_fsp;
1723 struct smb_filename *smb_fname;
1728 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq);
1730 static struct tevent_req *vfswrap_get_dos_attributes_send(
1731 TALLOC_CTX *mem_ctx,
1732 struct tevent_context *ev,
1733 struct vfs_handle_struct *handle,
1734 files_struct *dir_fsp,
1735 struct smb_filename *smb_fname)
1737 struct tevent_req *req = NULL;
1738 struct tevent_req *subreq = NULL;
1739 struct vfswrap_get_dos_attributes_state *state = NULL;
1741 req = tevent_req_create(mem_ctx, &state,
1742 struct vfswrap_get_dos_attributes_state);
1747 *state = (struct vfswrap_get_dos_attributes_state) {
1748 .conn = dir_fsp->conn,
1752 .smb_fname = smb_fname,
1755 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1759 SAMBA_XATTR_DOS_ATTRIB,
1761 if (tevent_req_nomem(subreq, req)) {
1762 return tevent_req_post(req, ev);
1764 tevent_req_set_callback(subreq,
1765 vfswrap_get_dos_attributes_getxattr_done,
1771 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq)
1773 struct tevent_req *req =
1774 tevent_req_callback_data(subreq,
1776 struct vfswrap_get_dos_attributes_state *state =
1777 tevent_req_data(req,
1778 struct vfswrap_get_dos_attributes_state);
1780 DATA_BLOB blob = {0};
1782 char *tofree = NULL;
1783 char pathbuf[PATH_MAX+1];
1785 struct smb_filename smb_fname;
1789 xattr_size = SMB_VFS_GETXATTRAT_RECV(subreq,
1793 TALLOC_FREE(subreq);
1794 if (xattr_size == -1) {
1795 status = map_nt_error_from_unix(state->aio_state.error);
1797 if (state->as_root) {
1798 tevent_req_nterror(req, status);
1801 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1802 tevent_req_nterror(req, status);
1806 state->as_root = true;
1809 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1813 SAMBA_XATTR_DOS_ATTRIB,
1816 if (tevent_req_nomem(subreq, req)) {
1819 tevent_req_set_callback(subreq,
1820 vfswrap_get_dos_attributes_getxattr_done,
1825 blob.length = xattr_size;
1827 status = parse_dos_attribute_blob(state->smb_fname,
1830 if (!NT_STATUS_IS_OK(status)) {
1831 tevent_req_nterror(req, status);
1835 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
1836 state->smb_fname->base_name,
1841 if (pathlen == -1) {
1842 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1846 smb_fname = (struct smb_filename) {
1848 .st = state->smb_fname->st,
1849 .flags = state->smb_fname->flags,
1850 .twrp = state->smb_fname->twrp,
1853 offline = vfswrap_is_offline(state->conn, &smb_fname);
1855 state->dosmode |= FILE_ATTRIBUTE_OFFLINE;
1857 TALLOC_FREE(tofree);
1859 tevent_req_done(req);
1863 static NTSTATUS vfswrap_get_dos_attributes_recv(struct tevent_req *req,
1864 struct vfs_aio_state *aio_state,
1867 struct vfswrap_get_dos_attributes_state *state =
1868 tevent_req_data(req,
1869 struct vfswrap_get_dos_attributes_state);
1872 if (tevent_req_is_nterror(req, &status)) {
1873 tevent_req_received(req);
1877 *aio_state = state->aio_state;
1878 *dosmode = state->dosmode;
1879 tevent_req_received(req);
1880 return NT_STATUS_OK;
1883 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1884 struct files_struct *fsp,
1889 offline = vfswrap_is_offline(handle->conn, fsp->fsp_name);
1891 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1894 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1897 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1898 const struct smb_filename *smb_fname,
1901 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1904 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1905 struct files_struct *fsp,
1908 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1911 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1913 struct vfswrap_offload_read_state {
1917 static struct tevent_req *vfswrap_offload_read_send(
1918 TALLOC_CTX *mem_ctx,
1919 struct tevent_context *ev,
1920 struct vfs_handle_struct *handle,
1921 struct files_struct *fsp,
1927 struct tevent_req *req = NULL;
1928 struct vfswrap_offload_read_state *state = NULL;
1931 req = tevent_req_create(mem_ctx, &state,
1932 struct vfswrap_offload_read_state);
1937 status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1938 &vfswrap_offload_ctx);
1939 if (tevent_req_nterror(req, status)) {
1940 return tevent_req_post(req, ev);
1943 if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1944 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1945 return tevent_req_post(req, ev);
1948 status = vfs_offload_token_create_blob(state, fsp, fsctl,
1950 if (tevent_req_nterror(req, status)) {
1951 return tevent_req_post(req, ev);
1954 status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1956 if (tevent_req_nterror(req, status)) {
1957 return tevent_req_post(req, ev);
1960 tevent_req_done(req);
1961 return tevent_req_post(req, ev);
1964 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
1965 struct vfs_handle_struct *handle,
1966 TALLOC_CTX *mem_ctx,
1969 struct vfswrap_offload_read_state *state = tevent_req_data(
1970 req, struct vfswrap_offload_read_state);
1973 if (tevent_req_is_nterror(req, &status)) {
1974 tevent_req_received(req);
1978 token->length = state->token.length;
1979 token->data = talloc_move(mem_ctx, &state->token.data);
1981 tevent_req_received(req);
1982 return NT_STATUS_OK;
1985 struct vfswrap_offload_write_state {
1987 bool read_lck_locked;
1988 bool write_lck_locked;
1990 struct tevent_context *src_ev;
1991 struct files_struct *src_fsp;
1993 struct tevent_context *dst_ev;
1994 struct files_struct *dst_fsp;
1998 size_t next_io_size;
2001 static void vfswrap_offload_write_cleanup(struct tevent_req *req,
2002 enum tevent_req_state req_state)
2004 struct vfswrap_offload_write_state *state = tevent_req_data(
2005 req, struct vfswrap_offload_write_state);
2008 if (state->dst_fsp == NULL) {
2012 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2014 state->dst_fsp = NULL;
2017 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
2019 static struct tevent_req *vfswrap_offload_write_send(
2020 struct vfs_handle_struct *handle,
2021 TALLOC_CTX *mem_ctx,
2022 struct tevent_context *ev,
2025 off_t transfer_offset,
2026 struct files_struct *dest_fsp,
2030 struct tevent_req *req;
2031 struct vfswrap_offload_write_state *state = NULL;
2032 /* off_t is signed! */
2033 off_t max_offset = INT64_MAX - to_copy;
2034 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
2035 files_struct *src_fsp = NULL;
2039 req = tevent_req_create(mem_ctx, &state,
2040 struct vfswrap_offload_write_state);
2045 *state = (struct vfswrap_offload_write_state) {
2047 .src_off = transfer_offset,
2049 .dst_fsp = dest_fsp,
2050 .dst_off = dest_off,
2052 .remaining = to_copy,
2055 tevent_req_set_cleanup_fn(req, vfswrap_offload_write_cleanup);
2058 case FSCTL_SRV_COPYCHUNK:
2059 case FSCTL_SRV_COPYCHUNK_WRITE:
2062 case FSCTL_OFFLOAD_WRITE:
2063 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
2064 return tevent_req_post(req, ev);
2066 case FSCTL_DUP_EXTENTS_TO_FILE:
2067 DBG_DEBUG("COW clones not supported by vfs_default\n");
2068 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2069 return tevent_req_post(req, ev);
2072 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2073 return tevent_req_post(req, ev);
2077 * From here on we assume a copy-chunk fsctl
2081 tevent_req_done(req);
2082 return tevent_req_post(req, ev);
2085 if (state->src_off > max_offset) {
2087 * Protect integer checks below.
2089 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2090 return tevent_req_post(req, ev);
2092 if (state->src_off < 0) {
2094 * Protect integer checks below.
2096 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2097 return tevent_req_post(req, ev);
2099 if (state->dst_off > max_offset) {
2101 * Protect integer checks below.
2103 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2104 return tevent_req_post(req, ev);
2106 if (state->dst_off < 0) {
2108 * Protect integer checks below.
2110 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2111 return tevent_req_post(req, ev);
2114 status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
2116 if (tevent_req_nterror(req, status)) {
2117 return tevent_req_post(req, ev);
2120 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
2122 status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
2123 if (!NT_STATUS_IS_OK(status)) {
2124 tevent_req_nterror(req, status);
2125 return tevent_req_post(req, ev);
2128 ok = change_to_user_and_service_by_fsp(src_fsp);
2130 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2131 return tevent_req_post(req, ev);
2134 state->src_ev = src_fsp->conn->sconn->ev_ctx;
2135 state->src_fsp = src_fsp;
2137 status = vfs_stat_fsp(src_fsp);
2138 if (tevent_req_nterror(req, status)) {
2139 return tevent_req_post(req, ev);
2142 if (src_fsp->fsp_name->st.st_ex_size < state->src_off + to_copy) {
2144 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
2145 * If the SourceOffset or SourceOffset + Length extends beyond
2146 * the end of file, the server SHOULD<240> treat this as a
2147 * STATUS_END_OF_FILE error.
2149 * <240> Section 3.3.5.15.6: Windows servers will return
2150 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
2152 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
2153 return tevent_req_post(req, ev);
2156 state->buf = talloc_array(state, uint8_t, num);
2157 if (tevent_req_nomem(state->buf, req)) {
2158 return tevent_req_post(req, ev);
2161 status = vfswrap_offload_write_loop(req);
2162 if (!NT_STATUS_IS_OK(status)) {
2163 tevent_req_nterror(req, status);
2164 return tevent_req_post(req, ev);
2170 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
2172 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
2174 struct vfswrap_offload_write_state *state = tevent_req_data(
2175 req, struct vfswrap_offload_write_state);
2176 struct tevent_req *subreq = NULL;
2177 struct lock_struct read_lck;
2181 * This is called under the context of state->src_fsp.
2184 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
2186 init_strict_lock_struct(state->src_fsp,
2187 state->src_fsp->op->global->open_persistent_id,
2189 state->next_io_size,
2193 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
2197 return NT_STATUS_FILE_LOCK_CONFLICT;
2200 subreq = SMB_VFS_PREAD_SEND(state,
2204 state->next_io_size,
2206 if (subreq == NULL) {
2207 return NT_STATUS_NO_MEMORY;
2209 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
2211 return NT_STATUS_OK;
2214 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
2216 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
2218 struct tevent_req *req = tevent_req_callback_data(
2219 subreq, struct tevent_req);
2220 struct vfswrap_offload_write_state *state = tevent_req_data(
2221 req, struct vfswrap_offload_write_state);
2222 struct vfs_aio_state aio_state;
2223 struct lock_struct write_lck;
2227 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
2228 TALLOC_FREE(subreq);
2230 DBG_ERR("read failed: %s\n", strerror(aio_state.error));
2231 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2234 if (nread != state->next_io_size) {
2235 DBG_ERR("Short read, only %zd of %zu\n",
2236 nread, state->next_io_size);
2237 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2241 state->src_off += nread;
2243 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2245 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2249 init_strict_lock_struct(state->dst_fsp,
2250 state->dst_fsp->op->global->open_persistent_id,
2252 state->next_io_size,
2256 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
2260 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
2264 subreq = SMB_VFS_PWRITE_SEND(state,
2268 state->next_io_size,
2270 if (subreq == NULL) {
2271 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2274 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
2277 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
2279 struct tevent_req *req = tevent_req_callback_data(
2280 subreq, struct tevent_req);
2281 struct vfswrap_offload_write_state *state = tevent_req_data(
2282 req, struct vfswrap_offload_write_state);
2283 struct vfs_aio_state aio_state;
2288 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
2289 TALLOC_FREE(subreq);
2290 if (nwritten == -1) {
2291 DBG_ERR("write failed: %s\n", strerror(aio_state.error));
2292 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2295 if (nwritten != state->next_io_size) {
2296 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
2297 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2301 state->dst_off += nwritten;
2303 if (state->remaining < nwritten) {
2304 /* Paranoia check */
2305 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2308 state->remaining -= nwritten;
2309 if (state->remaining == 0) {
2310 tevent_req_done(req);
2314 ok = change_to_user_and_service_by_fsp(state->src_fsp);
2316 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2320 status = vfswrap_offload_write_loop(req);
2321 if (!NT_STATUS_IS_OK(status)) {
2322 tevent_req_nterror(req, status);
2329 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
2330 struct tevent_req *req,
2333 struct vfswrap_offload_write_state *state = tevent_req_data(
2334 req, struct vfswrap_offload_write_state);
2337 if (tevent_req_is_nterror(req, &status)) {
2338 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
2340 tevent_req_received(req);
2344 *copied = state->to_copy;
2345 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
2346 tevent_req_received(req);
2348 return NT_STATUS_OK;
2351 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
2352 TALLOC_CTX *mem_ctx,
2353 struct files_struct *fsp,
2354 struct smb_filename *smb_fname,
2355 uint16_t *_compression_fmt)
2357 return NT_STATUS_INVALID_DEVICE_REQUEST;
2360 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
2361 TALLOC_CTX *mem_ctx,
2362 struct files_struct *fsp,
2363 uint16_t compression_fmt)
2365 return NT_STATUS_INVALID_DEVICE_REQUEST;
2368 /********************************************************************
2369 Given a stat buffer return the allocated size on disk, taking into
2370 account sparse files.
2371 ********************************************************************/
2372 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
2373 struct files_struct *fsp,
2374 const SMB_STRUCT_STAT *sbuf)
2378 START_PROFILE(syscall_get_alloc_size);
2380 if(S_ISDIR(sbuf->st_ex_mode)) {
2385 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2386 /* The type of st_blocksize is blkcnt_t which *MUST* be
2387 signed (according to POSIX) and can be less than 64-bits.
2388 Ensure when we're converting to 64 bits wide we don't
2390 #if defined(SIZEOF_BLKCNT_T_8)
2391 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2392 #elif defined(SIZEOF_BLKCNT_T_4)
2394 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2395 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2398 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2402 * Some file systems do not allocate a block for very
2403 * small files. But for non-empty file should report a
2407 uint64_t filesize = get_file_size_stat(sbuf);
2409 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2413 result = get_file_size_stat(sbuf);
2416 if (fsp && fsp->initial_allocation_size)
2417 result = MAX(result,fsp->initial_allocation_size);
2419 result = smb_roundup(handle->conn, result);
2422 END_PROFILE(syscall_get_alloc_size);
2426 static int vfswrap_unlinkat(vfs_handle_struct *handle,
2427 struct files_struct *dirfsp,
2428 const struct smb_filename *smb_fname,
2433 START_PROFILE(syscall_unlinkat);
2435 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2437 if (is_named_stream(smb_fname)) {
2441 result = unlinkat(fsp_get_pathref_fd(dirfsp),
2442 smb_fname->base_name,
2446 END_PROFILE(syscall_unlinkat);
2450 static int vfswrap_chmod(vfs_handle_struct *handle,
2451 const struct smb_filename *smb_fname,
2456 START_PROFILE(syscall_chmod);
2457 result = chmod(smb_fname->base_name, mode);
2458 END_PROFILE(syscall_chmod);
2462 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2466 START_PROFILE(syscall_fchmod);
2467 #if defined(HAVE_FCHMOD)
2468 result = fchmod(fsp_get_io_fd(fsp), mode);
2474 END_PROFILE(syscall_fchmod);
2478 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2483 START_PROFILE(syscall_fchown);
2484 result = fchown(fsp_get_io_fd(fsp), uid, gid);
2485 END_PROFILE(syscall_fchown);
2493 static int vfswrap_lchown(vfs_handle_struct *handle,
2494 const struct smb_filename *smb_fname,
2500 START_PROFILE(syscall_lchown);
2501 result = lchown(smb_fname->base_name, uid, gid);
2502 END_PROFILE(syscall_lchown);
2506 static int vfswrap_chdir(vfs_handle_struct *handle,
2507 const struct smb_filename *smb_fname)
2511 START_PROFILE(syscall_chdir);
2512 result = chdir(smb_fname->base_name);
2513 END_PROFILE(syscall_chdir);
2517 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2521 struct smb_filename *smb_fname = NULL;
2523 START_PROFILE(syscall_getwd);
2524 result = sys_getwd();
2525 END_PROFILE(syscall_getwd);
2527 if (result == NULL) {
2530 smb_fname = synthetic_smb_fname(ctx,
2537 * sys_getwd() *always* returns malloced memory.
2538 * We must free here to avoid leaks:
2539 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2545 /*********************************************************************
2546 nsec timestamp resolution call. Convert down to whatever the underlying
2547 system will support.
2548 **********************************************************************/
2550 static int vfswrap_ntimes(vfs_handle_struct *handle,
2551 const struct smb_filename *smb_fname,
2552 struct smb_file_time *ft)
2556 START_PROFILE(syscall_ntimes);
2558 if (is_named_stream(smb_fname)) {
2564 if (is_omit_timespec(&ft->atime)) {
2565 ft->atime= smb_fname->st.st_ex_atime;
2568 if (is_omit_timespec(&ft->mtime)) {
2569 ft->mtime = smb_fname->st.st_ex_mtime;
2572 if (!is_omit_timespec(&ft->create_time)) {
2573 set_create_timespec_ea(handle->conn,
2578 if ((timespec_compare(&ft->atime,
2579 &smb_fname->st.st_ex_atime) == 0) &&
2580 (timespec_compare(&ft->mtime,
2581 &smb_fname->st.st_ex_mtime) == 0)) {
2586 #if defined(HAVE_UTIMENSAT)
2588 struct timespec ts[2];
2591 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2593 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2595 if (!((result == -1) && (errno == ENOSYS))) {
2599 #if defined(HAVE_UTIMES)
2601 struct timeval tv[2];
2602 tv[0] = convert_timespec_to_timeval(ft->atime);
2603 tv[1] = convert_timespec_to_timeval(ft->mtime);
2604 result = utimes(smb_fname->base_name, tv);
2606 result = utimes(smb_fname->base_name, NULL);
2608 if (!((result == -1) && (errno == ENOSYS))) {
2612 #if defined(HAVE_UTIME)
2614 struct utimbuf times;
2615 times.actime = convert_timespec_to_time_t(ft->atime);
2616 times.modtime = convert_timespec_to_time_t(ft->mtime);
2617 result = utime(smb_fname->base_name, ×);
2619 result = utime(smb_fname->base_name, NULL);
2621 if (!((result == -1) && (errno == ENOSYS))) {
2629 END_PROFILE(syscall_ntimes);
2633 /*********************************************************************
2634 A version of ftruncate that will write the space on disk if strict
2636 **********************************************************************/
2638 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2640 off_t space_to_write;
2641 uint64_t space_avail;
2642 uint64_t bsize,dfree,dsize;
2645 SMB_STRUCT_STAT *pst;
2648 ok = vfs_valid_pwrite_range(len, 0);
2654 status = vfs_stat_fsp(fsp);
2655 if (!NT_STATUS_IS_OK(status)) {
2658 pst = &fsp->fsp_name->st;
2661 if (S_ISFIFO(pst->st_ex_mode))
2665 if (pst->st_ex_size == len)
2668 /* Shrink - just ftruncate. */
2669 if (pst->st_ex_size > len)
2670 return ftruncate(fsp_get_io_fd(fsp), len);
2672 space_to_write = len - pst->st_ex_size;
2674 /* for allocation try fallocate first. This can fail on some
2675 platforms e.g. when the filesystem doesn't support it and no
2676 emulation is being done by the libc (like on AIX with JFS1). In that
2677 case we do our own emulation. fallocate implementations can
2678 return ENOTSUP or EINVAL in cases like that. */
2679 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2680 if (ret == -1 && errno == ENOSPC) {
2686 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2687 "error %d. Falling back to slow manual allocation\n", errno));
2689 /* available disk space is enough or not? */
2691 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2692 /* space_avail is 1k blocks */
2693 if (space_avail == (uint64_t)-1 ||
2694 ((uint64_t)space_to_write/1024 > space_avail) ) {
2699 /* Write out the real space on disk. */
2700 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2708 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2711 SMB_STRUCT_STAT *pst;
2715 START_PROFILE(syscall_ftruncate);
2717 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->fsp_flags.is_sparse) {
2718 result = strict_allocate_ftruncate(handle, fsp, len);
2719 END_PROFILE(syscall_ftruncate);
2723 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2724 ftruncate if the system supports it. Then I discovered that
2725 you can have some filesystems that support ftruncate
2726 expansion and some that don't! On Linux fat can't do
2727 ftruncate extend but ext2 can. */
2729 result = ftruncate(fsp_get_io_fd(fsp), len);
2731 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2732 extend a file with ftruncate. Provide alternate implementation
2735 /* Do an fstat to see if the file is longer than the requested
2736 size in which case the ftruncate above should have
2737 succeeded or shorter, in which case seek to len - 1 and
2738 write 1 byte of zero */
2739 status = vfs_stat_fsp(fsp);
2740 if (!NT_STATUS_IS_OK(status)) {
2744 /* We need to update the files_struct after successful ftruncate */
2749 pst = &fsp->fsp_name->st;
2752 if (S_ISFIFO(pst->st_ex_mode)) {
2758 if (pst->st_ex_size == len) {
2763 if (pst->st_ex_size > len) {
2764 /* the ftruncate should have worked */
2768 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2776 END_PROFILE(syscall_ftruncate);
2780 static int vfswrap_fallocate(vfs_handle_struct *handle,
2788 START_PROFILE(syscall_fallocate);
2790 result = sys_posix_fallocate(fsp_get_io_fd(fsp), offset, len);
2792 * posix_fallocate returns 0 on success, errno on error
2793 * and doesn't set errno. Make it behave like fallocate()
2794 * which returns -1, and sets errno on failure.
2801 /* sys_fallocate handles filtering of unsupported mode flags */
2802 result = sys_fallocate(fsp_get_io_fd(fsp), mode, offset, len);
2804 END_PROFILE(syscall_fallocate);
2808 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2812 START_PROFILE(syscall_fcntl_lock);
2814 if (fsp->fsp_flags.use_ofd_locks) {
2815 op = map_process_lock_to_ofd_lock(op);
2818 result = fcntl_lock(fsp_get_io_fd(fsp), op, offset, count, type);
2819 END_PROFILE(syscall_fcntl_lock);
2823 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2824 uint32_t share_access, uint32_t access_mask)
2826 START_PROFILE(syscall_kernel_flock);
2827 kernel_flock(fsp_get_io_fd(fsp), share_access, access_mask);
2828 END_PROFILE(syscall_kernel_flock);
2832 static int vfswrap_fcntl(vfs_handle_struct *handle, files_struct *fsp, int cmd,
2836 va_list dup_cmd_arg;
2840 START_PROFILE(syscall_fcntl);
2842 va_copy(dup_cmd_arg, cmd_arg);
2848 #if defined(HAVE_OFD_LOCKS)
2853 #if defined(HAVE_F_OWNER_EX)
2857 #if defined(HAVE_RW_HINTS)
2860 case F_GET_FILE_RW_HINT:
2861 case F_SET_FILE_RW_HINT:
2863 argp = va_arg(dup_cmd_arg, void *);
2864 result = sys_fcntl_ptr(fsp_get_io_fd(fsp), cmd, argp);
2867 val = va_arg(dup_cmd_arg, int);
2868 result = sys_fcntl_int(fsp_get_io_fd(fsp), cmd, val);
2871 va_end(dup_cmd_arg);
2873 END_PROFILE(syscall_fcntl);
2877 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2882 START_PROFILE(syscall_fcntl_getlock);
2884 if (fsp->fsp_flags.use_ofd_locks) {
2885 op = map_process_lock_to_ofd_lock(op);
2888 result = fcntl_getlock(fsp_get_io_fd(fsp), op, poffset, pcount, ptype, ppid);
2889 END_PROFILE(syscall_fcntl_getlock);
2893 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2898 START_PROFILE(syscall_linux_setlease);
2900 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2901 result = linux_setlease(fsp_get_io_fd(fsp), leasetype);
2905 END_PROFILE(syscall_linux_setlease);
2909 static int vfswrap_symlinkat(vfs_handle_struct *handle,
2910 const struct smb_filename *link_target,
2911 struct files_struct *dirfsp,
2912 const struct smb_filename *new_smb_fname)
2916 START_PROFILE(syscall_symlinkat);
2918 result = symlinkat(link_target->base_name,
2919 fsp_get_pathref_fd(dirfsp),
2920 new_smb_fname->base_name);
2921 END_PROFILE(syscall_symlinkat);
2925 static int vfswrap_readlinkat(vfs_handle_struct *handle,
2926 const struct files_struct *dirfsp,
2927 const struct smb_filename *smb_fname,
2933 START_PROFILE(syscall_readlinkat);
2935 result = readlinkat(fsp_get_pathref_fd(dirfsp),
2936 smb_fname->base_name,
2940 END_PROFILE(syscall_readlinkat);
2944 static int vfswrap_linkat(vfs_handle_struct *handle,
2945 files_struct *srcfsp,
2946 const struct smb_filename *old_smb_fname,
2947 files_struct *dstfsp,
2948 const struct smb_filename *new_smb_fname,
2953 START_PROFILE(syscall_linkat);
2955 result = linkat(fsp_get_pathref_fd(srcfsp),
2956 old_smb_fname->base_name,
2957 fsp_get_pathref_fd(dstfsp),
2958 new_smb_fname->base_name,
2961 END_PROFILE(syscall_linkat);
2965 static int vfswrap_mknodat(vfs_handle_struct *handle,
2966 files_struct *dirfsp,
2967 const struct smb_filename *smb_fname,
2973 START_PROFILE(syscall_mknodat);
2975 result = sys_mknodat(fsp_get_pathref_fd(dirfsp),
2976 smb_fname->base_name,
2980 END_PROFILE(syscall_mknodat);
2984 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2986 const struct smb_filename *smb_fname)
2989 struct smb_filename *result_fname = NULL;
2991 START_PROFILE(syscall_realpath);
2992 result = sys_realpath(smb_fname->base_name);
2993 END_PROFILE(syscall_realpath);
2995 result_fname = synthetic_smb_fname(ctx,
3003 return result_fname;
3006 static int vfswrap_chflags(vfs_handle_struct *handle,
3007 const struct smb_filename *smb_fname,
3011 return chflags(smb_fname->base_name, flags);
3018 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
3019 const SMB_STRUCT_STAT *sbuf)
3023 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
3027 key.devid = sbuf->st_ex_dev;
3028 key.inode = sbuf->st_ex_ino;
3029 /* key.extid is unused by default. */
3034 static uint64_t vfswrap_fs_file_id(struct vfs_handle_struct *handle,
3035 const SMB_STRUCT_STAT *psbuf)
3039 if (!(psbuf->st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)) {
3040 return psbuf->st_ex_file_id;
3043 if (handle->conn->base_share_dev == psbuf->st_ex_dev) {
3044 return (uint64_t)psbuf->st_ex_ino;
3048 file_id = ((psbuf->st_ex_ino) & UINT32_MAX);
3051 file_id |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32;
3056 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
3057 struct files_struct *fsp,
3058 const struct smb_filename *smb_fname,
3059 TALLOC_CTX *mem_ctx,
3060 unsigned int *pnum_streams,
3061 struct stream_struct **pstreams)
3063 SMB_STRUCT_STAT sbuf;
3064 struct stream_struct *tmp_streams = NULL;
3067 if ((fsp != NULL) && (fsp->fsp_flags.is_directory)) {
3069 * No default streams on directories
3074 if ((fsp != NULL) && (fsp_get_pathref_fd(fsp) != -1)) {
3075 ret = SMB_VFS_FSTAT(fsp, &sbuf);
3078 struct smb_filename *smb_fname_cp = NULL;
3080 smb_fname_cp = cp_smb_filename_nostream(talloc_tos(), smb_fname);
3081 if (smb_fname_cp == NULL) {
3082 return NT_STATUS_NO_MEMORY;
3085 ret = vfs_stat(handle->conn, smb_fname_cp);
3086 sbuf = smb_fname_cp->st;
3087 TALLOC_FREE(smb_fname_cp);
3091 return map_nt_error_from_unix(errno);
3094 if (S_ISDIR(sbuf.st_ex_mode)) {
3098 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
3099 (*pnum_streams) + 1);
3100 if (tmp_streams == NULL) {
3101 return NT_STATUS_NO_MEMORY;
3103 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
3104 if (tmp_streams[*pnum_streams].name == NULL) {
3105 return NT_STATUS_NO_MEMORY;
3107 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
3108 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
3111 *pstreams = tmp_streams;
3113 return NT_STATUS_OK;
3116 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
3117 const struct smb_filename *path,
3119 TALLOC_CTX *mem_ctx,
3123 * Don't fall back to get_real_filename so callers can differentiate
3124 * between a full directory scan and an actual case-insensitive stat.
3130 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
3131 const struct smb_filename *smb_fname)
3133 return handle->conn->connectpath;
3136 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
3137 struct byte_range_lock *br_lck,
3138 struct lock_struct *plock)
3140 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3142 /* Note: blr is not used in the default implementation. */
3143 return brl_lock_windows_default(br_lck, plock);
3146 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
3147 struct byte_range_lock *br_lck,
3148 const struct lock_struct *plock)
3150 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3152 return brl_unlock_windows_default(br_lck, plock);
3155 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
3157 struct lock_struct *plock)
3159 SMB_ASSERT(plock->lock_type == READ_LOCK ||
3160 plock->lock_type == WRITE_LOCK);
3162 return strict_lock_check_default(fsp, plock);
3165 /* NT ACL operations. */
3167 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
3169 uint32_t security_info,
3170 TALLOC_CTX *mem_ctx,
3171 struct security_descriptor **ppdesc)
3175 START_PROFILE(fget_nt_acl);
3176 result = posix_fget_nt_acl(fsp, security_info,
3178 END_PROFILE(fget_nt_acl);
3182 static NTSTATUS vfswrap_get_nt_acl_at(vfs_handle_struct *handle,
3183 struct files_struct *dirfsp,
3184 const struct smb_filename *smb_fname,
3185 uint32_t security_info,
3186 TALLOC_CTX *mem_ctx,
3187 struct security_descriptor **ppdesc)
3191 START_PROFILE(get_nt_acl_at);
3193 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
3195 result = posix_get_nt_acl(handle->conn,
3200 END_PROFILE(get_nt_acl_at);
3204 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
3208 START_PROFILE(fset_nt_acl);
3209 result = set_nt_acl(fsp, security_info_sent, psd);
3210 END_PROFILE(fset_nt_acl);
3214 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
3215 struct smb_filename *file,
3216 struct security_acl *sacl,
3217 uint32_t access_requested,
3218 uint32_t access_denied)
3220 return NT_STATUS_OK; /* Nothing to do here ... */
3223 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
3224 const struct smb_filename *smb_fname,
3225 SMB_ACL_TYPE_T type,
3226 TALLOC_CTX *mem_ctx)
3228 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
3231 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
3233 TALLOC_CTX *mem_ctx)
3235 return sys_acl_get_fd(handle, fsp, mem_ctx);
3238 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
3239 const struct smb_filename *smb_fname,
3240 SMB_ACL_TYPE_T acltype,
3243 return sys_acl_set_file(handle, smb_fname, acltype, theacl);
3246 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
3248 return sys_acl_set_fd(handle, fsp, theacl);
3251 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
3252 const struct smb_filename *smb_fname)
3254 return sys_acl_delete_def_file(handle, smb_fname);
3257 /****************************************************************
3258 Extended attribute operations.
3259 *****************************************************************/
3261 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
3262 const struct smb_filename *smb_fname,
3267 return getxattr(smb_fname->base_name, name, value, size);
3270 struct vfswrap_getxattrat_state {
3271 struct tevent_context *ev;
3272 files_struct *dir_fsp;
3273 const struct smb_filename *smb_fname;
3276 * The following variables are talloced off "state" which is protected
3277 * by a destructor and thus are guaranteed to be safe to be used in the
3278 * job function in the worker thread.
3281 const char *xattr_name;
3282 uint8_t *xattr_value;
3283 struct security_unix_token *token;
3286 struct vfs_aio_state vfs_aio_state;
3287 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
3290 static int vfswrap_getxattrat_state_destructor(
3291 struct vfswrap_getxattrat_state *state)
3296 static void vfswrap_getxattrat_do_sync(struct tevent_req *req);
3297 static void vfswrap_getxattrat_do_async(void *private_data);
3298 static void vfswrap_getxattrat_done(struct tevent_req *subreq);
3300 static struct tevent_req *vfswrap_getxattrat_send(
3301 TALLOC_CTX *mem_ctx,
3302 struct tevent_context *ev,
3303 struct vfs_handle_struct *handle,
3304 files_struct *dir_fsp,
3305 const struct smb_filename *smb_fname,
3306 const char *xattr_name,
3309 struct tevent_req *req = NULL;
3310 struct tevent_req *subreq = NULL;
3311 struct vfswrap_getxattrat_state *state = NULL;
3312 size_t max_threads = 0;
3313 bool have_per_thread_cwd = false;
3314 bool have_per_thread_creds = false;
3315 bool do_async = false;
3317 req = tevent_req_create(mem_ctx, &state,
3318 struct vfswrap_getxattrat_state);
3322 *state = (struct vfswrap_getxattrat_state) {
3325 .smb_fname = smb_fname,
3328 max_threads = pthreadpool_tevent_max_threads(dir_fsp->conn->sconn->pool);
3329 if (max_threads >= 1) {
3331 * We need a non sync threadpool!
3333 have_per_thread_cwd = per_thread_cwd_supported();
3335 #ifdef HAVE_LINUX_THREAD_CREDENTIALS
3336 have_per_thread_creds = true;
3338 if (have_per_thread_cwd && have_per_thread_creds) {
3342 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat, profile_p,
3343 state->profile_bytes, 0);
3345 if (fsp_get_pathref_fd(dir_fsp) == -1) {
3346 DBG_ERR("Need a valid directory fd\n");
3347 tevent_req_error(req, EINVAL);
3348 return tevent_req_post(req, ev);
3351 if (alloc_hint > 0) {
3352 state->xattr_value = talloc_zero_array(state,
3355 if (tevent_req_nomem(state->xattr_value, req)) {
3356 return tevent_req_post(req, ev);
3361 vfswrap_getxattrat_do_sync(req);
3362 return tevent_req_post(req, ev);
3366 * Now allocate all parameters from a memory context that won't go away
3367 * no matter what. These paremeters will get used in threads and we
3368 * can't reliably cancel threads, so all buffers passed to the threads
3369 * must not be freed before all referencing threads terminate.
3372 state->name = talloc_strdup(state, smb_fname->base_name);
3373 if (tevent_req_nomem(state->name, req)) {
3374 return tevent_req_post(req, ev);
3377 state->xattr_name = talloc_strdup(state, xattr_name);
3378 if (tevent_req_nomem(state->xattr_name, req)) {
3379 return tevent_req_post(req, ev);
3383 * This is a hot codepath so at first glance one might think we should
3384 * somehow optimize away the token allocation and do a
3385 * talloc_reference() or similar black magic instead. But due to the
3386 * talloc_stackframe pool per SMB2 request this should be a simple copy
3387 * without a malloc in most cases.
3389 if (geteuid() == sec_initial_uid()) {
3390 state->token = root_unix_token(state);
3392 state->token = copy_unix_token(
3394 dir_fsp->conn->session_info->unix_token);
3396 if (tevent_req_nomem(state->token, req)) {
3397 return tevent_req_post(req, ev);
3400 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3402 subreq = pthreadpool_tevent_job_send(
3405 dir_fsp->conn->sconn->pool,
3406 vfswrap_getxattrat_do_async,
3408 if (tevent_req_nomem(subreq, req)) {
3409 return tevent_req_post(req, ev);
3411 tevent_req_set_callback(subreq, vfswrap_getxattrat_done, req);
3413 talloc_set_destructor(state, vfswrap_getxattrat_state_destructor);
3418 static void vfswrap_getxattrat_do_sync(struct tevent_req *req)
3420 struct vfswrap_getxattrat_state *state = tevent_req_data(
3421 req, struct vfswrap_getxattrat_state);
3423 char *tofree = NULL;
3424 char pathbuf[PATH_MAX+1];
3428 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
3429 state->smb_fname->base_name,
3434 if (pathlen == -1) {
3435 tevent_req_error(req, ENOMEM);
3439 state->xattr_size = getxattr(path,
3442 talloc_array_length(state->xattr_value));
3444 TALLOC_FREE(tofree);
3445 if (state->xattr_size == -1) {
3446 tevent_req_error(req, err);
3450 tevent_req_done(req);
3454 static void vfswrap_getxattrat_do_async(void *private_data)
3456 struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3457 private_data, struct vfswrap_getxattrat_state);
3458 struct timespec start_time;
3459 struct timespec end_time;
3462 PROFILE_TIMESTAMP(&start_time);
3463 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
3466 * Here we simulate a getxattrat()
3467 * call using fchdir();getxattr()
3470 per_thread_cwd_activate();
3472 /* Become the correct credential on this thread. */
3473 ret = set_thread_credentials(state->token->uid,
3475 (size_t)state->token->ngroups,
3476 state->token->groups);
3478 state->xattr_size = -1;
3479 state->vfs_aio_state.error = errno;
3483 ret = fchdir(fsp_get_pathref_fd(state->dir_fsp));
3485 state->xattr_size = -1;
3486 state->vfs_aio_state.error = errno;
3490 state->xattr_size = getxattr(state->name,
3493 talloc_array_length(state->xattr_value));
3494 if (state->xattr_size == -1) {
3495 state->vfs_aio_state.error = errno;
3499 PROFILE_TIMESTAMP(&end_time);
3500 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
3501 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3504 static void vfswrap_getxattrat_done(struct tevent_req *subreq)
3506 struct tevent_req *req = tevent_req_callback_data(
3507 subreq, struct tevent_req);
3508 struct vfswrap_getxattrat_state *state = tevent_req_data(
3509 req, struct vfswrap_getxattrat_state);
3514 * Make sure we run as the user again
3516 ok = change_to_user_and_service_by_fsp(state->dir_fsp);
3519 ret = pthreadpool_tevent_job_recv(subreq);
3520 TALLOC_FREE(subreq);
3521 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
3522 talloc_set_destructor(state, NULL);
3524 if (ret != EAGAIN) {
3525 tevent_req_error(req, ret);
3529 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
3530 * means the lower level pthreadpool failed to create a new
3531 * thread. Fallback to sync processing in that case to allow
3532 * some progress for the client.
3534 vfswrap_getxattrat_do_sync(req);
3538 if (state->xattr_size == -1) {
3539 tevent_req_error(req, state->vfs_aio_state.error);
3543 if (state->xattr_value == NULL) {
3545 * The caller only wanted the size.
3547 tevent_req_done(req);
3552 * shrink the buffer to the returned size.
3553 * (can't fail). It means NULL if size is 0.
3555 state->xattr_value = talloc_realloc(state,
3560 tevent_req_done(req);
3563 static ssize_t vfswrap_getxattrat_recv(struct tevent_req *req,
3564 struct vfs_aio_state *aio_state,
3565 TALLOC_CTX *mem_ctx,
3566 uint8_t **xattr_value)
3568 struct vfswrap_getxattrat_state *state = tevent_req_data(
3569 req, struct vfswrap_getxattrat_state);
3572 if (tevent_req_is_unix_error(req, &aio_state->error)) {
3573 tevent_req_received(req);
3577 *aio_state = state->vfs_aio_state;
3578 xattr_size = state->xattr_size;
3579 if (xattr_value != NULL) {
3580 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
3583 tevent_req_received(req);
3587 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle,
3588 struct files_struct *fsp,
3593 int fd = fsp_get_pathref_fd(fsp);
3595 if (!fsp->fsp_flags.is_pathref) {
3596 return fgetxattr(fd, name, value, size);
3599 if (fsp->fsp_flags.have_proc_fds) {
3600 const char *p = NULL;
3603 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3608 return getxattr(p, name, value, size);
3612 * This is no longer a handle based call.
3614 return getxattr(fsp->fsp_name->base_name, name, value, size);
3617 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
3618 const struct smb_filename *smb_fname,
3622 return listxattr(smb_fname->base_name, list, size);
3625 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
3627 int fd = fsp_get_pathref_fd(fsp);
3629 if (!fsp->fsp_flags.is_pathref) {
3630 return flistxattr(fd, list, size);
3633 if (fsp->fsp_flags.have_proc_fds) {
3634 const char *p = NULL;
3637 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3642 return listxattr(p, list, size);
3646 * This is no longer a handle based call.
3648 return listxattr(fsp->fsp_name->base_name, list, size);
3651 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
3652 const struct smb_filename *smb_fname,
3655 return removexattr(smb_fname->base_name, name);
3658 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
3660 int fd = fsp_get_pathref_fd(fsp);
3662 if (!fsp->fsp_flags.is_pathref) {
3663 return fremovexattr(fd, name);
3666 if (fsp->fsp_flags.have_proc_fds) {
3667 const char *p = NULL;
3670 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3675 return removexattr(p, name);
3679 * This is no longer a handle based call.
3681 return removexattr(fsp->fsp_name->base_name, name);
3684 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
3685 const struct smb_filename *smb_fname,
3691 return setxattr(smb_fname->base_name, name, value, size, flags);
3694 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
3696 int fd = fsp_get_pathref_fd(fsp);
3698 if (!fsp->fsp_flags.is_pathref) {
3699 return fsetxattr(fd, name, value, size, flags);
3702 if (fsp->fsp_flags.have_proc_fds) {
3703 const char *p = NULL;
3706 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3711 return setxattr(p, name, value, size, flags);
3715 * This is no longer a handle based call.
3717 return setxattr(fsp->fsp_name->base_name, name, value, size, flags);
3720 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
3725 static bool vfswrap_is_offline(struct connection_struct *conn,
3726 const struct smb_filename *fname)
3730 bool offline = false;
3732 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
3736 if (!lp_dmapi_support(SNUM(conn)) || !dmapi_have_session()) {
3737 #if defined(ENOTSUP)
3743 status = get_full_smb_filename(talloc_tos(), fname, &path);
3744 if (!NT_STATUS_IS_OK(status)) {
3745 errno = map_errno_from_nt_status(status);
3749 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
3756 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
3757 struct files_struct *fsp,
3758 TALLOC_CTX *mem_ctx,
3761 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
3764 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
3765 struct files_struct *fsp,
3766 const DATA_BLOB old_cookie,
3767 TALLOC_CTX *mem_ctx,
3768 DATA_BLOB *new_cookie)
3770 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
3774 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
3775 struct smb_request *smb1req,
3776 struct smbXsrv_open *op,
3777 const DATA_BLOB old_cookie,
3778 TALLOC_CTX *mem_ctx,
3779 struct files_struct **fsp,
3780 DATA_BLOB *new_cookie)
3782 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
3783 old_cookie, mem_ctx,
3787 static struct vfs_fn_pointers vfs_default_fns = {
3788 /* Disk operations */
3790 .connect_fn = vfswrap_connect,
3791 .disconnect_fn = vfswrap_disconnect,
3792 .disk_free_fn = vfswrap_disk_free,
3793 .get_quota_fn = vfswrap_get_quota,
3794 .set_quota_fn = vfswrap_set_quota,
3795 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3796 .statvfs_fn = vfswrap_statvfs,
3797 .fs_capabilities_fn = vfswrap_fs_capabilities,
3798 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3799 .create_dfs_pathat_fn = vfswrap_create_dfs_pathat,
3800 .read_dfs_pathat_fn = vfswrap_read_dfs_pathat,
3801 .snap_check_path_fn = vfswrap_snap_check_path,
3802 .snap_create_fn = vfswrap_snap_create,
3803 .snap_delete_fn = vfswrap_snap_delete,
3805 /* Directory operations */
3807 .fdopendir_fn = vfswrap_fdopendir,
3808 .readdir_fn = vfswrap_readdir,
3809 .readdir_attr_fn = vfswrap_readdir_attr,
3810 .seekdir_fn = vfswrap_seekdir,
3811 .telldir_fn = vfswrap_telldir,
3812 .rewind_dir_fn = vfswrap_rewinddir,
3813 .mkdirat_fn = vfswrap_mkdirat,
3814 .closedir_fn = vfswrap_closedir,
3816 /* File operations */
3818 .openat_fn = vfswrap_openat,
3819 .create_file_fn = vfswrap_create_file,
3820 .close_fn = vfswrap_close,
3821 .pread_fn = vfswrap_pread,
3822 .pread_send_fn = vfswrap_pread_send,
3823 .pread_recv_fn = vfswrap_pread_recv,
3824 .pwrite_fn = vfswrap_pwrite,
3825 .pwrite_send_fn = vfswrap_pwrite_send,
3826 .pwrite_recv_fn = vfswrap_pwrite_recv,
3827 .lseek_fn = vfswrap_lseek,
3828 .sendfile_fn = vfswrap_sendfile,
3829 .recvfile_fn = vfswrap_recvfile,
3830 .renameat_fn = vfswrap_renameat,
3831 .fsync_send_fn = vfswrap_fsync_send,
3832 .fsync_recv_fn = vfswrap_fsync_recv,
3833 .stat_fn = vfswrap_stat,
3834 .fstat_fn = vfswrap_fstat,
3835 .lstat_fn = vfswrap_lstat,
3836 .get_alloc_size_fn = vfswrap_get_alloc_size,
3837 .unlinkat_fn = vfswrap_unlinkat,
3838 .chmod_fn = vfswrap_chmod,
3839 .fchmod_fn = vfswrap_fchmod,
3840 .fchown_fn = vfswrap_fchown,
3841 .lchown_fn = vfswrap_lchown,
3842 .chdir_fn = vfswrap_chdir,
3843 .getwd_fn = vfswrap_getwd,
3844 .ntimes_fn = vfswrap_ntimes,
3845 .ftruncate_fn = vfswrap_ftruncate,
3846 .fallocate_fn = vfswrap_fallocate,
3847 .lock_fn = vfswrap_lock,
3848 .kernel_flock_fn = vfswrap_kernel_flock,
3849 .fcntl_fn = vfswrap_fcntl,
3850 .linux_setlease_fn = vfswrap_linux_setlease,
3851 .getlock_fn = vfswrap_getlock,
3852 .symlinkat_fn = vfswrap_symlinkat,
3853 .readlinkat_fn = vfswrap_readlinkat,
3854 .linkat_fn = vfswrap_linkat,
3855 .mknodat_fn = vfswrap_mknodat,
3856 .realpath_fn = vfswrap_realpath,
3857 .chflags_fn = vfswrap_chflags,
3858 .file_id_create_fn = vfswrap_file_id_create,
3859 .fs_file_id_fn = vfswrap_fs_file_id,
3860 .streaminfo_fn = vfswrap_streaminfo,
3861 .get_real_filename_fn = vfswrap_get_real_filename,
3862 .connectpath_fn = vfswrap_connectpath,
3863 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
3864 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3865 .strict_lock_check_fn = vfswrap_strict_lock_check,
3866 .translate_name_fn = vfswrap_translate_name,
3867 .fsctl_fn = vfswrap_fsctl,
3868 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
3869 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
3870 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
3871 .get_dos_attributes_send_fn = vfswrap_get_dos_attributes_send,
3872 .get_dos_attributes_recv_fn = vfswrap_get_dos_attributes_recv,
3873 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
3874 .offload_read_send_fn = vfswrap_offload_read_send,
3875 .offload_read_recv_fn = vfswrap_offload_read_recv,
3876 .offload_write_send_fn = vfswrap_offload_write_send,
3877 .offload_write_recv_fn = vfswrap_offload_write_recv,
3878 .get_compression_fn = vfswrap_get_compression,
3879 .set_compression_fn = vfswrap_set_compression,
3881 /* NT ACL operations. */
3883 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
3884 .get_nt_acl_at_fn = vfswrap_get_nt_acl_at,
3885 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
3886 .audit_file_fn = vfswrap_audit_file,
3888 /* POSIX ACL operations. */
3890 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
3891 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3892 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
3893 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3894 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
3895 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3896 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
3898 /* EA operations. */
3899 .getxattr_fn = vfswrap_getxattr,
3900 .getxattrat_send_fn = vfswrap_getxattrat_send,
3901 .getxattrat_recv_fn = vfswrap_getxattrat_recv,
3902 .fgetxattr_fn = vfswrap_fgetxattr,
3903 .listxattr_fn = vfswrap_listxattr,
3904 .flistxattr_fn = vfswrap_flistxattr,
3905 .removexattr_fn = vfswrap_removexattr,
3906 .fremovexattr_fn = vfswrap_fremovexattr,
3907 .setxattr_fn = vfswrap_setxattr,
3908 .fsetxattr_fn = vfswrap_fsetxattr,
3910 /* aio operations */
3911 .aio_force_fn = vfswrap_aio_force,
3913 /* durable handle operations */
3914 .durable_cookie_fn = vfswrap_durable_cookie,
3915 .durable_disconnect_fn = vfswrap_durable_disconnect,
3916 .durable_reconnect_fn = vfswrap_durable_reconnect,
3920 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3923 * Here we need to implement every call!
3925 * As this is the end of the vfs module chain.
3927 smb_vfs_assert_all_fns(&vfs_default_fns, DEFAULT_VFS_MODULE_NAME);
3928 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3929 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);