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 return 0; /* Return >= 0 for success */
55 static void vfswrap_disconnect(vfs_handle_struct *handle)
61 static uint64_t vfswrap_disk_free(vfs_handle_struct *handle,
62 const struct smb_filename *smb_fname,
67 if (sys_fsusage(smb_fname->base_name, dfree, dsize) != 0) {
75 static int vfswrap_get_quota(struct vfs_handle_struct *handle,
76 const struct smb_filename *smb_fname,
77 enum SMB_QUOTA_TYPE qtype,
81 #ifdef HAVE_SYS_QUOTAS
84 START_PROFILE(syscall_get_quota);
85 result = sys_get_quota(smb_fname->base_name, qtype, id, qt);
86 END_PROFILE(syscall_get_quota);
94 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
96 #ifdef HAVE_SYS_QUOTAS
99 START_PROFILE(syscall_set_quota);
100 result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
101 END_PROFILE(syscall_set_quota);
109 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
110 struct files_struct *fsp,
111 struct shadow_copy_data *shadow_copy_data,
115 return -1; /* Not implemented. */
118 static int vfswrap_statvfs(struct vfs_handle_struct *handle,
119 const struct smb_filename *smb_fname,
120 vfs_statvfs_struct *statbuf)
122 return sys_statvfs(smb_fname->base_name, statbuf);
125 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
126 enum timestamp_set_resolution *p_ts_res)
128 const struct loadparm_substitution *lp_sub =
129 loadparm_s3_global_substitution();
130 connection_struct *conn = handle->conn;
131 uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
132 struct smb_filename *smb_fname_cpath = NULL;
133 struct vfs_statvfs_struct statbuf;
136 smb_fname_cpath = synthetic_smb_fname(talloc_tos(),
142 if (smb_fname_cpath == NULL) {
146 ZERO_STRUCT(statbuf);
147 ret = SMB_VFS_STATVFS(conn, smb_fname_cpath, &statbuf);
149 caps = statbuf.FsCapabilities;
152 *p_ts_res = TIMESTAMP_SET_SECONDS;
154 /* Work out what timestamp resolution we can
155 * use when setting a timestamp. */
157 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
159 TALLOC_FREE(smb_fname_cpath);
163 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
164 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
165 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
166 /* If any of the normal UNIX directory timestamps
167 * have a non-zero tv_nsec component assume
168 * we might be able to set sub-second timestamps.
169 * See what filetime set primitives we have.
171 #if defined(HAVE_UTIMENSAT)
172 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
173 #elif defined(HAVE_UTIMES)
174 /* utimes allows msec timestamps to be set. */
175 *p_ts_res = TIMESTAMP_SET_MSEC;
176 #elif defined(HAVE_UTIME)
177 /* utime only allows sec timestamps to be set. */
178 *p_ts_res = TIMESTAMP_SET_SECONDS;
181 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
183 "available on share %s, directory %s\n",
184 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
185 lp_servicename(talloc_tos(), lp_sub, conn->params->service),
186 conn->connectpath ));
188 TALLOC_FREE(smb_fname_cpath);
192 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
193 struct dfs_GetDFSReferral *r)
195 struct junction_map *junction = NULL;
197 bool self_referral = false;
198 char *pathnamep = NULL;
199 char *local_dfs_path = NULL;
202 uint16_t max_referral_level = r->in.req.max_referral_level;
205 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
208 /* get the junction entry */
209 if (r->in.req.servername == NULL) {
210 return NT_STATUS_NOT_FOUND;
214 * Trim pathname sent by client so it begins with only one backslash.
215 * Two backslashes confuse some dfs clients
218 local_dfs_path = talloc_strdup(r, r->in.req.servername);
219 if (local_dfs_path == NULL) {
220 return NT_STATUS_NO_MEMORY;
222 pathnamep = local_dfs_path;
223 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
224 IS_DIRECTORY_SEP(pathnamep[1])) {
228 junction = talloc_zero(r, struct junction_map);
229 if (junction == NULL) {
230 return NT_STATUS_NO_MEMORY;
233 /* The following call can change cwd. */
234 status = get_referred_path(r,
235 handle->conn->session_info,
237 handle->conn->sconn->remote_address,
238 handle->conn->sconn->local_address,
239 !handle->conn->sconn->using_smb2,
240 junction, &consumedcnt, &self_referral);
241 if (!NT_STATUS_IS_OK(status)) {
242 struct smb_filename connectpath_fname = {
243 .base_name = handle->conn->connectpath
245 vfs_ChDir(handle->conn, &connectpath_fname);
249 struct smb_filename connectpath_fname = {
250 .base_name = handle->conn->connectpath
252 vfs_ChDir(handle->conn, &connectpath_fname);
255 if (!self_referral) {
256 pathnamep[consumedcnt] = '\0';
259 dbgtext("Path %s to alternate path(s):",
261 for (i=0; i < junction->referral_count; i++) {
263 junction->referral_list[i].alternate_path);
269 if (r->in.req.max_referral_level <= 2) {
270 max_referral_level = 2;
272 if (r->in.req.max_referral_level >= 3) {
273 max_referral_level = 3;
276 r->out.resp = talloc_zero(r, struct dfs_referral_resp);
277 if (r->out.resp == NULL) {
278 return NT_STATUS_NO_MEMORY;
281 r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
282 r->out.resp->nb_referrals = junction->referral_count;
284 r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
286 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
289 r->out.resp->referral_entries = talloc_zero_array(r,
290 struct dfs_referral_type,
291 r->out.resp->nb_referrals);
292 if (r->out.resp->referral_entries == NULL) {
293 return NT_STATUS_NO_MEMORY;
296 switch (max_referral_level) {
298 for(i=0; i < junction->referral_count; i++) {
299 struct referral *ref = &junction->referral_list[i];
300 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
301 struct dfs_referral_type *t =
302 &r->out.resp->referral_entries[i];
303 struct dfs_referral_v2 *v2 = &t->referral.v2;
306 v2->size = VERSION2_REFERRAL_SIZE;
308 v2->server_type = DFS_SERVER_ROOT;
310 v2->server_type = DFS_SERVER_NON_ROOT;
313 v2->proximity = ref->proximity;
315 v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
316 if (v2->DFS_path == NULL) {
317 return NT_STATUS_NO_MEMORY;
319 v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
320 if (v2->DFS_alt_path == NULL) {
321 return NT_STATUS_NO_MEMORY;
323 v2->netw_address = talloc_strdup(mem_ctx,
324 ref->alternate_path);
325 if (v2->netw_address == NULL) {
326 return NT_STATUS_NO_MEMORY;
332 for(i=0; i < junction->referral_count; i++) {
333 struct referral *ref = &junction->referral_list[i];
334 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
335 struct dfs_referral_type *t =
336 &r->out.resp->referral_entries[i];
337 struct dfs_referral_v3 *v3 = &t->referral.v3;
338 struct dfs_normal_referral *r1 = &v3->referrals.r1;
341 v3->size = VERSION3_REFERRAL_SIZE;
343 v3->server_type = DFS_SERVER_ROOT;
345 v3->server_type = DFS_SERVER_NON_ROOT;
349 r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
350 if (r1->DFS_path == NULL) {
351 return NT_STATUS_NO_MEMORY;
353 r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
354 if (r1->DFS_alt_path == NULL) {
355 return NT_STATUS_NO_MEMORY;
357 r1->netw_address = talloc_strdup(mem_ctx,
358 ref->alternate_path);
359 if (r1->netw_address == NULL) {
360 return NT_STATUS_NO_MEMORY;
365 DEBUG(0,("Invalid dfs referral version: %d\n",
366 max_referral_level));
367 return NT_STATUS_INVALID_LEVEL;
371 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
377 static NTSTATUS vfswrap_create_dfs_pathat(struct vfs_handle_struct *handle,
378 struct files_struct *dirfsp,
379 const struct smb_filename *smb_fname,
380 const struct referral *reflist,
381 size_t referral_count)
383 TALLOC_CTX *frame = talloc_stackframe();
384 NTSTATUS status = NT_STATUS_NO_MEMORY;
386 char *msdfs_link = NULL;
388 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
390 /* Form the msdfs_link contents */
391 msdfs_link = msdfs_link_string(frame,
394 if (msdfs_link == NULL) {
398 ret = symlinkat(msdfs_link,
399 fsp_get_io_fd(dirfsp),
400 smb_fname->base_name);
402 status = NT_STATUS_OK;
404 status = map_nt_error_from_unix(errno);
414 * Read and return the contents of a DFS redirect given a
415 * pathname. A caller can pass in NULL for ppreflist and
416 * preferral_count but still determine if this was a
417 * DFS redirect point by getting NT_STATUS_OK back
418 * without incurring the overhead of reading and parsing
419 * the referral contents.
422 static NTSTATUS vfswrap_read_dfs_pathat(struct vfs_handle_struct *handle,
424 struct files_struct *dirfsp,
425 struct smb_filename *smb_fname,
426 struct referral **ppreflist,
427 size_t *preferral_count)
429 NTSTATUS status = NT_STATUS_NO_MEMORY;
431 char *link_target = NULL;
434 #if defined(HAVE_BROKEN_READLINK)
435 char link_target_buf[PATH_MAX];
437 char link_target_buf[7];
441 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
443 if (is_named_stream(smb_fname)) {
444 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
448 if (ppreflist == NULL && preferral_count == NULL) {
450 * We're only checking if this is a DFS
451 * redirect. We don't need to return data.
453 bufsize = sizeof(link_target_buf);
454 link_target = link_target_buf;
457 link_target = talloc_array(mem_ctx, char, bufsize);
463 referral_len = readlinkat(fsp_get_io_fd(dirfsp),
464 smb_fname->base_name,
467 if (referral_len == -1) {
468 if (errno == EINVAL) {
470 * If the path isn't a link, readlinkat
471 * returns EINVAL. Allow the caller to
474 DBG_INFO("%s is not a link.\n", smb_fname->base_name);
475 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
477 status = map_nt_error_from_unix(errno);
478 DBG_ERR("Error reading "
479 "msdfs link %s: %s\n",
480 smb_fname->base_name,
485 link_target[referral_len] = '\0';
487 DBG_INFO("%s -> %s\n",
488 smb_fname->base_name,
491 if (!strnequal(link_target, "msdfs:", 6)) {
492 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
496 ret = sys_lstat(smb_fname->base_name,
498 lp_fake_directory_create_times(SNUM(handle->conn)));
500 status = map_nt_error_from_unix(errno);
504 if (ppreflist == NULL && preferral_count == NULL) {
505 /* Early return for checking if this is a DFS link. */
509 ok = parse_msdfs_symlink(mem_ctx,
510 lp_msdfs_shuffle_referrals(SNUM(handle->conn)),
516 status = NT_STATUS_OK;
518 status = NT_STATUS_NO_MEMORY;
523 if (link_target != link_target_buf) {
524 TALLOC_FREE(link_target);
529 static NTSTATUS vfswrap_snap_check_path(struct vfs_handle_struct *handle,
531 const char *service_path,
534 return NT_STATUS_NOT_SUPPORTED;
537 static NTSTATUS vfswrap_snap_create(struct vfs_handle_struct *handle,
539 const char *base_volume,
545 return NT_STATUS_NOT_SUPPORTED;
548 static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle,
553 return NT_STATUS_NOT_SUPPORTED;
556 /* Directory operations */
558 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
565 START_PROFILE(syscall_fdopendir);
566 result = sys_fdopendir(fsp_get_io_fd(fsp));
567 END_PROFILE(syscall_fdopendir);
572 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
574 SMB_STRUCT_STAT *sbuf)
576 struct dirent *result;
578 START_PROFILE(syscall_readdir);
579 result = readdir(dirp);
580 END_PROFILE(syscall_readdir);
582 /* Default Posix readdir() does not give us stat info.
583 * Set to invalid to indicate we didn't return this info. */
584 SET_STAT_INVALID(*sbuf);
585 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
586 if (result != NULL) {
587 /* See if we can efficiently return this. */
589 int flags = AT_SYMLINK_NOFOLLOW;
590 int ret = fstatat(dirfd(dirp),
595 * As this is an optimization,
596 * ignore it if we stat'ed a
597 * symlink. Make the caller
598 * do it again as we don't
599 * know if they wanted the link
600 * info, or its target info.
602 if ((ret == 0) && (!S_ISLNK(st.st_mode))) {
603 init_stat_ex_from_stat(sbuf,
605 lp_fake_directory_create_times(
606 SNUM(handle->conn)));
614 static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
615 const struct smb_filename *fname,
617 struct readdir_attr_data **attr_data)
619 return NT_STATUS_NOT_SUPPORTED;
622 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
624 START_PROFILE(syscall_seekdir);
625 seekdir(dirp, offset);
626 END_PROFILE(syscall_seekdir);
629 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
632 START_PROFILE(syscall_telldir);
633 result = telldir(dirp);
634 END_PROFILE(syscall_telldir);
638 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
640 START_PROFILE(syscall_rewinddir);
642 END_PROFILE(syscall_rewinddir);
645 static int vfswrap_mkdirat(vfs_handle_struct *handle,
646 struct files_struct *dirfsp,
647 const struct smb_filename *smb_fname,
651 struct smb_filename *parent = NULL;
654 START_PROFILE(syscall_mkdirat);
656 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
658 if (lp_inherit_acls(SNUM(handle->conn))) {
659 ok = parent_smb_fname(talloc_tos(), smb_fname, &parent, NULL);
660 if (ok && directory_has_default_acl(handle->conn,
664 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
670 result = mkdirat(fsp_get_pathref_fd(dirfsp), smb_fname->base_name, mode);
672 END_PROFILE(syscall_mkdirat);
676 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
680 START_PROFILE(syscall_closedir);
681 result = closedir(dirp);
682 END_PROFILE(syscall_closedir);
686 /* File operations */
688 static int vfswrap_openat(vfs_handle_struct *handle,
689 const struct files_struct *dirfsp,
690 const struct smb_filename *smb_fname,
697 START_PROFILE(syscall_openat);
699 if (is_named_stream(smb_fname)) {
705 result = openat(fsp_get_pathref_fd(dirfsp),
706 smb_fname->base_name,
711 END_PROFILE(syscall_openat);
714 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
715 struct smb_request *req,
716 struct smb_filename *smb_fname,
717 uint32_t access_mask,
718 uint32_t share_access,
719 uint32_t create_disposition,
720 uint32_t create_options,
721 uint32_t file_attributes,
722 uint32_t oplock_request,
723 const struct smb2_lease *lease,
724 uint64_t allocation_size,
725 uint32_t private_flags,
726 struct security_descriptor *sd,
727 struct ea_list *ea_list,
728 files_struct **result,
730 const struct smb2_create_blobs *in_context_blobs,
731 struct smb2_create_blobs *out_context_blobs)
733 return create_file_default(handle->conn, req, smb_fname,
734 access_mask, share_access,
735 create_disposition, create_options,
736 file_attributes, oplock_request, lease,
737 allocation_size, private_flags,
739 pinfo, in_context_blobs, out_context_blobs);
742 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
746 START_PROFILE(syscall_close);
747 result = fd_close_posix(fsp);
748 END_PROFILE(syscall_close);
752 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
753 size_t n, off_t offset)
757 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
758 START_PROFILE_BYTES(syscall_pread, n);
759 result = sys_pread_full(fsp_get_io_fd(fsp), data, n, offset);
760 END_PROFILE_BYTES(syscall_pread);
762 if (result == -1 && errno == ESPIPE) {
763 /* Maintain the fiction that pipes can be seeked (sought?) on. */
764 result = sys_read(fsp_get_io_fd(fsp), data, n);
768 #else /* HAVE_PREAD */
771 #endif /* HAVE_PREAD */
776 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
777 size_t n, off_t offset)
781 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
782 START_PROFILE_BYTES(syscall_pwrite, n);
783 result = sys_pwrite_full(fsp_get_io_fd(fsp), data, n, offset);
784 END_PROFILE_BYTES(syscall_pwrite);
786 if (result == -1 && errno == ESPIPE) {
787 /* Maintain the fiction that pipes can be sought on. */
788 result = sys_write(fsp_get_io_fd(fsp), data, n);
791 #else /* HAVE_PWRITE */
794 #endif /* HAVE_PWRITE */
799 struct vfswrap_pread_state {
806 struct vfs_aio_state vfs_aio_state;
807 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
810 static void vfs_pread_do(void *private_data);
811 static void vfs_pread_done(struct tevent_req *subreq);
812 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state);
814 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
816 struct tevent_context *ev,
817 struct files_struct *fsp,
819 size_t n, off_t offset)
821 struct tevent_req *req, *subreq;
822 struct vfswrap_pread_state *state;
824 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
830 state->fd = fsp_get_io_fd(fsp);
833 state->offset = offset;
835 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
836 state->profile_bytes, n);
837 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
839 subreq = pthreadpool_tevent_job_send(
840 state, ev, handle->conn->sconn->pool,
841 vfs_pread_do, state);
842 if (tevent_req_nomem(subreq, req)) {
843 return tevent_req_post(req, ev);
845 tevent_req_set_callback(subreq, vfs_pread_done, req);
847 talloc_set_destructor(state, vfs_pread_state_destructor);
852 static void vfs_pread_do(void *private_data)
854 struct vfswrap_pread_state *state = talloc_get_type_abort(
855 private_data, struct vfswrap_pread_state);
856 struct timespec start_time;
857 struct timespec end_time;
859 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
861 PROFILE_TIMESTAMP(&start_time);
863 state->ret = sys_pread_full(state->fd,
868 if (state->ret == -1) {
869 state->vfs_aio_state.error = errno;
872 PROFILE_TIMESTAMP(&end_time);
874 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
876 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
879 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state)
884 static void vfs_pread_done(struct tevent_req *subreq)
886 struct tevent_req *req = tevent_req_callback_data(
887 subreq, struct tevent_req);
888 struct vfswrap_pread_state *state = tevent_req_data(
889 req, struct vfswrap_pread_state);
892 ret = pthreadpool_tevent_job_recv(subreq);
894 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
895 talloc_set_destructor(state, NULL);
898 tevent_req_error(req, ret);
902 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
903 * means the lower level pthreadpool failed to create a new
904 * thread. Fallback to sync processing in that case to allow
905 * some progress for the client.
910 tevent_req_done(req);
913 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
914 struct vfs_aio_state *vfs_aio_state)
916 struct vfswrap_pread_state *state = tevent_req_data(
917 req, struct vfswrap_pread_state);
919 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
923 *vfs_aio_state = state->vfs_aio_state;
927 struct vfswrap_pwrite_state {
934 struct vfs_aio_state vfs_aio_state;
935 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
938 static void vfs_pwrite_do(void *private_data);
939 static void vfs_pwrite_done(struct tevent_req *subreq);
940 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state);
942 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
944 struct tevent_context *ev,
945 struct files_struct *fsp,
947 size_t n, off_t offset)
949 struct tevent_req *req, *subreq;
950 struct vfswrap_pwrite_state *state;
952 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
958 state->fd = fsp_get_io_fd(fsp);
961 state->offset = offset;
963 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
964 state->profile_bytes, n);
965 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
967 subreq = pthreadpool_tevent_job_send(
968 state, ev, handle->conn->sconn->pool,
969 vfs_pwrite_do, state);
970 if (tevent_req_nomem(subreq, req)) {
971 return tevent_req_post(req, ev);
973 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
975 talloc_set_destructor(state, vfs_pwrite_state_destructor);
980 static void vfs_pwrite_do(void *private_data)
982 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
983 private_data, struct vfswrap_pwrite_state);
984 struct timespec start_time;
985 struct timespec end_time;
987 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
989 PROFILE_TIMESTAMP(&start_time);
991 state->ret = sys_pwrite_full(state->fd,
996 if (state->ret == -1) {
997 state->vfs_aio_state.error = errno;
1000 PROFILE_TIMESTAMP(&end_time);
1002 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1004 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1007 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state)
1012 static void vfs_pwrite_done(struct tevent_req *subreq)
1014 struct tevent_req *req = tevent_req_callback_data(
1015 subreq, struct tevent_req);
1016 struct vfswrap_pwrite_state *state = tevent_req_data(
1017 req, struct vfswrap_pwrite_state);
1020 ret = pthreadpool_tevent_job_recv(subreq);
1021 TALLOC_FREE(subreq);
1022 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1023 talloc_set_destructor(state, NULL);
1025 if (ret != EAGAIN) {
1026 tevent_req_error(req, ret);
1030 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1031 * means the lower level pthreadpool failed to create a new
1032 * thread. Fallback to sync processing in that case to allow
1033 * some progress for the client.
1035 vfs_pwrite_do(state);
1038 tevent_req_done(req);
1041 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
1042 struct vfs_aio_state *vfs_aio_state)
1044 struct vfswrap_pwrite_state *state = tevent_req_data(
1045 req, struct vfswrap_pwrite_state);
1047 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1051 *vfs_aio_state = state->vfs_aio_state;
1055 struct vfswrap_fsync_state {
1059 struct vfs_aio_state vfs_aio_state;
1060 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
1063 static void vfs_fsync_do(void *private_data);
1064 static void vfs_fsync_done(struct tevent_req *subreq);
1065 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state);
1067 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
1068 TALLOC_CTX *mem_ctx,
1069 struct tevent_context *ev,
1070 struct files_struct *fsp)
1072 struct tevent_req *req, *subreq;
1073 struct vfswrap_fsync_state *state;
1075 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
1081 state->fd = fsp_get_io_fd(fsp);
1083 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_fsync, profile_p,
1084 state->profile_bytes, 0);
1085 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1087 subreq = pthreadpool_tevent_job_send(
1088 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
1089 if (tevent_req_nomem(subreq, req)) {
1090 return tevent_req_post(req, ev);
1092 tevent_req_set_callback(subreq, vfs_fsync_done, req);
1094 talloc_set_destructor(state, vfs_fsync_state_destructor);
1099 static void vfs_fsync_do(void *private_data)
1101 struct vfswrap_fsync_state *state = talloc_get_type_abort(
1102 private_data, struct vfswrap_fsync_state);
1103 struct timespec start_time;
1104 struct timespec end_time;
1106 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
1108 PROFILE_TIMESTAMP(&start_time);
1111 state->ret = fsync(state->fd);
1112 } while ((state->ret == -1) && (errno == EINTR));
1114 if (state->ret == -1) {
1115 state->vfs_aio_state.error = errno;
1118 PROFILE_TIMESTAMP(&end_time);
1120 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1122 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1125 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state)
1130 static void vfs_fsync_done(struct tevent_req *subreq)
1132 struct tevent_req *req = tevent_req_callback_data(
1133 subreq, struct tevent_req);
1134 struct vfswrap_fsync_state *state = tevent_req_data(
1135 req, struct vfswrap_fsync_state);
1138 ret = pthreadpool_tevent_job_recv(subreq);
1139 TALLOC_FREE(subreq);
1140 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1141 talloc_set_destructor(state, NULL);
1143 if (ret != EAGAIN) {
1144 tevent_req_error(req, ret);
1148 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1149 * means the lower level pthreadpool failed to create a new
1150 * thread. Fallback to sync processing in that case to allow
1151 * some progress for the client.
1153 vfs_fsync_do(state);
1156 tevent_req_done(req);
1159 static int vfswrap_fsync_recv(struct tevent_req *req,
1160 struct vfs_aio_state *vfs_aio_state)
1162 struct vfswrap_fsync_state *state = tevent_req_data(
1163 req, struct vfswrap_fsync_state);
1165 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1169 *vfs_aio_state = state->vfs_aio_state;
1173 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1177 START_PROFILE(syscall_lseek);
1179 result = lseek(fsp_get_io_fd(fsp), offset, whence);
1181 * We want to maintain the fiction that we can seek
1182 * on a fifo for file system purposes. This allows
1183 * people to set up UNIX fifo's that feed data to Windows
1184 * applications. JRA.
1187 if((result == -1) && (errno == ESPIPE)) {
1192 END_PROFILE(syscall_lseek);
1196 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1197 off_t offset, size_t n)
1201 START_PROFILE_BYTES(syscall_sendfile, n);
1202 result = sys_sendfile(tofd, fsp_get_io_fd(fromfsp), hdr, offset, n);
1203 END_PROFILE_BYTES(syscall_sendfile);
1207 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1209 files_struct *tofsp,
1215 START_PROFILE_BYTES(syscall_recvfile, n);
1216 result = sys_recvfile(fromfd, fsp_get_io_fd(tofsp), offset, n);
1217 END_PROFILE_BYTES(syscall_recvfile);
1221 static int vfswrap_renameat(vfs_handle_struct *handle,
1222 files_struct *srcfsp,
1223 const struct smb_filename *smb_fname_src,
1224 files_struct *dstfsp,
1225 const struct smb_filename *smb_fname_dst)
1229 START_PROFILE(syscall_renameat);
1231 if (is_named_stream(smb_fname_src) || is_named_stream(smb_fname_dst)) {
1236 result = renameat(fsp_get_pathref_fd(srcfsp),
1237 smb_fname_src->base_name,
1238 fsp_get_pathref_fd(dstfsp),
1239 smb_fname_dst->base_name);
1242 END_PROFILE(syscall_renameat);
1246 static int vfswrap_stat(vfs_handle_struct *handle,
1247 struct smb_filename *smb_fname)
1251 START_PROFILE(syscall_stat);
1253 if (is_named_stream(smb_fname)) {
1258 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1259 lp_fake_directory_create_times(SNUM(handle->conn)));
1261 END_PROFILE(syscall_stat);
1265 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1269 START_PROFILE(syscall_fstat);
1270 result = sys_fstat(fsp_get_pathref_fd(fsp),
1271 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1272 END_PROFILE(syscall_fstat);
1276 static int vfswrap_lstat(vfs_handle_struct *handle,
1277 struct smb_filename *smb_fname)
1281 START_PROFILE(syscall_lstat);
1283 if (is_named_stream(smb_fname)) {
1288 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1289 lp_fake_directory_create_times(SNUM(handle->conn)));
1291 END_PROFILE(syscall_lstat);
1295 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1297 enum vfs_translate_direction direction,
1298 TALLOC_CTX *mem_ctx,
1301 return NT_STATUS_NONE_MAPPED;
1305 * Implement the default fsctl operation.
1307 static bool vfswrap_logged_ioctl_message = false;
1309 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1310 struct files_struct *fsp,
1313 uint16_t req_flags, /* Needed for UNICODE ... */
1314 const uint8_t *_in_data,
1316 uint8_t **_out_data,
1317 uint32_t max_out_len,
1320 const char *in_data = (const char *)_in_data;
1321 char **out_data = (char **)_out_data;
1325 case FSCTL_SET_SPARSE:
1327 bool set_sparse = true;
1329 if (in_len >= 1 && in_data[0] == 0) {
1333 status = file_set_sparse(handle->conn, fsp, set_sparse);
1335 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1336 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1337 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1338 nt_errstr(status)));
1343 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1345 unsigned char objid[16];
1346 char *return_data = NULL;
1348 /* This should return the object-id on this file.
1349 * I think I'll make this be the inode+dev. JRA.
1352 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1353 fsp_fnum_dbg(fsp)));
1355 *out_len = MIN(max_out_len, 64);
1357 /* Hmmm, will this cause problems if less data asked for? */
1358 return_data = talloc_array(ctx, char, 64);
1359 if (return_data == NULL) {
1360 return NT_STATUS_NO_MEMORY;
1363 /* For backwards compatibility only store the dev/inode. */
1364 push_file_id_16(return_data, &fsp->file_id);
1365 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1366 push_file_id_16(return_data+32, &fsp->file_id);
1367 memset(return_data+48, 0, 16);
1368 *out_data = return_data;
1369 return NT_STATUS_OK;
1372 case FSCTL_GET_REPARSE_POINT:
1374 status = fsctl_get_reparse_point(
1375 fsp, ctx, out_data, max_out_len, out_len);
1379 case FSCTL_SET_REPARSE_POINT:
1381 status = fsctl_set_reparse_point(fsp, ctx, _in_data, in_len);
1385 case FSCTL_DELETE_REPARSE_POINT:
1387 status = fsctl_del_reparse_point(fsp, ctx, _in_data, in_len);
1391 case FSCTL_GET_SHADOW_COPY_DATA:
1394 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1395 * and return their volume names. If max_data_count is 16, then it is just
1396 * asking for the number of volumes and length of the combined names.
1398 * pdata is the data allocated by our caller, but that uses
1399 * total_data_count (which is 0 in our case) rather than max_data_count.
1400 * Allocate the correct amount and return the pointer to let
1401 * it be deallocated when we return.
1403 struct shadow_copy_data *shadow_data = NULL;
1404 bool labels = False;
1405 uint32_t labels_data_count = 0;
1407 char *cur_pdata = NULL;
1409 if (max_out_len < 16) {
1410 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1412 return NT_STATUS_INVALID_PARAMETER;
1415 if (max_out_len > 16) {
1419 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1420 if (shadow_data == NULL) {
1421 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1422 return NT_STATUS_NO_MEMORY;
1426 * Call the VFS routine to actually do the work.
1428 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1431 /* broken module didn't set errno on error */
1432 status = NT_STATUS_UNSUCCESSFUL;
1434 status = map_nt_error_from_unix(errno);
1435 if (NT_STATUS_EQUAL(status,
1436 NT_STATUS_NOT_SUPPORTED)) {
1440 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1441 "connectpath %s, failed - %s.\n",
1442 fsp->conn->connectpath,
1443 nt_errstr(status)));
1444 TALLOC_FREE(shadow_data);
1448 labels_data_count = (shadow_data->num_volumes * 2 *
1449 sizeof(SHADOW_COPY_LABEL)) + 2;
1454 *out_len = 12 + labels_data_count;
1457 if (max_out_len < *out_len) {
1458 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1459 max_out_len, *out_len));
1460 TALLOC_FREE(shadow_data);
1461 return NT_STATUS_BUFFER_TOO_SMALL;
1464 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1465 if (cur_pdata == NULL) {
1466 TALLOC_FREE(shadow_data);
1467 return NT_STATUS_NO_MEMORY;
1470 *out_data = cur_pdata;
1472 /* num_volumes 4 bytes */
1473 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1476 /* num_labels 4 bytes */
1477 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1480 /* needed_data_count 4 bytes */
1481 SIVAL(cur_pdata, 8, labels_data_count);
1485 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1486 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1487 if (labels && shadow_data->labels) {
1488 for (i=0; i<shadow_data->num_volumes; i++) {
1490 status = srvstr_push(cur_pdata, req_flags,
1491 cur_pdata, shadow_data->labels[i],
1492 2 * sizeof(SHADOW_COPY_LABEL),
1493 STR_UNICODE|STR_TERMINATE, &len);
1494 if (!NT_STATUS_IS_OK(status)) {
1495 TALLOC_FREE(*out_data);
1496 TALLOC_FREE(shadow_data);
1499 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1500 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1504 TALLOC_FREE(shadow_data);
1506 return NT_STATUS_OK;
1509 case FSCTL_FIND_FILES_BY_SID:
1511 /* pretend this succeeded -
1513 * we have to send back a list with all files owned by this SID
1515 * but I have to check that --metze
1519 struct dom_sid_buf buf;
1523 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1524 fsp_fnum_dbg(fsp)));
1527 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1528 return NT_STATUS_INVALID_PARAMETER;
1531 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1533 /* unknown 4 bytes: this is not the length of the sid :-( */
1534 /*unknown = IVAL(pdata,0);*/
1536 ret = sid_parse(_in_data + 4, sid_len, &sid);
1538 return NT_STATUS_INVALID_PARAMETER;
1540 DEBUGADD(10, ("for SID: %s\n",
1541 dom_sid_str_buf(&sid, &buf)));
1543 if (!sid_to_uid(&sid, &uid)) {
1544 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1545 dom_sid_str_buf(&sid, &buf),
1546 (unsigned long)sid_len));
1550 /* we can take a look at the find source :-)
1552 * find ./ -uid $uid -name '*' is what we need here
1555 * and send 4bytes len and then NULL terminated unicode strings
1558 * but I don't know how to deal with the paged results
1559 * (maybe we can hang the result anywhere in the fsp struct)
1561 * but I don't know how to deal with the paged results
1562 * (maybe we can hang the result anywhere in the fsp struct)
1564 * we don't send all files at once
1565 * and at the next we should *not* start from the beginning,
1566 * so we have to cache the result
1571 /* this works for now... */
1572 return NT_STATUS_OK;
1575 case FSCTL_QUERY_ALLOCATED_RANGES:
1577 /* FIXME: This is just a dummy reply, telling that all of the
1578 * file is allocated. MKS cp needs that.
1579 * Adding the real allocated ranges via FIEMAP on Linux
1580 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1581 * this FSCTL correct for sparse files.
1583 uint64_t offset, length;
1584 char *out_data_tmp = NULL;
1587 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1589 return NT_STATUS_INVALID_PARAMETER;
1592 if (max_out_len < 16) {
1593 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1595 return NT_STATUS_INVALID_PARAMETER;
1598 offset = BVAL(in_data,0);
1599 length = BVAL(in_data,8);
1601 if (offset + length < offset) {
1602 /* No 64-bit integer wrap. */
1603 return NT_STATUS_INVALID_PARAMETER;
1606 /* Shouldn't this be SMB_VFS_STAT ... ? */
1607 status = vfs_stat_fsp(fsp);
1608 if (!NT_STATUS_IS_OK(status)) {
1613 out_data_tmp = talloc_array(ctx, char, *out_len);
1614 if (out_data_tmp == NULL) {
1615 DEBUG(10, ("unable to allocate memory for response\n"));
1616 return NT_STATUS_NO_MEMORY;
1619 if (offset > fsp->fsp_name->st.st_ex_size ||
1620 fsp->fsp_name->st.st_ex_size == 0 ||
1622 memset(out_data_tmp, 0, *out_len);
1624 uint64_t end = offset + length;
1625 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1626 SBVAL(out_data_tmp, 0, 0);
1627 SBVAL(out_data_tmp, 8, end);
1630 *out_data = out_data_tmp;
1632 return NT_STATUS_OK;
1635 case FSCTL_IS_VOLUME_DIRTY:
1637 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1638 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1640 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1641 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1643 return NT_STATUS_INVALID_PARAMETER;
1648 * Only print once ... unfortunately there could be lots of
1649 * different FSCTLs that are called.
1651 if (!vfswrap_logged_ioctl_message) {
1652 vfswrap_logged_ioctl_message = true;
1653 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1654 __func__, function));
1658 return NT_STATUS_NOT_SUPPORTED;
1661 static bool vfswrap_is_offline(struct connection_struct *conn,
1662 const struct smb_filename *fname);
1664 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1665 struct smb_filename *smb_fname,
1670 offline = vfswrap_is_offline(handle->conn, smb_fname);
1672 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1675 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1678 struct vfswrap_get_dos_attributes_state {
1679 struct vfs_aio_state aio_state;
1680 connection_struct *conn;
1681 TALLOC_CTX *mem_ctx;
1682 struct tevent_context *ev;
1683 files_struct *dir_fsp;
1684 struct smb_filename *smb_fname;
1689 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq);
1691 static struct tevent_req *vfswrap_get_dos_attributes_send(
1692 TALLOC_CTX *mem_ctx,
1693 struct tevent_context *ev,
1694 struct vfs_handle_struct *handle,
1695 files_struct *dir_fsp,
1696 struct smb_filename *smb_fname)
1698 struct tevent_req *req = NULL;
1699 struct tevent_req *subreq = NULL;
1700 struct vfswrap_get_dos_attributes_state *state = NULL;
1702 req = tevent_req_create(mem_ctx, &state,
1703 struct vfswrap_get_dos_attributes_state);
1708 *state = (struct vfswrap_get_dos_attributes_state) {
1709 .conn = dir_fsp->conn,
1713 .smb_fname = smb_fname,
1716 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1720 SAMBA_XATTR_DOS_ATTRIB,
1722 if (tevent_req_nomem(subreq, req)) {
1723 return tevent_req_post(req, ev);
1725 tevent_req_set_callback(subreq,
1726 vfswrap_get_dos_attributes_getxattr_done,
1732 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq)
1734 struct tevent_req *req =
1735 tevent_req_callback_data(subreq,
1737 struct vfswrap_get_dos_attributes_state *state =
1738 tevent_req_data(req,
1739 struct vfswrap_get_dos_attributes_state);
1741 DATA_BLOB blob = {0};
1743 char *tofree = NULL;
1744 char pathbuf[PATH_MAX+1];
1746 struct smb_filename smb_fname;
1750 xattr_size = SMB_VFS_GETXATTRAT_RECV(subreq,
1754 TALLOC_FREE(subreq);
1755 if (xattr_size == -1) {
1756 status = map_nt_error_from_unix(state->aio_state.error);
1758 if (state->as_root) {
1759 tevent_req_nterror(req, status);
1762 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1763 tevent_req_nterror(req, status);
1767 state->as_root = true;
1770 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1774 SAMBA_XATTR_DOS_ATTRIB,
1777 if (tevent_req_nomem(subreq, req)) {
1780 tevent_req_set_callback(subreq,
1781 vfswrap_get_dos_attributes_getxattr_done,
1786 blob.length = xattr_size;
1788 status = parse_dos_attribute_blob(state->smb_fname,
1791 if (!NT_STATUS_IS_OK(status)) {
1792 tevent_req_nterror(req, status);
1796 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
1797 state->smb_fname->base_name,
1802 if (pathlen == -1) {
1803 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1807 smb_fname = (struct smb_filename) {
1809 .st = state->smb_fname->st,
1810 .flags = state->smb_fname->flags,
1811 .twrp = state->smb_fname->twrp,
1814 offline = vfswrap_is_offline(state->conn, &smb_fname);
1816 state->dosmode |= FILE_ATTRIBUTE_OFFLINE;
1818 TALLOC_FREE(tofree);
1820 tevent_req_done(req);
1824 static NTSTATUS vfswrap_get_dos_attributes_recv(struct tevent_req *req,
1825 struct vfs_aio_state *aio_state,
1828 struct vfswrap_get_dos_attributes_state *state =
1829 tevent_req_data(req,
1830 struct vfswrap_get_dos_attributes_state);
1833 if (tevent_req_is_nterror(req, &status)) {
1834 tevent_req_received(req);
1838 *aio_state = state->aio_state;
1839 *dosmode = state->dosmode;
1840 tevent_req_received(req);
1841 return NT_STATUS_OK;
1844 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1845 struct files_struct *fsp,
1850 offline = vfswrap_is_offline(handle->conn, fsp->fsp_name);
1852 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1855 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1858 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1859 const struct smb_filename *smb_fname,
1862 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1865 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1866 struct files_struct *fsp,
1869 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1872 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1874 struct vfswrap_offload_read_state {
1878 static struct tevent_req *vfswrap_offload_read_send(
1879 TALLOC_CTX *mem_ctx,
1880 struct tevent_context *ev,
1881 struct vfs_handle_struct *handle,
1882 struct files_struct *fsp,
1888 struct tevent_req *req = NULL;
1889 struct vfswrap_offload_read_state *state = NULL;
1892 req = tevent_req_create(mem_ctx, &state,
1893 struct vfswrap_offload_read_state);
1898 status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1899 &vfswrap_offload_ctx);
1900 if (tevent_req_nterror(req, status)) {
1901 return tevent_req_post(req, ev);
1904 if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1905 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1906 return tevent_req_post(req, ev);
1909 status = vfs_offload_token_create_blob(state, fsp, fsctl,
1911 if (tevent_req_nterror(req, status)) {
1912 return tevent_req_post(req, ev);
1915 status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1917 if (tevent_req_nterror(req, status)) {
1918 return tevent_req_post(req, ev);
1921 tevent_req_done(req);
1922 return tevent_req_post(req, ev);
1925 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
1926 struct vfs_handle_struct *handle,
1927 TALLOC_CTX *mem_ctx,
1930 struct vfswrap_offload_read_state *state = tevent_req_data(
1931 req, struct vfswrap_offload_read_state);
1934 if (tevent_req_is_nterror(req, &status)) {
1935 tevent_req_received(req);
1939 token->length = state->token.length;
1940 token->data = talloc_move(mem_ctx, &state->token.data);
1942 tevent_req_received(req);
1943 return NT_STATUS_OK;
1946 struct vfswrap_offload_write_state {
1948 bool read_lck_locked;
1949 bool write_lck_locked;
1951 struct tevent_context *src_ev;
1952 struct files_struct *src_fsp;
1954 struct tevent_context *dst_ev;
1955 struct files_struct *dst_fsp;
1959 size_t next_io_size;
1962 static void vfswrap_offload_write_cleanup(struct tevent_req *req,
1963 enum tevent_req_state req_state)
1965 struct vfswrap_offload_write_state *state = tevent_req_data(
1966 req, struct vfswrap_offload_write_state);
1969 if (state->dst_fsp == NULL) {
1973 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
1975 state->dst_fsp = NULL;
1978 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
1980 static struct tevent_req *vfswrap_offload_write_send(
1981 struct vfs_handle_struct *handle,
1982 TALLOC_CTX *mem_ctx,
1983 struct tevent_context *ev,
1986 off_t transfer_offset,
1987 struct files_struct *dest_fsp,
1991 struct tevent_req *req;
1992 struct vfswrap_offload_write_state *state = NULL;
1993 /* off_t is signed! */
1994 off_t max_offset = INT64_MAX - to_copy;
1995 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
1996 files_struct *src_fsp = NULL;
2000 req = tevent_req_create(mem_ctx, &state,
2001 struct vfswrap_offload_write_state);
2006 *state = (struct vfswrap_offload_write_state) {
2008 .src_off = transfer_offset,
2010 .dst_fsp = dest_fsp,
2011 .dst_off = dest_off,
2013 .remaining = to_copy,
2016 tevent_req_set_cleanup_fn(req, vfswrap_offload_write_cleanup);
2019 case FSCTL_SRV_COPYCHUNK:
2020 case FSCTL_SRV_COPYCHUNK_WRITE:
2023 case FSCTL_OFFLOAD_WRITE:
2024 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
2025 return tevent_req_post(req, ev);
2027 case FSCTL_DUP_EXTENTS_TO_FILE:
2028 DBG_DEBUG("COW clones not supported by vfs_default\n");
2029 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2030 return tevent_req_post(req, ev);
2033 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2034 return tevent_req_post(req, ev);
2038 * From here on we assume a copy-chunk fsctl
2042 tevent_req_done(req);
2043 return tevent_req_post(req, ev);
2046 if (state->src_off > max_offset) {
2048 * Protect integer checks below.
2050 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2051 return tevent_req_post(req, ev);
2053 if (state->src_off < 0) {
2055 * Protect integer checks below.
2057 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2058 return tevent_req_post(req, ev);
2060 if (state->dst_off > max_offset) {
2062 * Protect integer checks below.
2064 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2065 return tevent_req_post(req, ev);
2067 if (state->dst_off < 0) {
2069 * Protect integer checks below.
2071 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2072 return tevent_req_post(req, ev);
2075 status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
2077 if (tevent_req_nterror(req, status)) {
2078 return tevent_req_post(req, ev);
2081 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
2083 status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
2084 if (!NT_STATUS_IS_OK(status)) {
2085 tevent_req_nterror(req, status);
2086 return tevent_req_post(req, ev);
2089 ok = change_to_user_and_service_by_fsp(src_fsp);
2091 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2092 return tevent_req_post(req, ev);
2095 state->src_ev = src_fsp->conn->sconn->ev_ctx;
2096 state->src_fsp = src_fsp;
2098 status = vfs_stat_fsp(src_fsp);
2099 if (tevent_req_nterror(req, status)) {
2100 return tevent_req_post(req, ev);
2103 if (src_fsp->fsp_name->st.st_ex_size < state->src_off + to_copy) {
2105 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
2106 * If the SourceOffset or SourceOffset + Length extends beyond
2107 * the end of file, the server SHOULD<240> treat this as a
2108 * STATUS_END_OF_FILE error.
2110 * <240> Section 3.3.5.15.6: Windows servers will return
2111 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
2113 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
2114 return tevent_req_post(req, ev);
2117 state->buf = talloc_array(state, uint8_t, num);
2118 if (tevent_req_nomem(state->buf, req)) {
2119 return tevent_req_post(req, ev);
2122 status = vfswrap_offload_write_loop(req);
2123 if (!NT_STATUS_IS_OK(status)) {
2124 tevent_req_nterror(req, status);
2125 return tevent_req_post(req, ev);
2131 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
2133 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
2135 struct vfswrap_offload_write_state *state = tevent_req_data(
2136 req, struct vfswrap_offload_write_state);
2137 struct tevent_req *subreq = NULL;
2138 struct lock_struct read_lck;
2142 * This is called under the context of state->src_fsp.
2145 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
2147 init_strict_lock_struct(state->src_fsp,
2148 state->src_fsp->op->global->open_persistent_id,
2150 state->next_io_size,
2154 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
2158 return NT_STATUS_FILE_LOCK_CONFLICT;
2161 subreq = SMB_VFS_PREAD_SEND(state,
2165 state->next_io_size,
2167 if (subreq == NULL) {
2168 return NT_STATUS_NO_MEMORY;
2170 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
2172 return NT_STATUS_OK;
2175 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
2177 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
2179 struct tevent_req *req = tevent_req_callback_data(
2180 subreq, struct tevent_req);
2181 struct vfswrap_offload_write_state *state = tevent_req_data(
2182 req, struct vfswrap_offload_write_state);
2183 struct vfs_aio_state aio_state;
2184 struct lock_struct write_lck;
2188 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
2189 TALLOC_FREE(subreq);
2191 DBG_ERR("read failed: %s\n", strerror(aio_state.error));
2192 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2195 if (nread != state->next_io_size) {
2196 DBG_ERR("Short read, only %zd of %zu\n",
2197 nread, state->next_io_size);
2198 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2202 state->src_off += nread;
2204 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2206 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2210 init_strict_lock_struct(state->dst_fsp,
2211 state->dst_fsp->op->global->open_persistent_id,
2213 state->next_io_size,
2217 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
2221 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
2225 subreq = SMB_VFS_PWRITE_SEND(state,
2229 state->next_io_size,
2231 if (subreq == NULL) {
2232 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2235 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
2238 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
2240 struct tevent_req *req = tevent_req_callback_data(
2241 subreq, struct tevent_req);
2242 struct vfswrap_offload_write_state *state = tevent_req_data(
2243 req, struct vfswrap_offload_write_state);
2244 struct vfs_aio_state aio_state;
2249 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
2250 TALLOC_FREE(subreq);
2251 if (nwritten == -1) {
2252 DBG_ERR("write failed: %s\n", strerror(aio_state.error));
2253 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2256 if (nwritten != state->next_io_size) {
2257 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
2258 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2262 state->dst_off += nwritten;
2264 if (state->remaining < nwritten) {
2265 /* Paranoia check */
2266 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2269 state->remaining -= nwritten;
2270 if (state->remaining == 0) {
2271 tevent_req_done(req);
2275 ok = change_to_user_and_service_by_fsp(state->src_fsp);
2277 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2281 status = vfswrap_offload_write_loop(req);
2282 if (!NT_STATUS_IS_OK(status)) {
2283 tevent_req_nterror(req, status);
2290 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
2291 struct tevent_req *req,
2294 struct vfswrap_offload_write_state *state = tevent_req_data(
2295 req, struct vfswrap_offload_write_state);
2298 if (tevent_req_is_nterror(req, &status)) {
2299 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
2301 tevent_req_received(req);
2305 *copied = state->to_copy;
2306 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
2307 tevent_req_received(req);
2309 return NT_STATUS_OK;
2312 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
2313 TALLOC_CTX *mem_ctx,
2314 struct files_struct *fsp,
2315 struct smb_filename *smb_fname,
2316 uint16_t *_compression_fmt)
2318 return NT_STATUS_INVALID_DEVICE_REQUEST;
2321 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
2322 TALLOC_CTX *mem_ctx,
2323 struct files_struct *fsp,
2324 uint16_t compression_fmt)
2326 return NT_STATUS_INVALID_DEVICE_REQUEST;
2329 /********************************************************************
2330 Given a stat buffer return the allocated size on disk, taking into
2331 account sparse files.
2332 ********************************************************************/
2333 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
2334 struct files_struct *fsp,
2335 const SMB_STRUCT_STAT *sbuf)
2339 START_PROFILE(syscall_get_alloc_size);
2341 if(S_ISDIR(sbuf->st_ex_mode)) {
2346 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2347 /* The type of st_blocksize is blkcnt_t which *MUST* be
2348 signed (according to POSIX) and can be less than 64-bits.
2349 Ensure when we're converting to 64 bits wide we don't
2351 #if defined(SIZEOF_BLKCNT_T_8)
2352 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2353 #elif defined(SIZEOF_BLKCNT_T_4)
2355 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2356 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2359 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2363 * Some file systems do not allocate a block for very
2364 * small files. But for non-empty file should report a
2368 uint64_t filesize = get_file_size_stat(sbuf);
2370 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2374 result = get_file_size_stat(sbuf);
2377 if (fsp && fsp->initial_allocation_size)
2378 result = MAX(result,fsp->initial_allocation_size);
2380 result = smb_roundup(handle->conn, result);
2383 END_PROFILE(syscall_get_alloc_size);
2387 static int vfswrap_unlinkat(vfs_handle_struct *handle,
2388 struct files_struct *dirfsp,
2389 const struct smb_filename *smb_fname,
2394 START_PROFILE(syscall_unlinkat);
2396 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2398 if (is_named_stream(smb_fname)) {
2402 result = unlinkat(fsp_get_pathref_fd(dirfsp),
2403 smb_fname->base_name,
2407 END_PROFILE(syscall_unlinkat);
2411 static int vfswrap_chmod(vfs_handle_struct *handle,
2412 const struct smb_filename *smb_fname,
2417 START_PROFILE(syscall_chmod);
2418 result = chmod(smb_fname->base_name, mode);
2419 END_PROFILE(syscall_chmod);
2423 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2427 START_PROFILE(syscall_fchmod);
2428 #if defined(HAVE_FCHMOD)
2429 result = fchmod(fsp_get_io_fd(fsp), mode);
2435 END_PROFILE(syscall_fchmod);
2439 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2444 START_PROFILE(syscall_fchown);
2445 result = fchown(fsp_get_io_fd(fsp), uid, gid);
2446 END_PROFILE(syscall_fchown);
2454 static int vfswrap_lchown(vfs_handle_struct *handle,
2455 const struct smb_filename *smb_fname,
2461 START_PROFILE(syscall_lchown);
2462 result = lchown(smb_fname->base_name, uid, gid);
2463 END_PROFILE(syscall_lchown);
2467 static int vfswrap_chdir(vfs_handle_struct *handle,
2468 const struct smb_filename *smb_fname)
2472 START_PROFILE(syscall_chdir);
2473 result = chdir(smb_fname->base_name);
2474 END_PROFILE(syscall_chdir);
2478 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2482 struct smb_filename *smb_fname = NULL;
2484 START_PROFILE(syscall_getwd);
2485 result = sys_getwd();
2486 END_PROFILE(syscall_getwd);
2488 if (result == NULL) {
2491 smb_fname = synthetic_smb_fname(ctx,
2498 * sys_getwd() *always* returns malloced memory.
2499 * We must free here to avoid leaks:
2500 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2506 /*********************************************************************
2507 nsec timestamp resolution call. Convert down to whatever the underlying
2508 system will support.
2509 **********************************************************************/
2511 static int vfswrap_ntimes(vfs_handle_struct *handle,
2512 const struct smb_filename *smb_fname,
2513 struct smb_file_time *ft)
2517 START_PROFILE(syscall_ntimes);
2519 if (is_named_stream(smb_fname)) {
2525 if (is_omit_timespec(&ft->atime)) {
2526 ft->atime= smb_fname->st.st_ex_atime;
2529 if (is_omit_timespec(&ft->mtime)) {
2530 ft->mtime = smb_fname->st.st_ex_mtime;
2533 if (!is_omit_timespec(&ft->create_time)) {
2534 set_create_timespec_ea(handle->conn,
2539 if ((timespec_compare(&ft->atime,
2540 &smb_fname->st.st_ex_atime) == 0) &&
2541 (timespec_compare(&ft->mtime,
2542 &smb_fname->st.st_ex_mtime) == 0)) {
2547 #if defined(HAVE_UTIMENSAT)
2549 struct timespec ts[2];
2552 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2554 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2556 if (!((result == -1) && (errno == ENOSYS))) {
2560 #if defined(HAVE_UTIMES)
2562 struct timeval tv[2];
2563 tv[0] = convert_timespec_to_timeval(ft->atime);
2564 tv[1] = convert_timespec_to_timeval(ft->mtime);
2565 result = utimes(smb_fname->base_name, tv);
2567 result = utimes(smb_fname->base_name, NULL);
2569 if (!((result == -1) && (errno == ENOSYS))) {
2573 #if defined(HAVE_UTIME)
2575 struct utimbuf times;
2576 times.actime = convert_timespec_to_time_t(ft->atime);
2577 times.modtime = convert_timespec_to_time_t(ft->mtime);
2578 result = utime(smb_fname->base_name, ×);
2580 result = utime(smb_fname->base_name, NULL);
2582 if (!((result == -1) && (errno == ENOSYS))) {
2590 END_PROFILE(syscall_ntimes);
2594 /*********************************************************************
2595 A version of ftruncate that will write the space on disk if strict
2597 **********************************************************************/
2599 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2601 off_t space_to_write;
2602 uint64_t space_avail;
2603 uint64_t bsize,dfree,dsize;
2606 SMB_STRUCT_STAT *pst;
2609 ok = vfs_valid_pwrite_range(len, 0);
2615 status = vfs_stat_fsp(fsp);
2616 if (!NT_STATUS_IS_OK(status)) {
2619 pst = &fsp->fsp_name->st;
2622 if (S_ISFIFO(pst->st_ex_mode))
2626 if (pst->st_ex_size == len)
2629 /* Shrink - just ftruncate. */
2630 if (pst->st_ex_size > len)
2631 return ftruncate(fsp_get_io_fd(fsp), len);
2633 space_to_write = len - pst->st_ex_size;
2635 /* for allocation try fallocate first. This can fail on some
2636 platforms e.g. when the filesystem doesn't support it and no
2637 emulation is being done by the libc (like on AIX with JFS1). In that
2638 case we do our own emulation. fallocate implementations can
2639 return ENOTSUP or EINVAL in cases like that. */
2640 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2641 if (ret == -1 && errno == ENOSPC) {
2647 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2648 "error %d. Falling back to slow manual allocation\n", errno));
2650 /* available disk space is enough or not? */
2652 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2653 /* space_avail is 1k blocks */
2654 if (space_avail == (uint64_t)-1 ||
2655 ((uint64_t)space_to_write/1024 > space_avail) ) {
2660 /* Write out the real space on disk. */
2661 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2669 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2672 SMB_STRUCT_STAT *pst;
2676 START_PROFILE(syscall_ftruncate);
2678 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->fsp_flags.is_sparse) {
2679 result = strict_allocate_ftruncate(handle, fsp, len);
2680 END_PROFILE(syscall_ftruncate);
2684 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2685 ftruncate if the system supports it. Then I discovered that
2686 you can have some filesystems that support ftruncate
2687 expansion and some that don't! On Linux fat can't do
2688 ftruncate extend but ext2 can. */
2690 result = ftruncate(fsp_get_io_fd(fsp), len);
2692 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2693 extend a file with ftruncate. Provide alternate implementation
2696 /* Do an fstat to see if the file is longer than the requested
2697 size in which case the ftruncate above should have
2698 succeeded or shorter, in which case seek to len - 1 and
2699 write 1 byte of zero */
2700 status = vfs_stat_fsp(fsp);
2701 if (!NT_STATUS_IS_OK(status)) {
2705 /* We need to update the files_struct after successful ftruncate */
2710 pst = &fsp->fsp_name->st;
2713 if (S_ISFIFO(pst->st_ex_mode)) {
2719 if (pst->st_ex_size == len) {
2724 if (pst->st_ex_size > len) {
2725 /* the ftruncate should have worked */
2729 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2737 END_PROFILE(syscall_ftruncate);
2741 static int vfswrap_fallocate(vfs_handle_struct *handle,
2749 START_PROFILE(syscall_fallocate);
2751 result = sys_posix_fallocate(fsp_get_io_fd(fsp), offset, len);
2753 * posix_fallocate returns 0 on success, errno on error
2754 * and doesn't set errno. Make it behave like fallocate()
2755 * which returns -1, and sets errno on failure.
2762 /* sys_fallocate handles filtering of unsupported mode flags */
2763 result = sys_fallocate(fsp_get_io_fd(fsp), mode, offset, len);
2765 END_PROFILE(syscall_fallocate);
2769 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2773 START_PROFILE(syscall_fcntl_lock);
2775 if (fsp->fsp_flags.use_ofd_locks) {
2776 op = map_process_lock_to_ofd_lock(op);
2779 result = fcntl_lock(fsp_get_io_fd(fsp), op, offset, count, type);
2780 END_PROFILE(syscall_fcntl_lock);
2784 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2785 uint32_t share_access, uint32_t access_mask)
2787 START_PROFILE(syscall_kernel_flock);
2788 kernel_flock(fsp_get_io_fd(fsp), share_access, access_mask);
2789 END_PROFILE(syscall_kernel_flock);
2793 static int vfswrap_fcntl(vfs_handle_struct *handle, files_struct *fsp, int cmd,
2797 va_list dup_cmd_arg;
2801 START_PROFILE(syscall_fcntl);
2803 va_copy(dup_cmd_arg, cmd_arg);
2809 #if defined(HAVE_OFD_LOCKS)
2814 #if defined(HAVE_F_OWNER_EX)
2818 #if defined(HAVE_RW_HINTS)
2821 case F_GET_FILE_RW_HINT:
2822 case F_SET_FILE_RW_HINT:
2824 argp = va_arg(dup_cmd_arg, void *);
2825 result = sys_fcntl_ptr(fsp_get_io_fd(fsp), cmd, argp);
2828 val = va_arg(dup_cmd_arg, int);
2829 result = sys_fcntl_int(fsp_get_io_fd(fsp), cmd, val);
2832 va_end(dup_cmd_arg);
2834 END_PROFILE(syscall_fcntl);
2838 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2843 START_PROFILE(syscall_fcntl_getlock);
2845 if (fsp->fsp_flags.use_ofd_locks) {
2846 op = map_process_lock_to_ofd_lock(op);
2849 result = fcntl_getlock(fsp_get_io_fd(fsp), op, poffset, pcount, ptype, ppid);
2850 END_PROFILE(syscall_fcntl_getlock);
2854 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2859 START_PROFILE(syscall_linux_setlease);
2861 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2862 result = linux_setlease(fsp_get_io_fd(fsp), leasetype);
2866 END_PROFILE(syscall_linux_setlease);
2870 static int vfswrap_symlinkat(vfs_handle_struct *handle,
2871 const struct smb_filename *link_target,
2872 struct files_struct *dirfsp,
2873 const struct smb_filename *new_smb_fname)
2877 START_PROFILE(syscall_symlinkat);
2879 result = symlinkat(link_target->base_name,
2880 fsp_get_pathref_fd(dirfsp),
2881 new_smb_fname->base_name);
2882 END_PROFILE(syscall_symlinkat);
2886 static int vfswrap_readlinkat(vfs_handle_struct *handle,
2887 const struct files_struct *dirfsp,
2888 const struct smb_filename *smb_fname,
2894 START_PROFILE(syscall_readlinkat);
2896 result = readlinkat(fsp_get_pathref_fd(dirfsp),
2897 smb_fname->base_name,
2901 END_PROFILE(syscall_readlinkat);
2905 static int vfswrap_linkat(vfs_handle_struct *handle,
2906 files_struct *srcfsp,
2907 const struct smb_filename *old_smb_fname,
2908 files_struct *dstfsp,
2909 const struct smb_filename *new_smb_fname,
2914 START_PROFILE(syscall_linkat);
2916 result = linkat(fsp_get_pathref_fd(srcfsp),
2917 old_smb_fname->base_name,
2918 fsp_get_pathref_fd(dstfsp),
2919 new_smb_fname->base_name,
2922 END_PROFILE(syscall_linkat);
2926 static int vfswrap_mknodat(vfs_handle_struct *handle,
2927 files_struct *dirfsp,
2928 const struct smb_filename *smb_fname,
2934 START_PROFILE(syscall_mknodat);
2936 result = sys_mknodat(fsp_get_pathref_fd(dirfsp),
2937 smb_fname->base_name,
2941 END_PROFILE(syscall_mknodat);
2945 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2947 const struct smb_filename *smb_fname)
2950 struct smb_filename *result_fname = NULL;
2952 START_PROFILE(syscall_realpath);
2953 result = sys_realpath(smb_fname->base_name);
2954 END_PROFILE(syscall_realpath);
2956 result_fname = synthetic_smb_fname(ctx,
2964 return result_fname;
2967 static int vfswrap_chflags(vfs_handle_struct *handle,
2968 const struct smb_filename *smb_fname,
2972 return chflags(smb_fname->base_name, flags);
2979 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2980 const SMB_STRUCT_STAT *sbuf)
2984 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2988 key.devid = sbuf->st_ex_dev;
2989 key.inode = sbuf->st_ex_ino;
2990 /* key.extid is unused by default. */
2995 static uint64_t vfswrap_fs_file_id(struct vfs_handle_struct *handle,
2996 const SMB_STRUCT_STAT *psbuf)
3000 if (!(psbuf->st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)) {
3001 return psbuf->st_ex_file_id;
3004 if (handle->conn->base_share_dev == psbuf->st_ex_dev) {
3005 return (uint64_t)psbuf->st_ex_ino;
3009 file_id = ((psbuf->st_ex_ino) & UINT32_MAX);
3012 file_id |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32;
3017 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
3018 struct files_struct *fsp,
3019 const struct smb_filename *smb_fname,
3020 TALLOC_CTX *mem_ctx,
3021 unsigned int *pnum_streams,
3022 struct stream_struct **pstreams)
3024 SMB_STRUCT_STAT sbuf;
3025 struct stream_struct *tmp_streams = NULL;
3028 if ((fsp != NULL) && (fsp->fsp_flags.is_directory)) {
3030 * No default streams on directories
3035 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
3036 ret = SMB_VFS_FSTAT(fsp, &sbuf);
3039 struct smb_filename *smb_fname_cp = NULL;
3041 smb_fname_cp = cp_smb_filename_nostream(talloc_tos(), smb_fname);
3042 if (smb_fname_cp == NULL) {
3043 return NT_STATUS_NO_MEMORY;
3046 if (smb_fname_cp->flags & SMB_FILENAME_POSIX_PATH) {
3047 ret = SMB_VFS_LSTAT(handle->conn, smb_fname_cp);
3049 ret = SMB_VFS_STAT(handle->conn, smb_fname_cp);
3051 sbuf = smb_fname_cp->st;
3052 TALLOC_FREE(smb_fname_cp);
3056 return map_nt_error_from_unix(errno);
3059 if (S_ISDIR(sbuf.st_ex_mode)) {
3063 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
3064 (*pnum_streams) + 1);
3065 if (tmp_streams == NULL) {
3066 return NT_STATUS_NO_MEMORY;
3068 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
3069 if (tmp_streams[*pnum_streams].name == NULL) {
3070 return NT_STATUS_NO_MEMORY;
3072 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
3073 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
3076 *pstreams = tmp_streams;
3078 return NT_STATUS_OK;
3081 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
3082 const struct smb_filename *path,
3084 TALLOC_CTX *mem_ctx,
3088 * Don't fall back to get_real_filename so callers can differentiate
3089 * between a full directory scan and an actual case-insensitive stat.
3095 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
3096 const struct smb_filename *smb_fname)
3098 return handle->conn->connectpath;
3101 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
3102 struct byte_range_lock *br_lck,
3103 struct lock_struct *plock)
3105 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3107 /* Note: blr is not used in the default implementation. */
3108 return brl_lock_windows_default(br_lck, plock);
3111 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
3112 struct byte_range_lock *br_lck,
3113 const struct lock_struct *plock)
3115 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3117 return brl_unlock_windows_default(br_lck, plock);
3120 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
3122 struct lock_struct *plock)
3124 SMB_ASSERT(plock->lock_type == READ_LOCK ||
3125 plock->lock_type == WRITE_LOCK);
3127 return strict_lock_check_default(fsp, plock);
3130 /* NT ACL operations. */
3132 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
3134 uint32_t security_info,
3135 TALLOC_CTX *mem_ctx,
3136 struct security_descriptor **ppdesc)
3140 START_PROFILE(fget_nt_acl);
3141 result = posix_fget_nt_acl(fsp, security_info,
3143 END_PROFILE(fget_nt_acl);
3147 static NTSTATUS vfswrap_get_nt_acl_at(vfs_handle_struct *handle,
3148 struct files_struct *dirfsp,
3149 const struct smb_filename *smb_fname,
3150 uint32_t security_info,
3151 TALLOC_CTX *mem_ctx,
3152 struct security_descriptor **ppdesc)
3156 START_PROFILE(get_nt_acl_at);
3158 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
3160 result = posix_get_nt_acl(handle->conn,
3165 END_PROFILE(get_nt_acl_at);
3169 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
3173 START_PROFILE(fset_nt_acl);
3174 result = set_nt_acl(fsp, security_info_sent, psd);
3175 END_PROFILE(fset_nt_acl);
3179 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
3180 struct smb_filename *file,
3181 struct security_acl *sacl,
3182 uint32_t access_requested,
3183 uint32_t access_denied)
3185 return NT_STATUS_OK; /* Nothing to do here ... */
3188 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
3189 const struct smb_filename *smb_fname,
3190 SMB_ACL_TYPE_T type,
3191 TALLOC_CTX *mem_ctx)
3193 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
3196 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
3198 TALLOC_CTX *mem_ctx)
3200 return sys_acl_get_fd(handle, fsp, mem_ctx);
3203 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
3204 const struct smb_filename *smb_fname,
3205 SMB_ACL_TYPE_T acltype,
3208 return sys_acl_set_file(handle, smb_fname, acltype, theacl);
3211 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
3213 return sys_acl_set_fd(handle, fsp, theacl);
3216 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
3217 const struct smb_filename *smb_fname)
3219 return sys_acl_delete_def_file(handle, smb_fname);
3222 /****************************************************************
3223 Extended attribute operations.
3224 *****************************************************************/
3226 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
3227 const struct smb_filename *smb_fname,
3232 return getxattr(smb_fname->base_name, name, value, size);
3235 struct vfswrap_getxattrat_state {
3236 struct tevent_context *ev;
3237 files_struct *dir_fsp;
3238 const struct smb_filename *smb_fname;
3241 * The following variables are talloced off "state" which is protected
3242 * by a destructor and thus are guaranteed to be safe to be used in the
3243 * job function in the worker thread.
3246 const char *xattr_name;
3247 uint8_t *xattr_value;
3248 struct security_unix_token *token;
3251 struct vfs_aio_state vfs_aio_state;
3252 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
3255 static int vfswrap_getxattrat_state_destructor(
3256 struct vfswrap_getxattrat_state *state)
3261 static void vfswrap_getxattrat_do_sync(struct tevent_req *req);
3262 static void vfswrap_getxattrat_do_async(void *private_data);
3263 static void vfswrap_getxattrat_done(struct tevent_req *subreq);
3265 static struct tevent_req *vfswrap_getxattrat_send(
3266 TALLOC_CTX *mem_ctx,
3267 struct tevent_context *ev,
3268 struct vfs_handle_struct *handle,
3269 files_struct *dir_fsp,
3270 const struct smb_filename *smb_fname,
3271 const char *xattr_name,
3274 struct tevent_req *req = NULL;
3275 struct tevent_req *subreq = NULL;
3276 struct vfswrap_getxattrat_state *state = NULL;
3277 size_t max_threads = 0;
3278 bool have_per_thread_cwd = false;
3279 bool have_per_thread_creds = false;
3280 bool do_async = false;
3282 req = tevent_req_create(mem_ctx, &state,
3283 struct vfswrap_getxattrat_state);
3287 *state = (struct vfswrap_getxattrat_state) {
3290 .smb_fname = smb_fname,
3293 max_threads = pthreadpool_tevent_max_threads(dir_fsp->conn->sconn->pool);
3294 if (max_threads >= 1) {
3296 * We need a non sync threadpool!
3298 have_per_thread_cwd = per_thread_cwd_supported();
3300 #ifdef HAVE_LINUX_THREAD_CREDENTIALS
3301 have_per_thread_creds = true;
3303 if (have_per_thread_cwd && have_per_thread_creds) {
3307 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat, profile_p,
3308 state->profile_bytes, 0);
3310 if (fsp_get_pathref_fd(dir_fsp) == -1) {
3311 DBG_ERR("Need a valid directory fd\n");
3312 tevent_req_error(req, EINVAL);
3313 return tevent_req_post(req, ev);
3316 if (alloc_hint > 0) {
3317 state->xattr_value = talloc_zero_array(state,
3320 if (tevent_req_nomem(state->xattr_value, req)) {
3321 return tevent_req_post(req, ev);
3326 vfswrap_getxattrat_do_sync(req);
3327 return tevent_req_post(req, ev);
3331 * Now allocate all parameters from a memory context that won't go away
3332 * no matter what. These paremeters will get used in threads and we
3333 * can't reliably cancel threads, so all buffers passed to the threads
3334 * must not be freed before all referencing threads terminate.
3337 state->name = talloc_strdup(state, smb_fname->base_name);
3338 if (tevent_req_nomem(state->name, req)) {
3339 return tevent_req_post(req, ev);
3342 state->xattr_name = talloc_strdup(state, xattr_name);
3343 if (tevent_req_nomem(state->xattr_name, req)) {
3344 return tevent_req_post(req, ev);
3348 * This is a hot codepath so at first glance one might think we should
3349 * somehow optimize away the token allocation and do a
3350 * talloc_reference() or similar black magic instead. But due to the
3351 * talloc_stackframe pool per SMB2 request this should be a simple copy
3352 * without a malloc in most cases.
3354 if (geteuid() == sec_initial_uid()) {
3355 state->token = root_unix_token(state);
3357 state->token = copy_unix_token(
3359 dir_fsp->conn->session_info->unix_token);
3361 if (tevent_req_nomem(state->token, req)) {
3362 return tevent_req_post(req, ev);
3365 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3367 subreq = pthreadpool_tevent_job_send(
3370 dir_fsp->conn->sconn->pool,
3371 vfswrap_getxattrat_do_async,
3373 if (tevent_req_nomem(subreq, req)) {
3374 return tevent_req_post(req, ev);
3376 tevent_req_set_callback(subreq, vfswrap_getxattrat_done, req);
3378 talloc_set_destructor(state, vfswrap_getxattrat_state_destructor);
3383 static void vfswrap_getxattrat_do_sync(struct tevent_req *req)
3385 struct vfswrap_getxattrat_state *state = tevent_req_data(
3386 req, struct vfswrap_getxattrat_state);
3388 char *tofree = NULL;
3389 char pathbuf[PATH_MAX+1];
3393 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
3394 state->smb_fname->base_name,
3399 if (pathlen == -1) {
3400 tevent_req_error(req, ENOMEM);
3404 state->xattr_size = getxattr(path,
3407 talloc_array_length(state->xattr_value));
3409 TALLOC_FREE(tofree);
3410 if (state->xattr_size == -1) {
3411 tevent_req_error(req, err);
3415 tevent_req_done(req);
3419 static void vfswrap_getxattrat_do_async(void *private_data)
3421 struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3422 private_data, struct vfswrap_getxattrat_state);
3423 struct timespec start_time;
3424 struct timespec end_time;
3427 PROFILE_TIMESTAMP(&start_time);
3428 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
3431 * Here we simulate a getxattrat()
3432 * call using fchdir();getxattr()
3435 per_thread_cwd_activate();
3437 /* Become the correct credential on this thread. */
3438 ret = set_thread_credentials(state->token->uid,
3440 (size_t)state->token->ngroups,
3441 state->token->groups);
3443 state->xattr_size = -1;
3444 state->vfs_aio_state.error = errno;
3448 ret = fchdir(fsp_get_pathref_fd(state->dir_fsp));
3450 state->xattr_size = -1;
3451 state->vfs_aio_state.error = errno;
3455 state->xattr_size = getxattr(state->name,
3458 talloc_array_length(state->xattr_value));
3459 if (state->xattr_size == -1) {
3460 state->vfs_aio_state.error = errno;
3464 PROFILE_TIMESTAMP(&end_time);
3465 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
3466 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3469 static void vfswrap_getxattrat_done(struct tevent_req *subreq)
3471 struct tevent_req *req = tevent_req_callback_data(
3472 subreq, struct tevent_req);
3473 struct vfswrap_getxattrat_state *state = tevent_req_data(
3474 req, struct vfswrap_getxattrat_state);
3479 * Make sure we run as the user again
3481 ok = change_to_user_and_service_by_fsp(state->dir_fsp);
3484 ret = pthreadpool_tevent_job_recv(subreq);
3485 TALLOC_FREE(subreq);
3486 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
3487 talloc_set_destructor(state, NULL);
3489 if (ret != EAGAIN) {
3490 tevent_req_error(req, ret);
3494 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
3495 * means the lower level pthreadpool failed to create a new
3496 * thread. Fallback to sync processing in that case to allow
3497 * some progress for the client.
3499 vfswrap_getxattrat_do_sync(req);
3503 if (state->xattr_size == -1) {
3504 tevent_req_error(req, state->vfs_aio_state.error);
3508 if (state->xattr_value == NULL) {
3510 * The caller only wanted the size.
3512 tevent_req_done(req);
3517 * shrink the buffer to the returned size.
3518 * (can't fail). It means NULL if size is 0.
3520 state->xattr_value = talloc_realloc(state,
3525 tevent_req_done(req);
3528 static ssize_t vfswrap_getxattrat_recv(struct tevent_req *req,
3529 struct vfs_aio_state *aio_state,
3530 TALLOC_CTX *mem_ctx,
3531 uint8_t **xattr_value)
3533 struct vfswrap_getxattrat_state *state = tevent_req_data(
3534 req, struct vfswrap_getxattrat_state);
3537 if (tevent_req_is_unix_error(req, &aio_state->error)) {
3538 tevent_req_received(req);
3542 *aio_state = state->vfs_aio_state;
3543 xattr_size = state->xattr_size;
3544 if (xattr_value != NULL) {
3545 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
3548 tevent_req_received(req);
3552 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle,
3553 struct files_struct *fsp,
3558 return fgetxattr(fsp_get_io_fd(fsp), name, value, size);
3561 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
3562 const struct smb_filename *smb_fname,
3566 return listxattr(smb_fname->base_name, list, size);
3569 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
3571 return flistxattr(fsp_get_io_fd(fsp), list, size);
3574 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
3575 const struct smb_filename *smb_fname,
3578 return removexattr(smb_fname->base_name, name);
3581 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
3583 return fremovexattr(fsp_get_io_fd(fsp), name);
3586 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
3587 const struct smb_filename *smb_fname,
3593 return setxattr(smb_fname->base_name, name, value, size, flags);
3596 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
3598 return fsetxattr(fsp_get_io_fd(fsp), name, value, size, flags);
3601 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
3606 static bool vfswrap_is_offline(struct connection_struct *conn,
3607 const struct smb_filename *fname)
3611 bool offline = false;
3613 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
3617 if (!lp_dmapi_support(SNUM(conn)) || !dmapi_have_session()) {
3618 #if defined(ENOTSUP)
3624 status = get_full_smb_filename(talloc_tos(), fname, &path);
3625 if (!NT_STATUS_IS_OK(status)) {
3626 errno = map_errno_from_nt_status(status);
3630 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
3637 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
3638 struct files_struct *fsp,
3639 TALLOC_CTX *mem_ctx,
3642 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
3645 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
3646 struct files_struct *fsp,
3647 const DATA_BLOB old_cookie,
3648 TALLOC_CTX *mem_ctx,
3649 DATA_BLOB *new_cookie)
3651 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
3655 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
3656 struct smb_request *smb1req,
3657 struct smbXsrv_open *op,
3658 const DATA_BLOB old_cookie,
3659 TALLOC_CTX *mem_ctx,
3660 struct files_struct **fsp,
3661 DATA_BLOB *new_cookie)
3663 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
3664 old_cookie, mem_ctx,
3668 static struct vfs_fn_pointers vfs_default_fns = {
3669 /* Disk operations */
3671 .connect_fn = vfswrap_connect,
3672 .disconnect_fn = vfswrap_disconnect,
3673 .disk_free_fn = vfswrap_disk_free,
3674 .get_quota_fn = vfswrap_get_quota,
3675 .set_quota_fn = vfswrap_set_quota,
3676 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3677 .statvfs_fn = vfswrap_statvfs,
3678 .fs_capabilities_fn = vfswrap_fs_capabilities,
3679 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3680 .create_dfs_pathat_fn = vfswrap_create_dfs_pathat,
3681 .read_dfs_pathat_fn = vfswrap_read_dfs_pathat,
3682 .snap_check_path_fn = vfswrap_snap_check_path,
3683 .snap_create_fn = vfswrap_snap_create,
3684 .snap_delete_fn = vfswrap_snap_delete,
3686 /* Directory operations */
3688 .fdopendir_fn = vfswrap_fdopendir,
3689 .readdir_fn = vfswrap_readdir,
3690 .readdir_attr_fn = vfswrap_readdir_attr,
3691 .seekdir_fn = vfswrap_seekdir,
3692 .telldir_fn = vfswrap_telldir,
3693 .rewind_dir_fn = vfswrap_rewinddir,
3694 .mkdirat_fn = vfswrap_mkdirat,
3695 .closedir_fn = vfswrap_closedir,
3697 /* File operations */
3699 .openat_fn = vfswrap_openat,
3700 .create_file_fn = vfswrap_create_file,
3701 .close_fn = vfswrap_close,
3702 .pread_fn = vfswrap_pread,
3703 .pread_send_fn = vfswrap_pread_send,
3704 .pread_recv_fn = vfswrap_pread_recv,
3705 .pwrite_fn = vfswrap_pwrite,
3706 .pwrite_send_fn = vfswrap_pwrite_send,
3707 .pwrite_recv_fn = vfswrap_pwrite_recv,
3708 .lseek_fn = vfswrap_lseek,
3709 .sendfile_fn = vfswrap_sendfile,
3710 .recvfile_fn = vfswrap_recvfile,
3711 .renameat_fn = vfswrap_renameat,
3712 .fsync_send_fn = vfswrap_fsync_send,
3713 .fsync_recv_fn = vfswrap_fsync_recv,
3714 .stat_fn = vfswrap_stat,
3715 .fstat_fn = vfswrap_fstat,
3716 .lstat_fn = vfswrap_lstat,
3717 .get_alloc_size_fn = vfswrap_get_alloc_size,
3718 .unlinkat_fn = vfswrap_unlinkat,
3719 .chmod_fn = vfswrap_chmod,
3720 .fchmod_fn = vfswrap_fchmod,
3721 .fchown_fn = vfswrap_fchown,
3722 .lchown_fn = vfswrap_lchown,
3723 .chdir_fn = vfswrap_chdir,
3724 .getwd_fn = vfswrap_getwd,
3725 .ntimes_fn = vfswrap_ntimes,
3726 .ftruncate_fn = vfswrap_ftruncate,
3727 .fallocate_fn = vfswrap_fallocate,
3728 .lock_fn = vfswrap_lock,
3729 .kernel_flock_fn = vfswrap_kernel_flock,
3730 .fcntl_fn = vfswrap_fcntl,
3731 .linux_setlease_fn = vfswrap_linux_setlease,
3732 .getlock_fn = vfswrap_getlock,
3733 .symlinkat_fn = vfswrap_symlinkat,
3734 .readlinkat_fn = vfswrap_readlinkat,
3735 .linkat_fn = vfswrap_linkat,
3736 .mknodat_fn = vfswrap_mknodat,
3737 .realpath_fn = vfswrap_realpath,
3738 .chflags_fn = vfswrap_chflags,
3739 .file_id_create_fn = vfswrap_file_id_create,
3740 .fs_file_id_fn = vfswrap_fs_file_id,
3741 .streaminfo_fn = vfswrap_streaminfo,
3742 .get_real_filename_fn = vfswrap_get_real_filename,
3743 .connectpath_fn = vfswrap_connectpath,
3744 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
3745 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3746 .strict_lock_check_fn = vfswrap_strict_lock_check,
3747 .translate_name_fn = vfswrap_translate_name,
3748 .fsctl_fn = vfswrap_fsctl,
3749 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
3750 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
3751 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
3752 .get_dos_attributes_send_fn = vfswrap_get_dos_attributes_send,
3753 .get_dos_attributes_recv_fn = vfswrap_get_dos_attributes_recv,
3754 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
3755 .offload_read_send_fn = vfswrap_offload_read_send,
3756 .offload_read_recv_fn = vfswrap_offload_read_recv,
3757 .offload_write_send_fn = vfswrap_offload_write_send,
3758 .offload_write_recv_fn = vfswrap_offload_write_recv,
3759 .get_compression_fn = vfswrap_get_compression,
3760 .set_compression_fn = vfswrap_set_compression,
3762 /* NT ACL operations. */
3764 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
3765 .get_nt_acl_at_fn = vfswrap_get_nt_acl_at,
3766 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
3767 .audit_file_fn = vfswrap_audit_file,
3769 /* POSIX ACL operations. */
3771 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
3772 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3773 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
3774 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3775 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
3776 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3777 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
3779 /* EA operations. */
3780 .getxattr_fn = vfswrap_getxattr,
3781 .getxattrat_send_fn = vfswrap_getxattrat_send,
3782 .getxattrat_recv_fn = vfswrap_getxattrat_recv,
3783 .fgetxattr_fn = vfswrap_fgetxattr,
3784 .listxattr_fn = vfswrap_listxattr,
3785 .flistxattr_fn = vfswrap_flistxattr,
3786 .removexattr_fn = vfswrap_removexattr,
3787 .fremovexattr_fn = vfswrap_fremovexattr,
3788 .setxattr_fn = vfswrap_setxattr,
3789 .fsetxattr_fn = vfswrap_fsetxattr,
3791 /* aio operations */
3792 .aio_force_fn = vfswrap_aio_force,
3794 /* durable handle operations */
3795 .durable_cookie_fn = vfswrap_durable_cookie,
3796 .durable_disconnect_fn = vfswrap_durable_disconnect,
3797 .durable_reconnect_fn = vfswrap_durable_reconnect,
3801 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3804 * Here we need to implement every call!
3806 * As this is the end of the vfs module chain.
3808 smb_vfs_assert_all_fns(&vfs_default_fns, DEFAULT_VFS_MODULE_NAME);
3809 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3810 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);