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,
575 SMB_STRUCT_STAT *sbuf)
577 struct dirent *result;
579 START_PROFILE(syscall_readdir);
580 result = readdir(dirp);
581 END_PROFILE(syscall_readdir);
583 /* Default Posix readdir() does not give us stat info.
584 * Set to invalid to indicate we didn't return this info. */
585 SET_STAT_INVALID(*sbuf);
586 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
587 if (result != NULL) {
588 /* See if we can efficiently return this. */
590 int flags = AT_SYMLINK_NOFOLLOW;
591 int ret = fstatat(dirfd(dirp),
596 * As this is an optimization,
597 * ignore it if we stat'ed a
598 * symlink. Make the caller
599 * do it again as we don't
600 * know if they wanted the link
601 * info, or its target info.
603 if ((ret == 0) && (!S_ISLNK(st.st_mode))) {
604 init_stat_ex_from_stat(sbuf,
606 lp_fake_directory_create_times(
607 SNUM(handle->conn)));
615 static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
616 const struct smb_filename *fname,
618 struct readdir_attr_data **attr_data)
620 return NT_STATUS_NOT_SUPPORTED;
623 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
625 START_PROFILE(syscall_seekdir);
626 seekdir(dirp, offset);
627 END_PROFILE(syscall_seekdir);
630 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
633 START_PROFILE(syscall_telldir);
634 result = telldir(dirp);
635 END_PROFILE(syscall_telldir);
639 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
641 START_PROFILE(syscall_rewinddir);
643 END_PROFILE(syscall_rewinddir);
646 static int vfswrap_mkdirat(vfs_handle_struct *handle,
647 struct files_struct *dirfsp,
648 const struct smb_filename *smb_fname,
652 struct smb_filename *parent = NULL;
655 START_PROFILE(syscall_mkdirat);
657 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
659 if (lp_inherit_acls(SNUM(handle->conn))) {
660 ok = parent_smb_fname(talloc_tos(), smb_fname, &parent, NULL);
661 if (ok && directory_has_default_acl(handle->conn,
665 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
671 result = mkdirat(fsp_get_pathref_fd(dirfsp), smb_fname->base_name, mode);
673 END_PROFILE(syscall_mkdirat);
677 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
681 START_PROFILE(syscall_closedir);
682 result = closedir(dirp);
683 END_PROFILE(syscall_closedir);
687 /* File operations */
689 static int vfswrap_openat(vfs_handle_struct *handle,
690 const struct files_struct *dirfsp,
691 const struct smb_filename *smb_fname,
698 START_PROFILE(syscall_openat);
700 if (is_named_stream(smb_fname)) {
706 result = openat(fsp_get_pathref_fd(dirfsp),
707 smb_fname->base_name,
712 END_PROFILE(syscall_openat);
715 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
716 struct smb_request *req,
717 struct smb_filename *smb_fname,
718 uint32_t access_mask,
719 uint32_t share_access,
720 uint32_t create_disposition,
721 uint32_t create_options,
722 uint32_t file_attributes,
723 uint32_t oplock_request,
724 const struct smb2_lease *lease,
725 uint64_t allocation_size,
726 uint32_t private_flags,
727 struct security_descriptor *sd,
728 struct ea_list *ea_list,
729 files_struct **result,
731 const struct smb2_create_blobs *in_context_blobs,
732 struct smb2_create_blobs *out_context_blobs)
734 return create_file_default(handle->conn, req, smb_fname,
735 access_mask, share_access,
736 create_disposition, create_options,
737 file_attributes, oplock_request, lease,
738 allocation_size, private_flags,
740 pinfo, in_context_blobs, out_context_blobs);
743 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
747 START_PROFILE(syscall_close);
748 result = fd_close_posix(fsp);
749 END_PROFILE(syscall_close);
753 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
754 size_t n, off_t offset)
758 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
759 START_PROFILE_BYTES(syscall_pread, n);
760 result = sys_pread_full(fsp_get_io_fd(fsp), data, n, offset);
761 END_PROFILE_BYTES(syscall_pread);
763 if (result == -1 && errno == ESPIPE) {
764 /* Maintain the fiction that pipes can be seeked (sought?) on. */
765 result = sys_read(fsp_get_io_fd(fsp), data, n);
766 fh_set_pos(fsp->fh, 0);
769 #else /* HAVE_PREAD */
772 #endif /* HAVE_PREAD */
777 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
778 size_t n, off_t offset)
782 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
783 START_PROFILE_BYTES(syscall_pwrite, n);
784 result = sys_pwrite_full(fsp_get_io_fd(fsp), data, n, offset);
785 END_PROFILE_BYTES(syscall_pwrite);
787 if (result == -1 && errno == ESPIPE) {
788 /* Maintain the fiction that pipes can be sought on. */
789 result = sys_write(fsp_get_io_fd(fsp), data, n);
792 #else /* HAVE_PWRITE */
795 #endif /* HAVE_PWRITE */
800 struct vfswrap_pread_state {
807 struct vfs_aio_state vfs_aio_state;
808 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
811 static void vfs_pread_do(void *private_data);
812 static void vfs_pread_done(struct tevent_req *subreq);
813 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state);
815 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
817 struct tevent_context *ev,
818 struct files_struct *fsp,
820 size_t n, off_t offset)
822 struct tevent_req *req, *subreq;
823 struct vfswrap_pread_state *state;
825 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
831 state->fd = fsp_get_io_fd(fsp);
834 state->offset = offset;
836 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
837 state->profile_bytes, n);
838 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
840 subreq = pthreadpool_tevent_job_send(
841 state, ev, handle->conn->sconn->pool,
842 vfs_pread_do, state);
843 if (tevent_req_nomem(subreq, req)) {
844 return tevent_req_post(req, ev);
846 tevent_req_set_callback(subreq, vfs_pread_done, req);
848 talloc_set_destructor(state, vfs_pread_state_destructor);
853 static void vfs_pread_do(void *private_data)
855 struct vfswrap_pread_state *state = talloc_get_type_abort(
856 private_data, struct vfswrap_pread_state);
857 struct timespec start_time;
858 struct timespec end_time;
860 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
862 PROFILE_TIMESTAMP(&start_time);
864 state->ret = sys_pread_full(state->fd,
869 if (state->ret == -1) {
870 state->vfs_aio_state.error = errno;
873 PROFILE_TIMESTAMP(&end_time);
875 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
877 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
880 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state)
885 static void vfs_pread_done(struct tevent_req *subreq)
887 struct tevent_req *req = tevent_req_callback_data(
888 subreq, struct tevent_req);
889 struct vfswrap_pread_state *state = tevent_req_data(
890 req, struct vfswrap_pread_state);
893 ret = pthreadpool_tevent_job_recv(subreq);
895 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
896 talloc_set_destructor(state, NULL);
899 tevent_req_error(req, ret);
903 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
904 * means the lower level pthreadpool failed to create a new
905 * thread. Fallback to sync processing in that case to allow
906 * some progress for the client.
911 tevent_req_done(req);
914 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
915 struct vfs_aio_state *vfs_aio_state)
917 struct vfswrap_pread_state *state = tevent_req_data(
918 req, struct vfswrap_pread_state);
920 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
924 *vfs_aio_state = state->vfs_aio_state;
928 struct vfswrap_pwrite_state {
935 struct vfs_aio_state vfs_aio_state;
936 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
939 static void vfs_pwrite_do(void *private_data);
940 static void vfs_pwrite_done(struct tevent_req *subreq);
941 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state);
943 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
945 struct tevent_context *ev,
946 struct files_struct *fsp,
948 size_t n, off_t offset)
950 struct tevent_req *req, *subreq;
951 struct vfswrap_pwrite_state *state;
953 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
959 state->fd = fsp_get_io_fd(fsp);
962 state->offset = offset;
964 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
965 state->profile_bytes, n);
966 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
968 subreq = pthreadpool_tevent_job_send(
969 state, ev, handle->conn->sconn->pool,
970 vfs_pwrite_do, state);
971 if (tevent_req_nomem(subreq, req)) {
972 return tevent_req_post(req, ev);
974 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
976 talloc_set_destructor(state, vfs_pwrite_state_destructor);
981 static void vfs_pwrite_do(void *private_data)
983 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
984 private_data, struct vfswrap_pwrite_state);
985 struct timespec start_time;
986 struct timespec end_time;
988 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
990 PROFILE_TIMESTAMP(&start_time);
992 state->ret = sys_pwrite_full(state->fd,
997 if (state->ret == -1) {
998 state->vfs_aio_state.error = errno;
1001 PROFILE_TIMESTAMP(&end_time);
1003 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1005 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1008 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state)
1013 static void vfs_pwrite_done(struct tevent_req *subreq)
1015 struct tevent_req *req = tevent_req_callback_data(
1016 subreq, struct tevent_req);
1017 struct vfswrap_pwrite_state *state = tevent_req_data(
1018 req, struct vfswrap_pwrite_state);
1021 ret = pthreadpool_tevent_job_recv(subreq);
1022 TALLOC_FREE(subreq);
1023 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1024 talloc_set_destructor(state, NULL);
1026 if (ret != EAGAIN) {
1027 tevent_req_error(req, ret);
1031 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1032 * means the lower level pthreadpool failed to create a new
1033 * thread. Fallback to sync processing in that case to allow
1034 * some progress for the client.
1036 vfs_pwrite_do(state);
1039 tevent_req_done(req);
1042 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
1043 struct vfs_aio_state *vfs_aio_state)
1045 struct vfswrap_pwrite_state *state = tevent_req_data(
1046 req, struct vfswrap_pwrite_state);
1048 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1052 *vfs_aio_state = state->vfs_aio_state;
1056 struct vfswrap_fsync_state {
1060 struct vfs_aio_state vfs_aio_state;
1061 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
1064 static void vfs_fsync_do(void *private_data);
1065 static void vfs_fsync_done(struct tevent_req *subreq);
1066 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state);
1068 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
1069 TALLOC_CTX *mem_ctx,
1070 struct tevent_context *ev,
1071 struct files_struct *fsp)
1073 struct tevent_req *req, *subreq;
1074 struct vfswrap_fsync_state *state;
1076 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
1082 state->fd = fsp_get_io_fd(fsp);
1084 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_fsync, profile_p,
1085 state->profile_bytes, 0);
1086 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1088 subreq = pthreadpool_tevent_job_send(
1089 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
1090 if (tevent_req_nomem(subreq, req)) {
1091 return tevent_req_post(req, ev);
1093 tevent_req_set_callback(subreq, vfs_fsync_done, req);
1095 talloc_set_destructor(state, vfs_fsync_state_destructor);
1100 static void vfs_fsync_do(void *private_data)
1102 struct vfswrap_fsync_state *state = talloc_get_type_abort(
1103 private_data, struct vfswrap_fsync_state);
1104 struct timespec start_time;
1105 struct timespec end_time;
1107 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
1109 PROFILE_TIMESTAMP(&start_time);
1112 state->ret = fsync(state->fd);
1113 } while ((state->ret == -1) && (errno == EINTR));
1115 if (state->ret == -1) {
1116 state->vfs_aio_state.error = errno;
1119 PROFILE_TIMESTAMP(&end_time);
1121 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1123 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1126 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state)
1131 static void vfs_fsync_done(struct tevent_req *subreq)
1133 struct tevent_req *req = tevent_req_callback_data(
1134 subreq, struct tevent_req);
1135 struct vfswrap_fsync_state *state = tevent_req_data(
1136 req, struct vfswrap_fsync_state);
1139 ret = pthreadpool_tevent_job_recv(subreq);
1140 TALLOC_FREE(subreq);
1141 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1142 talloc_set_destructor(state, NULL);
1144 if (ret != EAGAIN) {
1145 tevent_req_error(req, ret);
1149 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1150 * means the lower level pthreadpool failed to create a new
1151 * thread. Fallback to sync processing in that case to allow
1152 * some progress for the client.
1154 vfs_fsync_do(state);
1157 tevent_req_done(req);
1160 static int vfswrap_fsync_recv(struct tevent_req *req,
1161 struct vfs_aio_state *vfs_aio_state)
1163 struct vfswrap_fsync_state *state = tevent_req_data(
1164 req, struct vfswrap_fsync_state);
1166 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1170 *vfs_aio_state = state->vfs_aio_state;
1174 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1178 START_PROFILE(syscall_lseek);
1180 result = lseek(fsp_get_io_fd(fsp), offset, whence);
1182 * We want to maintain the fiction that we can seek
1183 * on a fifo for file system purposes. This allows
1184 * people to set up UNIX fifo's that feed data to Windows
1185 * applications. JRA.
1188 if((result == -1) && (errno == ESPIPE)) {
1193 END_PROFILE(syscall_lseek);
1197 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1198 off_t offset, size_t n)
1202 START_PROFILE_BYTES(syscall_sendfile, n);
1203 result = sys_sendfile(tofd, fsp_get_io_fd(fromfsp), hdr, offset, n);
1204 END_PROFILE_BYTES(syscall_sendfile);
1208 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1210 files_struct *tofsp,
1216 START_PROFILE_BYTES(syscall_recvfile, n);
1217 result = sys_recvfile(fromfd, fsp_get_io_fd(tofsp), offset, n);
1218 END_PROFILE_BYTES(syscall_recvfile);
1222 static int vfswrap_renameat(vfs_handle_struct *handle,
1223 files_struct *srcfsp,
1224 const struct smb_filename *smb_fname_src,
1225 files_struct *dstfsp,
1226 const struct smb_filename *smb_fname_dst)
1230 START_PROFILE(syscall_renameat);
1232 if (is_named_stream(smb_fname_src) || is_named_stream(smb_fname_dst)) {
1237 result = renameat(fsp_get_pathref_fd(srcfsp),
1238 smb_fname_src->base_name,
1239 fsp_get_pathref_fd(dstfsp),
1240 smb_fname_dst->base_name);
1243 END_PROFILE(syscall_renameat);
1247 static int vfswrap_stat(vfs_handle_struct *handle,
1248 struct smb_filename *smb_fname)
1252 START_PROFILE(syscall_stat);
1254 if (is_named_stream(smb_fname)) {
1259 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1260 lp_fake_directory_create_times(SNUM(handle->conn)));
1262 END_PROFILE(syscall_stat);
1266 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1270 START_PROFILE(syscall_fstat);
1271 result = sys_fstat(fsp_get_pathref_fd(fsp),
1272 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1273 END_PROFILE(syscall_fstat);
1277 static int vfswrap_lstat(vfs_handle_struct *handle,
1278 struct smb_filename *smb_fname)
1282 START_PROFILE(syscall_lstat);
1284 if (is_named_stream(smb_fname)) {
1289 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1290 lp_fake_directory_create_times(SNUM(handle->conn)));
1292 END_PROFILE(syscall_lstat);
1296 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1298 enum vfs_translate_direction direction,
1299 TALLOC_CTX *mem_ctx,
1302 return NT_STATUS_NONE_MAPPED;
1306 * Implement the default fsctl operation.
1308 static bool vfswrap_logged_ioctl_message = false;
1310 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1311 struct files_struct *fsp,
1314 uint16_t req_flags, /* Needed for UNICODE ... */
1315 const uint8_t *_in_data,
1317 uint8_t **_out_data,
1318 uint32_t max_out_len,
1321 const char *in_data = (const char *)_in_data;
1322 char **out_data = (char **)_out_data;
1326 case FSCTL_SET_SPARSE:
1328 bool set_sparse = true;
1330 if (in_len >= 1 && in_data[0] == 0) {
1334 status = file_set_sparse(handle->conn, fsp, set_sparse);
1336 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1337 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1338 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1339 nt_errstr(status)));
1344 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1346 unsigned char objid[16];
1347 char *return_data = NULL;
1349 /* This should return the object-id on this file.
1350 * I think I'll make this be the inode+dev. JRA.
1353 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1354 fsp_fnum_dbg(fsp)));
1356 *out_len = MIN(max_out_len, 64);
1358 /* Hmmm, will this cause problems if less data asked for? */
1359 return_data = talloc_array(ctx, char, 64);
1360 if (return_data == NULL) {
1361 return NT_STATUS_NO_MEMORY;
1364 /* For backwards compatibility only store the dev/inode. */
1365 push_file_id_16(return_data, &fsp->file_id);
1366 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1367 push_file_id_16(return_data+32, &fsp->file_id);
1368 memset(return_data+48, 0, 16);
1369 *out_data = return_data;
1370 return NT_STATUS_OK;
1373 case FSCTL_GET_REPARSE_POINT:
1375 status = fsctl_get_reparse_point(
1376 fsp, ctx, out_data, max_out_len, out_len);
1380 case FSCTL_SET_REPARSE_POINT:
1382 status = fsctl_set_reparse_point(fsp, ctx, _in_data, in_len);
1386 case FSCTL_DELETE_REPARSE_POINT:
1388 status = fsctl_del_reparse_point(fsp, ctx, _in_data, in_len);
1392 case FSCTL_GET_SHADOW_COPY_DATA:
1395 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1396 * and return their volume names. If max_data_count is 16, then it is just
1397 * asking for the number of volumes and length of the combined names.
1399 * pdata is the data allocated by our caller, but that uses
1400 * total_data_count (which is 0 in our case) rather than max_data_count.
1401 * Allocate the correct amount and return the pointer to let
1402 * it be deallocated when we return.
1404 struct shadow_copy_data *shadow_data = NULL;
1405 bool labels = False;
1406 uint32_t labels_data_count = 0;
1408 char *cur_pdata = NULL;
1410 if (max_out_len < 16) {
1411 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1413 return NT_STATUS_INVALID_PARAMETER;
1416 if (max_out_len > 16) {
1420 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1421 if (shadow_data == NULL) {
1422 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1423 return NT_STATUS_NO_MEMORY;
1427 * Call the VFS routine to actually do the work.
1429 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1432 /* broken module didn't set errno on error */
1433 status = NT_STATUS_UNSUCCESSFUL;
1435 status = map_nt_error_from_unix(errno);
1436 if (NT_STATUS_EQUAL(status,
1437 NT_STATUS_NOT_SUPPORTED)) {
1441 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1442 "connectpath %s, failed - %s.\n",
1443 fsp->conn->connectpath,
1444 nt_errstr(status)));
1445 TALLOC_FREE(shadow_data);
1449 labels_data_count = (shadow_data->num_volumes * 2 *
1450 sizeof(SHADOW_COPY_LABEL)) + 2;
1455 *out_len = 12 + labels_data_count;
1458 if (max_out_len < *out_len) {
1459 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1460 max_out_len, *out_len));
1461 TALLOC_FREE(shadow_data);
1462 return NT_STATUS_BUFFER_TOO_SMALL;
1465 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1466 if (cur_pdata == NULL) {
1467 TALLOC_FREE(shadow_data);
1468 return NT_STATUS_NO_MEMORY;
1471 *out_data = cur_pdata;
1473 /* num_volumes 4 bytes */
1474 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1477 /* num_labels 4 bytes */
1478 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1481 /* needed_data_count 4 bytes */
1482 SIVAL(cur_pdata, 8, labels_data_count);
1486 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1487 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1488 if (labels && shadow_data->labels) {
1489 for (i=0; i<shadow_data->num_volumes; i++) {
1491 status = srvstr_push(cur_pdata, req_flags,
1492 cur_pdata, shadow_data->labels[i],
1493 2 * sizeof(SHADOW_COPY_LABEL),
1494 STR_UNICODE|STR_TERMINATE, &len);
1495 if (!NT_STATUS_IS_OK(status)) {
1496 TALLOC_FREE(*out_data);
1497 TALLOC_FREE(shadow_data);
1500 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1501 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1505 TALLOC_FREE(shadow_data);
1507 return NT_STATUS_OK;
1510 case FSCTL_FIND_FILES_BY_SID:
1512 /* pretend this succeeded -
1514 * we have to send back a list with all files owned by this SID
1516 * but I have to check that --metze
1520 struct dom_sid_buf buf;
1524 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1525 fsp_fnum_dbg(fsp)));
1528 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1529 return NT_STATUS_INVALID_PARAMETER;
1532 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1534 /* unknown 4 bytes: this is not the length of the sid :-( */
1535 /*unknown = IVAL(pdata,0);*/
1537 ret = sid_parse(_in_data + 4, sid_len, &sid);
1539 return NT_STATUS_INVALID_PARAMETER;
1541 DEBUGADD(10, ("for SID: %s\n",
1542 dom_sid_str_buf(&sid, &buf)));
1544 if (!sid_to_uid(&sid, &uid)) {
1545 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1546 dom_sid_str_buf(&sid, &buf),
1547 (unsigned long)sid_len));
1551 /* we can take a look at the find source :-)
1553 * find ./ -uid $uid -name '*' is what we need here
1556 * and send 4bytes len and then NULL terminated unicode strings
1559 * but I don't know how to deal with the paged results
1560 * (maybe we can hang the result anywhere in the fsp struct)
1562 * but I don't know how to deal with the paged results
1563 * (maybe we can hang the result anywhere in the fsp struct)
1565 * we don't send all files at once
1566 * and at the next we should *not* start from the beginning,
1567 * so we have to cache the result
1572 /* this works for now... */
1573 return NT_STATUS_OK;
1576 case FSCTL_QUERY_ALLOCATED_RANGES:
1578 /* FIXME: This is just a dummy reply, telling that all of the
1579 * file is allocated. MKS cp needs that.
1580 * Adding the real allocated ranges via FIEMAP on Linux
1581 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1582 * this FSCTL correct for sparse files.
1584 uint64_t offset, length;
1585 char *out_data_tmp = NULL;
1588 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1590 return NT_STATUS_INVALID_PARAMETER;
1593 if (max_out_len < 16) {
1594 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1596 return NT_STATUS_INVALID_PARAMETER;
1599 offset = BVAL(in_data,0);
1600 length = BVAL(in_data,8);
1602 if (offset + length < offset) {
1603 /* No 64-bit integer wrap. */
1604 return NT_STATUS_INVALID_PARAMETER;
1607 /* Shouldn't this be SMB_VFS_STAT ... ? */
1608 status = vfs_stat_fsp(fsp);
1609 if (!NT_STATUS_IS_OK(status)) {
1614 out_data_tmp = talloc_array(ctx, char, *out_len);
1615 if (out_data_tmp == NULL) {
1616 DEBUG(10, ("unable to allocate memory for response\n"));
1617 return NT_STATUS_NO_MEMORY;
1620 if (offset > fsp->fsp_name->st.st_ex_size ||
1621 fsp->fsp_name->st.st_ex_size == 0 ||
1623 memset(out_data_tmp, 0, *out_len);
1625 uint64_t end = offset + length;
1626 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1627 SBVAL(out_data_tmp, 0, 0);
1628 SBVAL(out_data_tmp, 8, end);
1631 *out_data = out_data_tmp;
1633 return NT_STATUS_OK;
1636 case FSCTL_IS_VOLUME_DIRTY:
1638 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1639 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1641 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1642 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1644 return NT_STATUS_INVALID_PARAMETER;
1649 * Only print once ... unfortunately there could be lots of
1650 * different FSCTLs that are called.
1652 if (!vfswrap_logged_ioctl_message) {
1653 vfswrap_logged_ioctl_message = true;
1654 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1655 __func__, function));
1659 return NT_STATUS_NOT_SUPPORTED;
1662 static bool vfswrap_is_offline(struct connection_struct *conn,
1663 const struct smb_filename *fname);
1665 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1666 struct smb_filename *smb_fname,
1671 offline = vfswrap_is_offline(handle->conn, smb_fname);
1673 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1676 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1679 struct vfswrap_get_dos_attributes_state {
1680 struct vfs_aio_state aio_state;
1681 connection_struct *conn;
1682 TALLOC_CTX *mem_ctx;
1683 struct tevent_context *ev;
1684 files_struct *dir_fsp;
1685 struct smb_filename *smb_fname;
1690 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq);
1692 static struct tevent_req *vfswrap_get_dos_attributes_send(
1693 TALLOC_CTX *mem_ctx,
1694 struct tevent_context *ev,
1695 struct vfs_handle_struct *handle,
1696 files_struct *dir_fsp,
1697 struct smb_filename *smb_fname)
1699 struct tevent_req *req = NULL;
1700 struct tevent_req *subreq = NULL;
1701 struct vfswrap_get_dos_attributes_state *state = NULL;
1703 req = tevent_req_create(mem_ctx, &state,
1704 struct vfswrap_get_dos_attributes_state);
1709 *state = (struct vfswrap_get_dos_attributes_state) {
1710 .conn = dir_fsp->conn,
1714 .smb_fname = smb_fname,
1717 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1721 SAMBA_XATTR_DOS_ATTRIB,
1723 if (tevent_req_nomem(subreq, req)) {
1724 return tevent_req_post(req, ev);
1726 tevent_req_set_callback(subreq,
1727 vfswrap_get_dos_attributes_getxattr_done,
1733 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq)
1735 struct tevent_req *req =
1736 tevent_req_callback_data(subreq,
1738 struct vfswrap_get_dos_attributes_state *state =
1739 tevent_req_data(req,
1740 struct vfswrap_get_dos_attributes_state);
1742 DATA_BLOB blob = {0};
1744 char *tofree = NULL;
1745 char pathbuf[PATH_MAX+1];
1747 struct smb_filename smb_fname;
1751 xattr_size = SMB_VFS_GETXATTRAT_RECV(subreq,
1755 TALLOC_FREE(subreq);
1756 if (xattr_size == -1) {
1757 status = map_nt_error_from_unix(state->aio_state.error);
1759 if (state->as_root) {
1760 tevent_req_nterror(req, status);
1763 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1764 tevent_req_nterror(req, status);
1768 state->as_root = true;
1771 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1775 SAMBA_XATTR_DOS_ATTRIB,
1778 if (tevent_req_nomem(subreq, req)) {
1781 tevent_req_set_callback(subreq,
1782 vfswrap_get_dos_attributes_getxattr_done,
1787 blob.length = xattr_size;
1789 status = parse_dos_attribute_blob(state->smb_fname,
1792 if (!NT_STATUS_IS_OK(status)) {
1793 tevent_req_nterror(req, status);
1797 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
1798 state->smb_fname->base_name,
1803 if (pathlen == -1) {
1804 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1808 smb_fname = (struct smb_filename) {
1810 .st = state->smb_fname->st,
1811 .flags = state->smb_fname->flags,
1812 .twrp = state->smb_fname->twrp,
1815 offline = vfswrap_is_offline(state->conn, &smb_fname);
1817 state->dosmode |= FILE_ATTRIBUTE_OFFLINE;
1819 TALLOC_FREE(tofree);
1821 tevent_req_done(req);
1825 static NTSTATUS vfswrap_get_dos_attributes_recv(struct tevent_req *req,
1826 struct vfs_aio_state *aio_state,
1829 struct vfswrap_get_dos_attributes_state *state =
1830 tevent_req_data(req,
1831 struct vfswrap_get_dos_attributes_state);
1834 if (tevent_req_is_nterror(req, &status)) {
1835 tevent_req_received(req);
1839 *aio_state = state->aio_state;
1840 *dosmode = state->dosmode;
1841 tevent_req_received(req);
1842 return NT_STATUS_OK;
1845 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1846 struct files_struct *fsp,
1851 offline = vfswrap_is_offline(handle->conn, fsp->fsp_name);
1853 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1856 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1859 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1860 const struct smb_filename *smb_fname,
1863 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1866 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1867 struct files_struct *fsp,
1870 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1873 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1875 struct vfswrap_offload_read_state {
1879 static struct tevent_req *vfswrap_offload_read_send(
1880 TALLOC_CTX *mem_ctx,
1881 struct tevent_context *ev,
1882 struct vfs_handle_struct *handle,
1883 struct files_struct *fsp,
1889 struct tevent_req *req = NULL;
1890 struct vfswrap_offload_read_state *state = NULL;
1893 req = tevent_req_create(mem_ctx, &state,
1894 struct vfswrap_offload_read_state);
1899 status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1900 &vfswrap_offload_ctx);
1901 if (tevent_req_nterror(req, status)) {
1902 return tevent_req_post(req, ev);
1905 if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1906 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1907 return tevent_req_post(req, ev);
1910 status = vfs_offload_token_create_blob(state, fsp, fsctl,
1912 if (tevent_req_nterror(req, status)) {
1913 return tevent_req_post(req, ev);
1916 status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1918 if (tevent_req_nterror(req, status)) {
1919 return tevent_req_post(req, ev);
1922 tevent_req_done(req);
1923 return tevent_req_post(req, ev);
1926 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
1927 struct vfs_handle_struct *handle,
1928 TALLOC_CTX *mem_ctx,
1931 struct vfswrap_offload_read_state *state = tevent_req_data(
1932 req, struct vfswrap_offload_read_state);
1935 if (tevent_req_is_nterror(req, &status)) {
1936 tevent_req_received(req);
1940 token->length = state->token.length;
1941 token->data = talloc_move(mem_ctx, &state->token.data);
1943 tevent_req_received(req);
1944 return NT_STATUS_OK;
1947 struct vfswrap_offload_write_state {
1949 bool read_lck_locked;
1950 bool write_lck_locked;
1952 struct tevent_context *src_ev;
1953 struct files_struct *src_fsp;
1955 struct tevent_context *dst_ev;
1956 struct files_struct *dst_fsp;
1960 size_t next_io_size;
1963 static void vfswrap_offload_write_cleanup(struct tevent_req *req,
1964 enum tevent_req_state req_state)
1966 struct vfswrap_offload_write_state *state = tevent_req_data(
1967 req, struct vfswrap_offload_write_state);
1970 if (state->dst_fsp == NULL) {
1974 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
1976 state->dst_fsp = NULL;
1979 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
1981 static struct tevent_req *vfswrap_offload_write_send(
1982 struct vfs_handle_struct *handle,
1983 TALLOC_CTX *mem_ctx,
1984 struct tevent_context *ev,
1987 off_t transfer_offset,
1988 struct files_struct *dest_fsp,
1992 struct tevent_req *req;
1993 struct vfswrap_offload_write_state *state = NULL;
1994 /* off_t is signed! */
1995 off_t max_offset = INT64_MAX - to_copy;
1996 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
1997 files_struct *src_fsp = NULL;
2001 req = tevent_req_create(mem_ctx, &state,
2002 struct vfswrap_offload_write_state);
2007 *state = (struct vfswrap_offload_write_state) {
2009 .src_off = transfer_offset,
2011 .dst_fsp = dest_fsp,
2012 .dst_off = dest_off,
2014 .remaining = to_copy,
2017 tevent_req_set_cleanup_fn(req, vfswrap_offload_write_cleanup);
2020 case FSCTL_SRV_COPYCHUNK:
2021 case FSCTL_SRV_COPYCHUNK_WRITE:
2024 case FSCTL_OFFLOAD_WRITE:
2025 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
2026 return tevent_req_post(req, ev);
2028 case FSCTL_DUP_EXTENTS_TO_FILE:
2029 DBG_DEBUG("COW clones not supported by vfs_default\n");
2030 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2031 return tevent_req_post(req, ev);
2034 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2035 return tevent_req_post(req, ev);
2039 * From here on we assume a copy-chunk fsctl
2043 tevent_req_done(req);
2044 return tevent_req_post(req, ev);
2047 if (state->src_off > max_offset) {
2049 * Protect integer checks below.
2051 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2052 return tevent_req_post(req, ev);
2054 if (state->src_off < 0) {
2056 * Protect integer checks below.
2058 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2059 return tevent_req_post(req, ev);
2061 if (state->dst_off > max_offset) {
2063 * Protect integer checks below.
2065 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2066 return tevent_req_post(req, ev);
2068 if (state->dst_off < 0) {
2070 * Protect integer checks below.
2072 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2073 return tevent_req_post(req, ev);
2076 status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
2078 if (tevent_req_nterror(req, status)) {
2079 return tevent_req_post(req, ev);
2082 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
2084 status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
2085 if (!NT_STATUS_IS_OK(status)) {
2086 tevent_req_nterror(req, status);
2087 return tevent_req_post(req, ev);
2090 ok = change_to_user_and_service_by_fsp(src_fsp);
2092 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2093 return tevent_req_post(req, ev);
2096 state->src_ev = src_fsp->conn->sconn->ev_ctx;
2097 state->src_fsp = src_fsp;
2099 status = vfs_stat_fsp(src_fsp);
2100 if (tevent_req_nterror(req, status)) {
2101 return tevent_req_post(req, ev);
2104 if (src_fsp->fsp_name->st.st_ex_size < state->src_off + to_copy) {
2106 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
2107 * If the SourceOffset or SourceOffset + Length extends beyond
2108 * the end of file, the server SHOULD<240> treat this as a
2109 * STATUS_END_OF_FILE error.
2111 * <240> Section 3.3.5.15.6: Windows servers will return
2112 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
2114 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
2115 return tevent_req_post(req, ev);
2118 state->buf = talloc_array(state, uint8_t, num);
2119 if (tevent_req_nomem(state->buf, req)) {
2120 return tevent_req_post(req, ev);
2123 status = vfswrap_offload_write_loop(req);
2124 if (!NT_STATUS_IS_OK(status)) {
2125 tevent_req_nterror(req, status);
2126 return tevent_req_post(req, ev);
2132 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
2134 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
2136 struct vfswrap_offload_write_state *state = tevent_req_data(
2137 req, struct vfswrap_offload_write_state);
2138 struct tevent_req *subreq = NULL;
2139 struct lock_struct read_lck;
2143 * This is called under the context of state->src_fsp.
2146 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
2148 init_strict_lock_struct(state->src_fsp,
2149 state->src_fsp->op->global->open_persistent_id,
2151 state->next_io_size,
2155 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
2159 return NT_STATUS_FILE_LOCK_CONFLICT;
2162 subreq = SMB_VFS_PREAD_SEND(state,
2166 state->next_io_size,
2168 if (subreq == NULL) {
2169 return NT_STATUS_NO_MEMORY;
2171 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
2173 return NT_STATUS_OK;
2176 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
2178 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
2180 struct tevent_req *req = tevent_req_callback_data(
2181 subreq, struct tevent_req);
2182 struct vfswrap_offload_write_state *state = tevent_req_data(
2183 req, struct vfswrap_offload_write_state);
2184 struct vfs_aio_state aio_state;
2185 struct lock_struct write_lck;
2189 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
2190 TALLOC_FREE(subreq);
2192 DBG_ERR("read failed: %s\n", strerror(aio_state.error));
2193 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2196 if (nread != state->next_io_size) {
2197 DBG_ERR("Short read, only %zd of %zu\n",
2198 nread, state->next_io_size);
2199 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2203 state->src_off += nread;
2205 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2207 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2211 init_strict_lock_struct(state->dst_fsp,
2212 state->dst_fsp->op->global->open_persistent_id,
2214 state->next_io_size,
2218 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
2222 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
2226 subreq = SMB_VFS_PWRITE_SEND(state,
2230 state->next_io_size,
2232 if (subreq == NULL) {
2233 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2236 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
2239 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
2241 struct tevent_req *req = tevent_req_callback_data(
2242 subreq, struct tevent_req);
2243 struct vfswrap_offload_write_state *state = tevent_req_data(
2244 req, struct vfswrap_offload_write_state);
2245 struct vfs_aio_state aio_state;
2250 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
2251 TALLOC_FREE(subreq);
2252 if (nwritten == -1) {
2253 DBG_ERR("write failed: %s\n", strerror(aio_state.error));
2254 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2257 if (nwritten != state->next_io_size) {
2258 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
2259 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2263 state->dst_off += nwritten;
2265 if (state->remaining < nwritten) {
2266 /* Paranoia check */
2267 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2270 state->remaining -= nwritten;
2271 if (state->remaining == 0) {
2272 tevent_req_done(req);
2276 ok = change_to_user_and_service_by_fsp(state->src_fsp);
2278 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2282 status = vfswrap_offload_write_loop(req);
2283 if (!NT_STATUS_IS_OK(status)) {
2284 tevent_req_nterror(req, status);
2291 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
2292 struct tevent_req *req,
2295 struct vfswrap_offload_write_state *state = tevent_req_data(
2296 req, struct vfswrap_offload_write_state);
2299 if (tevent_req_is_nterror(req, &status)) {
2300 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
2302 tevent_req_received(req);
2306 *copied = state->to_copy;
2307 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
2308 tevent_req_received(req);
2310 return NT_STATUS_OK;
2313 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
2314 TALLOC_CTX *mem_ctx,
2315 struct files_struct *fsp,
2316 struct smb_filename *smb_fname,
2317 uint16_t *_compression_fmt)
2319 return NT_STATUS_INVALID_DEVICE_REQUEST;
2322 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
2323 TALLOC_CTX *mem_ctx,
2324 struct files_struct *fsp,
2325 uint16_t compression_fmt)
2327 return NT_STATUS_INVALID_DEVICE_REQUEST;
2330 /********************************************************************
2331 Given a stat buffer return the allocated size on disk, taking into
2332 account sparse files.
2333 ********************************************************************/
2334 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
2335 struct files_struct *fsp,
2336 const SMB_STRUCT_STAT *sbuf)
2340 START_PROFILE(syscall_get_alloc_size);
2342 if(S_ISDIR(sbuf->st_ex_mode)) {
2347 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2348 /* The type of st_blocksize is blkcnt_t which *MUST* be
2349 signed (according to POSIX) and can be less than 64-bits.
2350 Ensure when we're converting to 64 bits wide we don't
2352 #if defined(SIZEOF_BLKCNT_T_8)
2353 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2354 #elif defined(SIZEOF_BLKCNT_T_4)
2356 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2357 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2360 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2364 * Some file systems do not allocate a block for very
2365 * small files. But for non-empty file should report a
2369 uint64_t filesize = get_file_size_stat(sbuf);
2371 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2375 result = get_file_size_stat(sbuf);
2378 if (fsp && fsp->initial_allocation_size)
2379 result = MAX(result,fsp->initial_allocation_size);
2381 result = smb_roundup(handle->conn, result);
2384 END_PROFILE(syscall_get_alloc_size);
2388 static int vfswrap_unlinkat(vfs_handle_struct *handle,
2389 struct files_struct *dirfsp,
2390 const struct smb_filename *smb_fname,
2395 START_PROFILE(syscall_unlinkat);
2397 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2399 if (is_named_stream(smb_fname)) {
2403 result = unlinkat(fsp_get_pathref_fd(dirfsp),
2404 smb_fname->base_name,
2408 END_PROFILE(syscall_unlinkat);
2412 static int vfswrap_chmod(vfs_handle_struct *handle,
2413 const struct smb_filename *smb_fname,
2418 START_PROFILE(syscall_chmod);
2419 result = chmod(smb_fname->base_name, mode);
2420 END_PROFILE(syscall_chmod);
2424 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2428 START_PROFILE(syscall_fchmod);
2429 #if defined(HAVE_FCHMOD)
2430 result = fchmod(fsp_get_io_fd(fsp), mode);
2436 END_PROFILE(syscall_fchmod);
2440 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2445 START_PROFILE(syscall_fchown);
2446 result = fchown(fsp_get_io_fd(fsp), uid, gid);
2447 END_PROFILE(syscall_fchown);
2455 static int vfswrap_lchown(vfs_handle_struct *handle,
2456 const struct smb_filename *smb_fname,
2462 START_PROFILE(syscall_lchown);
2463 result = lchown(smb_fname->base_name, uid, gid);
2464 END_PROFILE(syscall_lchown);
2468 static int vfswrap_chdir(vfs_handle_struct *handle,
2469 const struct smb_filename *smb_fname)
2473 START_PROFILE(syscall_chdir);
2474 result = chdir(smb_fname->base_name);
2475 END_PROFILE(syscall_chdir);
2479 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2483 struct smb_filename *smb_fname = NULL;
2485 START_PROFILE(syscall_getwd);
2486 result = sys_getwd();
2487 END_PROFILE(syscall_getwd);
2489 if (result == NULL) {
2492 smb_fname = synthetic_smb_fname(ctx,
2499 * sys_getwd() *always* returns malloced memory.
2500 * We must free here to avoid leaks:
2501 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2507 /*********************************************************************
2508 nsec timestamp resolution call. Convert down to whatever the underlying
2509 system will support.
2510 **********************************************************************/
2512 static int vfswrap_ntimes(vfs_handle_struct *handle,
2513 const struct smb_filename *smb_fname,
2514 struct smb_file_time *ft)
2518 START_PROFILE(syscall_ntimes);
2520 if (is_named_stream(smb_fname)) {
2526 if (is_omit_timespec(&ft->atime)) {
2527 ft->atime= smb_fname->st.st_ex_atime;
2530 if (is_omit_timespec(&ft->mtime)) {
2531 ft->mtime = smb_fname->st.st_ex_mtime;
2534 if (!is_omit_timespec(&ft->create_time)) {
2535 set_create_timespec_ea(handle->conn,
2540 if ((timespec_compare(&ft->atime,
2541 &smb_fname->st.st_ex_atime) == 0) &&
2542 (timespec_compare(&ft->mtime,
2543 &smb_fname->st.st_ex_mtime) == 0)) {
2548 #if defined(HAVE_UTIMENSAT)
2550 struct timespec ts[2];
2553 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2555 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2557 if (!((result == -1) && (errno == ENOSYS))) {
2561 #if defined(HAVE_UTIMES)
2563 struct timeval tv[2];
2564 tv[0] = convert_timespec_to_timeval(ft->atime);
2565 tv[1] = convert_timespec_to_timeval(ft->mtime);
2566 result = utimes(smb_fname->base_name, tv);
2568 result = utimes(smb_fname->base_name, NULL);
2570 if (!((result == -1) && (errno == ENOSYS))) {
2574 #if defined(HAVE_UTIME)
2576 struct utimbuf times;
2577 times.actime = convert_timespec_to_time_t(ft->atime);
2578 times.modtime = convert_timespec_to_time_t(ft->mtime);
2579 result = utime(smb_fname->base_name, ×);
2581 result = utime(smb_fname->base_name, NULL);
2583 if (!((result == -1) && (errno == ENOSYS))) {
2591 END_PROFILE(syscall_ntimes);
2595 /*********************************************************************
2596 A version of ftruncate that will write the space on disk if strict
2598 **********************************************************************/
2600 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2602 off_t space_to_write;
2603 uint64_t space_avail;
2604 uint64_t bsize,dfree,dsize;
2607 SMB_STRUCT_STAT *pst;
2610 ok = vfs_valid_pwrite_range(len, 0);
2616 status = vfs_stat_fsp(fsp);
2617 if (!NT_STATUS_IS_OK(status)) {
2620 pst = &fsp->fsp_name->st;
2623 if (S_ISFIFO(pst->st_ex_mode))
2627 if (pst->st_ex_size == len)
2630 /* Shrink - just ftruncate. */
2631 if (pst->st_ex_size > len)
2632 return ftruncate(fsp_get_io_fd(fsp), len);
2634 space_to_write = len - pst->st_ex_size;
2636 /* for allocation try fallocate first. This can fail on some
2637 platforms e.g. when the filesystem doesn't support it and no
2638 emulation is being done by the libc (like on AIX with JFS1). In that
2639 case we do our own emulation. fallocate implementations can
2640 return ENOTSUP or EINVAL in cases like that. */
2641 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2642 if (ret == -1 && errno == ENOSPC) {
2648 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2649 "error %d. Falling back to slow manual allocation\n", errno));
2651 /* available disk space is enough or not? */
2653 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2654 /* space_avail is 1k blocks */
2655 if (space_avail == (uint64_t)-1 ||
2656 ((uint64_t)space_to_write/1024 > space_avail) ) {
2661 /* Write out the real space on disk. */
2662 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2670 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2673 SMB_STRUCT_STAT *pst;
2677 START_PROFILE(syscall_ftruncate);
2679 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->fsp_flags.is_sparse) {
2680 result = strict_allocate_ftruncate(handle, fsp, len);
2681 END_PROFILE(syscall_ftruncate);
2685 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2686 ftruncate if the system supports it. Then I discovered that
2687 you can have some filesystems that support ftruncate
2688 expansion and some that don't! On Linux fat can't do
2689 ftruncate extend but ext2 can. */
2691 result = ftruncate(fsp_get_io_fd(fsp), len);
2693 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2694 extend a file with ftruncate. Provide alternate implementation
2697 /* Do an fstat to see if the file is longer than the requested
2698 size in which case the ftruncate above should have
2699 succeeded or shorter, in which case seek to len - 1 and
2700 write 1 byte of zero */
2701 status = vfs_stat_fsp(fsp);
2702 if (!NT_STATUS_IS_OK(status)) {
2706 /* We need to update the files_struct after successful ftruncate */
2711 pst = &fsp->fsp_name->st;
2714 if (S_ISFIFO(pst->st_ex_mode)) {
2720 if (pst->st_ex_size == len) {
2725 if (pst->st_ex_size > len) {
2726 /* the ftruncate should have worked */
2730 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2738 END_PROFILE(syscall_ftruncate);
2742 static int vfswrap_fallocate(vfs_handle_struct *handle,
2750 START_PROFILE(syscall_fallocate);
2752 result = sys_posix_fallocate(fsp_get_io_fd(fsp), offset, len);
2754 * posix_fallocate returns 0 on success, errno on error
2755 * and doesn't set errno. Make it behave like fallocate()
2756 * which returns -1, and sets errno on failure.
2763 /* sys_fallocate handles filtering of unsupported mode flags */
2764 result = sys_fallocate(fsp_get_io_fd(fsp), mode, offset, len);
2766 END_PROFILE(syscall_fallocate);
2770 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2774 START_PROFILE(syscall_fcntl_lock);
2776 if (fsp->fsp_flags.use_ofd_locks) {
2777 op = map_process_lock_to_ofd_lock(op);
2780 result = fcntl_lock(fsp_get_io_fd(fsp), op, offset, count, type);
2781 END_PROFILE(syscall_fcntl_lock);
2785 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2786 uint32_t share_access, uint32_t access_mask)
2788 START_PROFILE(syscall_kernel_flock);
2789 kernel_flock(fsp_get_io_fd(fsp), share_access, access_mask);
2790 END_PROFILE(syscall_kernel_flock);
2794 static int vfswrap_fcntl(vfs_handle_struct *handle, files_struct *fsp, int cmd,
2798 va_list dup_cmd_arg;
2802 START_PROFILE(syscall_fcntl);
2804 va_copy(dup_cmd_arg, cmd_arg);
2810 #if defined(HAVE_OFD_LOCKS)
2815 #if defined(HAVE_F_OWNER_EX)
2819 #if defined(HAVE_RW_HINTS)
2822 case F_GET_FILE_RW_HINT:
2823 case F_SET_FILE_RW_HINT:
2825 argp = va_arg(dup_cmd_arg, void *);
2826 result = sys_fcntl_ptr(fsp_get_io_fd(fsp), cmd, argp);
2829 val = va_arg(dup_cmd_arg, int);
2830 result = sys_fcntl_int(fsp_get_io_fd(fsp), cmd, val);
2833 va_end(dup_cmd_arg);
2835 END_PROFILE(syscall_fcntl);
2839 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2844 START_PROFILE(syscall_fcntl_getlock);
2846 if (fsp->fsp_flags.use_ofd_locks) {
2847 op = map_process_lock_to_ofd_lock(op);
2850 result = fcntl_getlock(fsp_get_io_fd(fsp), op, poffset, pcount, ptype, ppid);
2851 END_PROFILE(syscall_fcntl_getlock);
2855 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2860 START_PROFILE(syscall_linux_setlease);
2862 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2863 result = linux_setlease(fsp_get_io_fd(fsp), leasetype);
2867 END_PROFILE(syscall_linux_setlease);
2871 static int vfswrap_symlinkat(vfs_handle_struct *handle,
2872 const struct smb_filename *link_target,
2873 struct files_struct *dirfsp,
2874 const struct smb_filename *new_smb_fname)
2878 START_PROFILE(syscall_symlinkat);
2880 result = symlinkat(link_target->base_name,
2881 fsp_get_pathref_fd(dirfsp),
2882 new_smb_fname->base_name);
2883 END_PROFILE(syscall_symlinkat);
2887 static int vfswrap_readlinkat(vfs_handle_struct *handle,
2888 const struct files_struct *dirfsp,
2889 const struct smb_filename *smb_fname,
2895 START_PROFILE(syscall_readlinkat);
2897 result = readlinkat(fsp_get_pathref_fd(dirfsp),
2898 smb_fname->base_name,
2902 END_PROFILE(syscall_readlinkat);
2906 static int vfswrap_linkat(vfs_handle_struct *handle,
2907 files_struct *srcfsp,
2908 const struct smb_filename *old_smb_fname,
2909 files_struct *dstfsp,
2910 const struct smb_filename *new_smb_fname,
2915 START_PROFILE(syscall_linkat);
2917 result = linkat(fsp_get_pathref_fd(srcfsp),
2918 old_smb_fname->base_name,
2919 fsp_get_pathref_fd(dstfsp),
2920 new_smb_fname->base_name,
2923 END_PROFILE(syscall_linkat);
2927 static int vfswrap_mknodat(vfs_handle_struct *handle,
2928 files_struct *dirfsp,
2929 const struct smb_filename *smb_fname,
2935 START_PROFILE(syscall_mknodat);
2937 result = sys_mknodat(fsp_get_pathref_fd(dirfsp),
2938 smb_fname->base_name,
2942 END_PROFILE(syscall_mknodat);
2946 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2948 const struct smb_filename *smb_fname)
2951 struct smb_filename *result_fname = NULL;
2953 START_PROFILE(syscall_realpath);
2954 result = sys_realpath(smb_fname->base_name);
2955 END_PROFILE(syscall_realpath);
2957 result_fname = synthetic_smb_fname(ctx,
2965 return result_fname;
2968 static int vfswrap_chflags(vfs_handle_struct *handle,
2969 const struct smb_filename *smb_fname,
2973 return chflags(smb_fname->base_name, flags);
2980 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2981 const SMB_STRUCT_STAT *sbuf)
2985 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2989 key.devid = sbuf->st_ex_dev;
2990 key.inode = sbuf->st_ex_ino;
2991 /* key.extid is unused by default. */
2996 static uint64_t vfswrap_fs_file_id(struct vfs_handle_struct *handle,
2997 const SMB_STRUCT_STAT *psbuf)
3001 if (!(psbuf->st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)) {
3002 return psbuf->st_ex_file_id;
3005 if (handle->conn->base_share_dev == psbuf->st_ex_dev) {
3006 return (uint64_t)psbuf->st_ex_ino;
3010 file_id = ((psbuf->st_ex_ino) & UINT32_MAX);
3013 file_id |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32;
3018 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
3019 struct files_struct *fsp,
3020 const struct smb_filename *smb_fname,
3021 TALLOC_CTX *mem_ctx,
3022 unsigned int *pnum_streams,
3023 struct stream_struct **pstreams)
3025 SMB_STRUCT_STAT sbuf;
3026 struct stream_struct *tmp_streams = NULL;
3029 if ((fsp != NULL) && (fsp->fsp_flags.is_directory)) {
3031 * No default streams on directories
3036 if ((fsp != NULL) && (fsp_get_pathref_fd(fsp) != -1)) {
3037 ret = SMB_VFS_FSTAT(fsp, &sbuf);
3040 struct smb_filename *smb_fname_cp = NULL;
3042 smb_fname_cp = cp_smb_filename_nostream(talloc_tos(), smb_fname);
3043 if (smb_fname_cp == NULL) {
3044 return NT_STATUS_NO_MEMORY;
3047 if (smb_fname_cp->flags & SMB_FILENAME_POSIX_PATH) {
3048 ret = SMB_VFS_LSTAT(handle->conn, smb_fname_cp);
3050 ret = SMB_VFS_STAT(handle->conn, smb_fname_cp);
3052 sbuf = smb_fname_cp->st;
3053 TALLOC_FREE(smb_fname_cp);
3057 return map_nt_error_from_unix(errno);
3060 if (S_ISDIR(sbuf.st_ex_mode)) {
3064 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
3065 (*pnum_streams) + 1);
3066 if (tmp_streams == NULL) {
3067 return NT_STATUS_NO_MEMORY;
3069 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
3070 if (tmp_streams[*pnum_streams].name == NULL) {
3071 return NT_STATUS_NO_MEMORY;
3073 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
3074 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
3077 *pstreams = tmp_streams;
3079 return NT_STATUS_OK;
3082 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
3083 const struct smb_filename *path,
3085 TALLOC_CTX *mem_ctx,
3089 * Don't fall back to get_real_filename so callers can differentiate
3090 * between a full directory scan and an actual case-insensitive stat.
3096 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
3097 const struct smb_filename *smb_fname)
3099 return handle->conn->connectpath;
3102 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
3103 struct byte_range_lock *br_lck,
3104 struct lock_struct *plock)
3106 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3108 /* Note: blr is not used in the default implementation. */
3109 return brl_lock_windows_default(br_lck, plock);
3112 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
3113 struct byte_range_lock *br_lck,
3114 const struct lock_struct *plock)
3116 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3118 return brl_unlock_windows_default(br_lck, plock);
3121 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
3123 struct lock_struct *plock)
3125 SMB_ASSERT(plock->lock_type == READ_LOCK ||
3126 plock->lock_type == WRITE_LOCK);
3128 return strict_lock_check_default(fsp, plock);
3131 /* NT ACL operations. */
3133 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
3135 uint32_t security_info,
3136 TALLOC_CTX *mem_ctx,
3137 struct security_descriptor **ppdesc)
3141 START_PROFILE(fget_nt_acl);
3142 result = posix_fget_nt_acl(fsp, security_info,
3144 END_PROFILE(fget_nt_acl);
3148 static NTSTATUS vfswrap_get_nt_acl_at(vfs_handle_struct *handle,
3149 struct files_struct *dirfsp,
3150 const struct smb_filename *smb_fname,
3151 uint32_t security_info,
3152 TALLOC_CTX *mem_ctx,
3153 struct security_descriptor **ppdesc)
3157 START_PROFILE(get_nt_acl_at);
3159 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
3161 result = posix_get_nt_acl(handle->conn,
3166 END_PROFILE(get_nt_acl_at);
3170 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
3174 START_PROFILE(fset_nt_acl);
3175 result = set_nt_acl(fsp, security_info_sent, psd);
3176 END_PROFILE(fset_nt_acl);
3180 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
3181 struct smb_filename *file,
3182 struct security_acl *sacl,
3183 uint32_t access_requested,
3184 uint32_t access_denied)
3186 return NT_STATUS_OK; /* Nothing to do here ... */
3189 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
3190 const struct smb_filename *smb_fname,
3191 SMB_ACL_TYPE_T type,
3192 TALLOC_CTX *mem_ctx)
3194 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
3197 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
3199 TALLOC_CTX *mem_ctx)
3201 return sys_acl_get_fd(handle, fsp, mem_ctx);
3204 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
3205 const struct smb_filename *smb_fname,
3206 SMB_ACL_TYPE_T acltype,
3209 return sys_acl_set_file(handle, smb_fname, acltype, theacl);
3212 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
3214 return sys_acl_set_fd(handle, fsp, theacl);
3217 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
3218 const struct smb_filename *smb_fname)
3220 return sys_acl_delete_def_file(handle, smb_fname);
3223 /****************************************************************
3224 Extended attribute operations.
3225 *****************************************************************/
3227 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
3228 const struct smb_filename *smb_fname,
3233 return getxattr(smb_fname->base_name, name, value, size);
3236 struct vfswrap_getxattrat_state {
3237 struct tevent_context *ev;
3238 files_struct *dir_fsp;
3239 const struct smb_filename *smb_fname;
3242 * The following variables are talloced off "state" which is protected
3243 * by a destructor and thus are guaranteed to be safe to be used in the
3244 * job function in the worker thread.
3247 const char *xattr_name;
3248 uint8_t *xattr_value;
3249 struct security_unix_token *token;
3252 struct vfs_aio_state vfs_aio_state;
3253 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
3256 static int vfswrap_getxattrat_state_destructor(
3257 struct vfswrap_getxattrat_state *state)
3262 static void vfswrap_getxattrat_do_sync(struct tevent_req *req);
3263 static void vfswrap_getxattrat_do_async(void *private_data);
3264 static void vfswrap_getxattrat_done(struct tevent_req *subreq);
3266 static struct tevent_req *vfswrap_getxattrat_send(
3267 TALLOC_CTX *mem_ctx,
3268 struct tevent_context *ev,
3269 struct vfs_handle_struct *handle,
3270 files_struct *dir_fsp,
3271 const struct smb_filename *smb_fname,
3272 const char *xattr_name,
3275 struct tevent_req *req = NULL;
3276 struct tevent_req *subreq = NULL;
3277 struct vfswrap_getxattrat_state *state = NULL;
3278 size_t max_threads = 0;
3279 bool have_per_thread_cwd = false;
3280 bool have_per_thread_creds = false;
3281 bool do_async = false;
3283 req = tevent_req_create(mem_ctx, &state,
3284 struct vfswrap_getxattrat_state);
3288 *state = (struct vfswrap_getxattrat_state) {
3291 .smb_fname = smb_fname,
3294 max_threads = pthreadpool_tevent_max_threads(dir_fsp->conn->sconn->pool);
3295 if (max_threads >= 1) {
3297 * We need a non sync threadpool!
3299 have_per_thread_cwd = per_thread_cwd_supported();
3301 #ifdef HAVE_LINUX_THREAD_CREDENTIALS
3302 have_per_thread_creds = true;
3304 if (have_per_thread_cwd && have_per_thread_creds) {
3308 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat, profile_p,
3309 state->profile_bytes, 0);
3311 if (fsp_get_pathref_fd(dir_fsp) == -1) {
3312 DBG_ERR("Need a valid directory fd\n");
3313 tevent_req_error(req, EINVAL);
3314 return tevent_req_post(req, ev);
3317 if (alloc_hint > 0) {
3318 state->xattr_value = talloc_zero_array(state,
3321 if (tevent_req_nomem(state->xattr_value, req)) {
3322 return tevent_req_post(req, ev);
3327 vfswrap_getxattrat_do_sync(req);
3328 return tevent_req_post(req, ev);
3332 * Now allocate all parameters from a memory context that won't go away
3333 * no matter what. These paremeters will get used in threads and we
3334 * can't reliably cancel threads, so all buffers passed to the threads
3335 * must not be freed before all referencing threads terminate.
3338 state->name = talloc_strdup(state, smb_fname->base_name);
3339 if (tevent_req_nomem(state->name, req)) {
3340 return tevent_req_post(req, ev);
3343 state->xattr_name = talloc_strdup(state, xattr_name);
3344 if (tevent_req_nomem(state->xattr_name, req)) {
3345 return tevent_req_post(req, ev);
3349 * This is a hot codepath so at first glance one might think we should
3350 * somehow optimize away the token allocation and do a
3351 * talloc_reference() or similar black magic instead. But due to the
3352 * talloc_stackframe pool per SMB2 request this should be a simple copy
3353 * without a malloc in most cases.
3355 if (geteuid() == sec_initial_uid()) {
3356 state->token = root_unix_token(state);
3358 state->token = copy_unix_token(
3360 dir_fsp->conn->session_info->unix_token);
3362 if (tevent_req_nomem(state->token, req)) {
3363 return tevent_req_post(req, ev);
3366 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3368 subreq = pthreadpool_tevent_job_send(
3371 dir_fsp->conn->sconn->pool,
3372 vfswrap_getxattrat_do_async,
3374 if (tevent_req_nomem(subreq, req)) {
3375 return tevent_req_post(req, ev);
3377 tevent_req_set_callback(subreq, vfswrap_getxattrat_done, req);
3379 talloc_set_destructor(state, vfswrap_getxattrat_state_destructor);
3384 static void vfswrap_getxattrat_do_sync(struct tevent_req *req)
3386 struct vfswrap_getxattrat_state *state = tevent_req_data(
3387 req, struct vfswrap_getxattrat_state);
3389 char *tofree = NULL;
3390 char pathbuf[PATH_MAX+1];
3394 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
3395 state->smb_fname->base_name,
3400 if (pathlen == -1) {
3401 tevent_req_error(req, ENOMEM);
3405 state->xattr_size = getxattr(path,
3408 talloc_array_length(state->xattr_value));
3410 TALLOC_FREE(tofree);
3411 if (state->xattr_size == -1) {
3412 tevent_req_error(req, err);
3416 tevent_req_done(req);
3420 static void vfswrap_getxattrat_do_async(void *private_data)
3422 struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3423 private_data, struct vfswrap_getxattrat_state);
3424 struct timespec start_time;
3425 struct timespec end_time;
3428 PROFILE_TIMESTAMP(&start_time);
3429 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
3432 * Here we simulate a getxattrat()
3433 * call using fchdir();getxattr()
3436 per_thread_cwd_activate();
3438 /* Become the correct credential on this thread. */
3439 ret = set_thread_credentials(state->token->uid,
3441 (size_t)state->token->ngroups,
3442 state->token->groups);
3444 state->xattr_size = -1;
3445 state->vfs_aio_state.error = errno;
3449 ret = fchdir(fsp_get_pathref_fd(state->dir_fsp));
3451 state->xattr_size = -1;
3452 state->vfs_aio_state.error = errno;
3456 state->xattr_size = getxattr(state->name,
3459 talloc_array_length(state->xattr_value));
3460 if (state->xattr_size == -1) {
3461 state->vfs_aio_state.error = errno;
3465 PROFILE_TIMESTAMP(&end_time);
3466 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
3467 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3470 static void vfswrap_getxattrat_done(struct tevent_req *subreq)
3472 struct tevent_req *req = tevent_req_callback_data(
3473 subreq, struct tevent_req);
3474 struct vfswrap_getxattrat_state *state = tevent_req_data(
3475 req, struct vfswrap_getxattrat_state);
3480 * Make sure we run as the user again
3482 ok = change_to_user_and_service_by_fsp(state->dir_fsp);
3485 ret = pthreadpool_tevent_job_recv(subreq);
3486 TALLOC_FREE(subreq);
3487 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
3488 talloc_set_destructor(state, NULL);
3490 if (ret != EAGAIN) {
3491 tevent_req_error(req, ret);
3495 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
3496 * means the lower level pthreadpool failed to create a new
3497 * thread. Fallback to sync processing in that case to allow
3498 * some progress for the client.
3500 vfswrap_getxattrat_do_sync(req);
3504 if (state->xattr_size == -1) {
3505 tevent_req_error(req, state->vfs_aio_state.error);
3509 if (state->xattr_value == NULL) {
3511 * The caller only wanted the size.
3513 tevent_req_done(req);
3518 * shrink the buffer to the returned size.
3519 * (can't fail). It means NULL if size is 0.
3521 state->xattr_value = talloc_realloc(state,
3526 tevent_req_done(req);
3529 static ssize_t vfswrap_getxattrat_recv(struct tevent_req *req,
3530 struct vfs_aio_state *aio_state,
3531 TALLOC_CTX *mem_ctx,
3532 uint8_t **xattr_value)
3534 struct vfswrap_getxattrat_state *state = tevent_req_data(
3535 req, struct vfswrap_getxattrat_state);
3538 if (tevent_req_is_unix_error(req, &aio_state->error)) {
3539 tevent_req_received(req);
3543 *aio_state = state->vfs_aio_state;
3544 xattr_size = state->xattr_size;
3545 if (xattr_value != NULL) {
3546 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
3549 tevent_req_received(req);
3553 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle,
3554 struct files_struct *fsp,
3559 int fd = fsp_get_pathref_fd(fsp);
3561 if (!fsp->fsp_flags.is_pathref) {
3562 return fgetxattr(fd, name, value, size);
3565 if (fsp->fsp_flags.have_proc_fds) {
3566 const char *p = NULL;
3569 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3574 return getxattr(p, name, value, size);
3578 * This is no longer a handle based call.
3580 return getxattr(fsp->fsp_name->base_name, name, value, size);
3583 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
3584 const struct smb_filename *smb_fname,
3588 return listxattr(smb_fname->base_name, list, size);
3591 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
3593 int fd = fsp_get_pathref_fd(fsp);
3595 if (!fsp->fsp_flags.is_pathref) {
3596 return flistxattr(fd, list, 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 listxattr(p, list, size);
3612 * This is no longer a handle based call.
3614 return listxattr(fsp->fsp_name->base_name, list, size);
3617 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
3618 const struct smb_filename *smb_fname,
3621 return removexattr(smb_fname->base_name, name);
3624 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
3626 int fd = fsp_get_pathref_fd(fsp);
3628 if (!fsp->fsp_flags.is_pathref) {
3629 return fremovexattr(fd, name);
3632 if (fsp->fsp_flags.have_proc_fds) {
3633 const char *p = NULL;
3636 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3641 return removexattr(p, name);
3645 * This is no longer a handle based call.
3647 return removexattr(fsp->fsp_name->base_name, name);
3650 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
3651 const struct smb_filename *smb_fname,
3657 return setxattr(smb_fname->base_name, name, value, size, flags);
3660 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
3662 return fsetxattr(fsp_get_io_fd(fsp), name, value, size, flags);
3665 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
3670 static bool vfswrap_is_offline(struct connection_struct *conn,
3671 const struct smb_filename *fname)
3675 bool offline = false;
3677 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
3681 if (!lp_dmapi_support(SNUM(conn)) || !dmapi_have_session()) {
3682 #if defined(ENOTSUP)
3688 status = get_full_smb_filename(talloc_tos(), fname, &path);
3689 if (!NT_STATUS_IS_OK(status)) {
3690 errno = map_errno_from_nt_status(status);
3694 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
3701 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
3702 struct files_struct *fsp,
3703 TALLOC_CTX *mem_ctx,
3706 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
3709 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
3710 struct files_struct *fsp,
3711 const DATA_BLOB old_cookie,
3712 TALLOC_CTX *mem_ctx,
3713 DATA_BLOB *new_cookie)
3715 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
3719 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
3720 struct smb_request *smb1req,
3721 struct smbXsrv_open *op,
3722 const DATA_BLOB old_cookie,
3723 TALLOC_CTX *mem_ctx,
3724 struct files_struct **fsp,
3725 DATA_BLOB *new_cookie)
3727 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
3728 old_cookie, mem_ctx,
3732 static struct vfs_fn_pointers vfs_default_fns = {
3733 /* Disk operations */
3735 .connect_fn = vfswrap_connect,
3736 .disconnect_fn = vfswrap_disconnect,
3737 .disk_free_fn = vfswrap_disk_free,
3738 .get_quota_fn = vfswrap_get_quota,
3739 .set_quota_fn = vfswrap_set_quota,
3740 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3741 .statvfs_fn = vfswrap_statvfs,
3742 .fs_capabilities_fn = vfswrap_fs_capabilities,
3743 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3744 .create_dfs_pathat_fn = vfswrap_create_dfs_pathat,
3745 .read_dfs_pathat_fn = vfswrap_read_dfs_pathat,
3746 .snap_check_path_fn = vfswrap_snap_check_path,
3747 .snap_create_fn = vfswrap_snap_create,
3748 .snap_delete_fn = vfswrap_snap_delete,
3750 /* Directory operations */
3752 .fdopendir_fn = vfswrap_fdopendir,
3753 .readdir_fn = vfswrap_readdir,
3754 .readdir_attr_fn = vfswrap_readdir_attr,
3755 .seekdir_fn = vfswrap_seekdir,
3756 .telldir_fn = vfswrap_telldir,
3757 .rewind_dir_fn = vfswrap_rewinddir,
3758 .mkdirat_fn = vfswrap_mkdirat,
3759 .closedir_fn = vfswrap_closedir,
3761 /* File operations */
3763 .openat_fn = vfswrap_openat,
3764 .create_file_fn = vfswrap_create_file,
3765 .close_fn = vfswrap_close,
3766 .pread_fn = vfswrap_pread,
3767 .pread_send_fn = vfswrap_pread_send,
3768 .pread_recv_fn = vfswrap_pread_recv,
3769 .pwrite_fn = vfswrap_pwrite,
3770 .pwrite_send_fn = vfswrap_pwrite_send,
3771 .pwrite_recv_fn = vfswrap_pwrite_recv,
3772 .lseek_fn = vfswrap_lseek,
3773 .sendfile_fn = vfswrap_sendfile,
3774 .recvfile_fn = vfswrap_recvfile,
3775 .renameat_fn = vfswrap_renameat,
3776 .fsync_send_fn = vfswrap_fsync_send,
3777 .fsync_recv_fn = vfswrap_fsync_recv,
3778 .stat_fn = vfswrap_stat,
3779 .fstat_fn = vfswrap_fstat,
3780 .lstat_fn = vfswrap_lstat,
3781 .get_alloc_size_fn = vfswrap_get_alloc_size,
3782 .unlinkat_fn = vfswrap_unlinkat,
3783 .chmod_fn = vfswrap_chmod,
3784 .fchmod_fn = vfswrap_fchmod,
3785 .fchown_fn = vfswrap_fchown,
3786 .lchown_fn = vfswrap_lchown,
3787 .chdir_fn = vfswrap_chdir,
3788 .getwd_fn = vfswrap_getwd,
3789 .ntimes_fn = vfswrap_ntimes,
3790 .ftruncate_fn = vfswrap_ftruncate,
3791 .fallocate_fn = vfswrap_fallocate,
3792 .lock_fn = vfswrap_lock,
3793 .kernel_flock_fn = vfswrap_kernel_flock,
3794 .fcntl_fn = vfswrap_fcntl,
3795 .linux_setlease_fn = vfswrap_linux_setlease,
3796 .getlock_fn = vfswrap_getlock,
3797 .symlinkat_fn = vfswrap_symlinkat,
3798 .readlinkat_fn = vfswrap_readlinkat,
3799 .linkat_fn = vfswrap_linkat,
3800 .mknodat_fn = vfswrap_mknodat,
3801 .realpath_fn = vfswrap_realpath,
3802 .chflags_fn = vfswrap_chflags,
3803 .file_id_create_fn = vfswrap_file_id_create,
3804 .fs_file_id_fn = vfswrap_fs_file_id,
3805 .streaminfo_fn = vfswrap_streaminfo,
3806 .get_real_filename_fn = vfswrap_get_real_filename,
3807 .connectpath_fn = vfswrap_connectpath,
3808 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
3809 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3810 .strict_lock_check_fn = vfswrap_strict_lock_check,
3811 .translate_name_fn = vfswrap_translate_name,
3812 .fsctl_fn = vfswrap_fsctl,
3813 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
3814 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
3815 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
3816 .get_dos_attributes_send_fn = vfswrap_get_dos_attributes_send,
3817 .get_dos_attributes_recv_fn = vfswrap_get_dos_attributes_recv,
3818 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
3819 .offload_read_send_fn = vfswrap_offload_read_send,
3820 .offload_read_recv_fn = vfswrap_offload_read_recv,
3821 .offload_write_send_fn = vfswrap_offload_write_send,
3822 .offload_write_recv_fn = vfswrap_offload_write_recv,
3823 .get_compression_fn = vfswrap_get_compression,
3824 .set_compression_fn = vfswrap_set_compression,
3826 /* NT ACL operations. */
3828 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
3829 .get_nt_acl_at_fn = vfswrap_get_nt_acl_at,
3830 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
3831 .audit_file_fn = vfswrap_audit_file,
3833 /* POSIX ACL operations. */
3835 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
3836 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3837 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
3838 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3839 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
3840 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3841 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
3843 /* EA operations. */
3844 .getxattr_fn = vfswrap_getxattr,
3845 .getxattrat_send_fn = vfswrap_getxattrat_send,
3846 .getxattrat_recv_fn = vfswrap_getxattrat_recv,
3847 .fgetxattr_fn = vfswrap_fgetxattr,
3848 .listxattr_fn = vfswrap_listxattr,
3849 .flistxattr_fn = vfswrap_flistxattr,
3850 .removexattr_fn = vfswrap_removexattr,
3851 .fremovexattr_fn = vfswrap_fremovexattr,
3852 .setxattr_fn = vfswrap_setxattr,
3853 .fsetxattr_fn = vfswrap_fsetxattr,
3855 /* aio operations */
3856 .aio_force_fn = vfswrap_aio_force,
3858 /* durable handle operations */
3859 .durable_cookie_fn = vfswrap_durable_cookie,
3860 .durable_disconnect_fn = vfswrap_durable_disconnect,
3861 .durable_reconnect_fn = vfswrap_durable_reconnect,
3865 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3868 * Here we need to implement every call!
3870 * As this is the end of the vfs module chain.
3872 smb_vfs_assert_all_fns(&vfs_default_fns, DEFAULT_VFS_MODULE_NAME);
3873 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3874 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);