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,
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(dirfsp->fh->fd,
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->fh->fd);
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(dirfsp->fh->fd, 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(dirfsp->fh->fd, smb_fname->base_name, flags, mode);
708 END_PROFILE(syscall_openat);
711 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
712 struct smb_request *req,
713 struct smb_filename *smb_fname,
714 uint32_t access_mask,
715 uint32_t share_access,
716 uint32_t create_disposition,
717 uint32_t create_options,
718 uint32_t file_attributes,
719 uint32_t oplock_request,
720 const struct smb2_lease *lease,
721 uint64_t allocation_size,
722 uint32_t private_flags,
723 struct security_descriptor *sd,
724 struct ea_list *ea_list,
725 files_struct **result,
727 const struct smb2_create_blobs *in_context_blobs,
728 struct smb2_create_blobs *out_context_blobs)
730 return create_file_default(handle->conn, req, smb_fname,
731 access_mask, share_access,
732 create_disposition, create_options,
733 file_attributes, oplock_request, lease,
734 allocation_size, private_flags,
736 pinfo, in_context_blobs, out_context_blobs);
739 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
743 START_PROFILE(syscall_close);
744 result = fd_close_posix(fsp);
745 END_PROFILE(syscall_close);
749 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
750 size_t n, off_t offset)
754 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
755 START_PROFILE_BYTES(syscall_pread, n);
756 result = sys_pread_full(fsp->fh->fd, data, n, offset);
757 END_PROFILE_BYTES(syscall_pread);
759 if (result == -1 && errno == ESPIPE) {
760 /* Maintain the fiction that pipes can be seeked (sought?) on. */
761 result = sys_read(fsp->fh->fd, data, n);
765 #else /* HAVE_PREAD */
768 #endif /* HAVE_PREAD */
773 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
774 size_t n, off_t offset)
778 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
779 START_PROFILE_BYTES(syscall_pwrite, n);
780 result = sys_pwrite_full(fsp->fh->fd, data, n, offset);
781 END_PROFILE_BYTES(syscall_pwrite);
783 if (result == -1 && errno == ESPIPE) {
784 /* Maintain the fiction that pipes can be sought on. */
785 result = sys_write(fsp->fh->fd, data, n);
788 #else /* HAVE_PWRITE */
791 #endif /* HAVE_PWRITE */
796 struct vfswrap_pread_state {
803 struct vfs_aio_state vfs_aio_state;
804 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
807 static void vfs_pread_do(void *private_data);
808 static void vfs_pread_done(struct tevent_req *subreq);
809 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state);
811 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
813 struct tevent_context *ev,
814 struct files_struct *fsp,
816 size_t n, off_t offset)
818 struct tevent_req *req, *subreq;
819 struct vfswrap_pread_state *state;
821 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
827 state->fd = fsp->fh->fd;
830 state->offset = offset;
832 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
833 state->profile_bytes, n);
834 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
836 subreq = pthreadpool_tevent_job_send(
837 state, ev, handle->conn->sconn->pool,
838 vfs_pread_do, state);
839 if (tevent_req_nomem(subreq, req)) {
840 return tevent_req_post(req, ev);
842 tevent_req_set_callback(subreq, vfs_pread_done, req);
844 talloc_set_destructor(state, vfs_pread_state_destructor);
849 static void vfs_pread_do(void *private_data)
851 struct vfswrap_pread_state *state = talloc_get_type_abort(
852 private_data, struct vfswrap_pread_state);
853 struct timespec start_time;
854 struct timespec end_time;
856 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
858 PROFILE_TIMESTAMP(&start_time);
860 state->ret = sys_pread_full(state->fd,
865 if (state->ret == -1) {
866 state->vfs_aio_state.error = errno;
869 PROFILE_TIMESTAMP(&end_time);
871 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
873 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
876 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state)
881 static void vfs_pread_done(struct tevent_req *subreq)
883 struct tevent_req *req = tevent_req_callback_data(
884 subreq, struct tevent_req);
885 struct vfswrap_pread_state *state = tevent_req_data(
886 req, struct vfswrap_pread_state);
889 ret = pthreadpool_tevent_job_recv(subreq);
891 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
892 talloc_set_destructor(state, NULL);
895 tevent_req_error(req, ret);
899 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
900 * means the lower level pthreadpool failed to create a new
901 * thread. Fallback to sync processing in that case to allow
902 * some progress for the client.
907 tevent_req_done(req);
910 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
911 struct vfs_aio_state *vfs_aio_state)
913 struct vfswrap_pread_state *state = tevent_req_data(
914 req, struct vfswrap_pread_state);
916 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
920 *vfs_aio_state = state->vfs_aio_state;
924 struct vfswrap_pwrite_state {
931 struct vfs_aio_state vfs_aio_state;
932 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
935 static void vfs_pwrite_do(void *private_data);
936 static void vfs_pwrite_done(struct tevent_req *subreq);
937 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state);
939 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
941 struct tevent_context *ev,
942 struct files_struct *fsp,
944 size_t n, off_t offset)
946 struct tevent_req *req, *subreq;
947 struct vfswrap_pwrite_state *state;
949 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
955 state->fd = fsp->fh->fd;
958 state->offset = offset;
960 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
961 state->profile_bytes, n);
962 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
964 subreq = pthreadpool_tevent_job_send(
965 state, ev, handle->conn->sconn->pool,
966 vfs_pwrite_do, state);
967 if (tevent_req_nomem(subreq, req)) {
968 return tevent_req_post(req, ev);
970 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
972 talloc_set_destructor(state, vfs_pwrite_state_destructor);
977 static void vfs_pwrite_do(void *private_data)
979 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
980 private_data, struct vfswrap_pwrite_state);
981 struct timespec start_time;
982 struct timespec end_time;
984 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
986 PROFILE_TIMESTAMP(&start_time);
988 state->ret = sys_pwrite_full(state->fd,
993 if (state->ret == -1) {
994 state->vfs_aio_state.error = errno;
997 PROFILE_TIMESTAMP(&end_time);
999 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1001 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1004 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state)
1009 static void vfs_pwrite_done(struct tevent_req *subreq)
1011 struct tevent_req *req = tevent_req_callback_data(
1012 subreq, struct tevent_req);
1013 struct vfswrap_pwrite_state *state = tevent_req_data(
1014 req, struct vfswrap_pwrite_state);
1017 ret = pthreadpool_tevent_job_recv(subreq);
1018 TALLOC_FREE(subreq);
1019 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1020 talloc_set_destructor(state, NULL);
1022 if (ret != EAGAIN) {
1023 tevent_req_error(req, ret);
1027 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1028 * means the lower level pthreadpool failed to create a new
1029 * thread. Fallback to sync processing in that case to allow
1030 * some progress for the client.
1032 vfs_pwrite_do(state);
1035 tevent_req_done(req);
1038 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
1039 struct vfs_aio_state *vfs_aio_state)
1041 struct vfswrap_pwrite_state *state = tevent_req_data(
1042 req, struct vfswrap_pwrite_state);
1044 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1048 *vfs_aio_state = state->vfs_aio_state;
1052 struct vfswrap_fsync_state {
1056 struct vfs_aio_state vfs_aio_state;
1057 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
1060 static void vfs_fsync_do(void *private_data);
1061 static void vfs_fsync_done(struct tevent_req *subreq);
1062 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state);
1064 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
1065 TALLOC_CTX *mem_ctx,
1066 struct tevent_context *ev,
1067 struct files_struct *fsp)
1069 struct tevent_req *req, *subreq;
1070 struct vfswrap_fsync_state *state;
1072 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
1078 state->fd = fsp->fh->fd;
1080 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_fsync, profile_p,
1081 state->profile_bytes, 0);
1082 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1084 subreq = pthreadpool_tevent_job_send(
1085 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
1086 if (tevent_req_nomem(subreq, req)) {
1087 return tevent_req_post(req, ev);
1089 tevent_req_set_callback(subreq, vfs_fsync_done, req);
1091 talloc_set_destructor(state, vfs_fsync_state_destructor);
1096 static void vfs_fsync_do(void *private_data)
1098 struct vfswrap_fsync_state *state = talloc_get_type_abort(
1099 private_data, struct vfswrap_fsync_state);
1100 struct timespec start_time;
1101 struct timespec end_time;
1103 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
1105 PROFILE_TIMESTAMP(&start_time);
1108 state->ret = fsync(state->fd);
1109 } while ((state->ret == -1) && (errno == EINTR));
1111 if (state->ret == -1) {
1112 state->vfs_aio_state.error = errno;
1115 PROFILE_TIMESTAMP(&end_time);
1117 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1119 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1122 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state)
1127 static void vfs_fsync_done(struct tevent_req *subreq)
1129 struct tevent_req *req = tevent_req_callback_data(
1130 subreq, struct tevent_req);
1131 struct vfswrap_fsync_state *state = tevent_req_data(
1132 req, struct vfswrap_fsync_state);
1135 ret = pthreadpool_tevent_job_recv(subreq);
1136 TALLOC_FREE(subreq);
1137 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1138 talloc_set_destructor(state, NULL);
1140 if (ret != EAGAIN) {
1141 tevent_req_error(req, ret);
1145 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1146 * means the lower level pthreadpool failed to create a new
1147 * thread. Fallback to sync processing in that case to allow
1148 * some progress for the client.
1150 vfs_fsync_do(state);
1153 tevent_req_done(req);
1156 static int vfswrap_fsync_recv(struct tevent_req *req,
1157 struct vfs_aio_state *vfs_aio_state)
1159 struct vfswrap_fsync_state *state = tevent_req_data(
1160 req, struct vfswrap_fsync_state);
1162 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1166 *vfs_aio_state = state->vfs_aio_state;
1170 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1174 START_PROFILE(syscall_lseek);
1176 result = lseek(fsp->fh->fd, offset, whence);
1178 * We want to maintain the fiction that we can seek
1179 * on a fifo for file system purposes. This allows
1180 * people to set up UNIX fifo's that feed data to Windows
1181 * applications. JRA.
1184 if((result == -1) && (errno == ESPIPE)) {
1189 END_PROFILE(syscall_lseek);
1193 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1194 off_t offset, size_t n)
1198 START_PROFILE_BYTES(syscall_sendfile, n);
1199 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
1200 END_PROFILE_BYTES(syscall_sendfile);
1204 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1206 files_struct *tofsp,
1212 START_PROFILE_BYTES(syscall_recvfile, n);
1213 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
1214 END_PROFILE_BYTES(syscall_recvfile);
1218 static int vfswrap_renameat(vfs_handle_struct *handle,
1219 files_struct *srcfsp,
1220 const struct smb_filename *smb_fname_src,
1221 files_struct *dstfsp,
1222 const struct smb_filename *smb_fname_dst)
1226 START_PROFILE(syscall_renameat);
1228 if (is_named_stream(smb_fname_src) || is_named_stream(smb_fname_dst)) {
1233 result = renameat(srcfsp->fh->fd,
1234 smb_fname_src->base_name,
1236 smb_fname_dst->base_name);
1239 END_PROFILE(syscall_renameat);
1243 static int vfswrap_stat(vfs_handle_struct *handle,
1244 struct smb_filename *smb_fname)
1248 START_PROFILE(syscall_stat);
1250 if (is_named_stream(smb_fname)) {
1255 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1256 lp_fake_directory_create_times(SNUM(handle->conn)));
1258 END_PROFILE(syscall_stat);
1262 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1266 START_PROFILE(syscall_fstat);
1267 result = sys_fstat(fsp->fh->fd,
1268 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1269 END_PROFILE(syscall_fstat);
1273 static int vfswrap_lstat(vfs_handle_struct *handle,
1274 struct smb_filename *smb_fname)
1278 START_PROFILE(syscall_lstat);
1280 if (is_named_stream(smb_fname)) {
1285 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1286 lp_fake_directory_create_times(SNUM(handle->conn)));
1288 END_PROFILE(syscall_lstat);
1292 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1294 enum vfs_translate_direction direction,
1295 TALLOC_CTX *mem_ctx,
1298 return NT_STATUS_NONE_MAPPED;
1302 * Implement the default fsctl operation.
1304 static bool vfswrap_logged_ioctl_message = false;
1306 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1307 struct files_struct *fsp,
1310 uint16_t req_flags, /* Needed for UNICODE ... */
1311 const uint8_t *_in_data,
1313 uint8_t **_out_data,
1314 uint32_t max_out_len,
1317 const char *in_data = (const char *)_in_data;
1318 char **out_data = (char **)_out_data;
1322 case FSCTL_SET_SPARSE:
1324 bool set_sparse = true;
1326 if (in_len >= 1 && in_data[0] == 0) {
1330 status = file_set_sparse(handle->conn, fsp, set_sparse);
1332 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1333 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1334 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1335 nt_errstr(status)));
1340 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1342 unsigned char objid[16];
1343 char *return_data = NULL;
1345 /* This should return the object-id on this file.
1346 * I think I'll make this be the inode+dev. JRA.
1349 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1350 fsp_fnum_dbg(fsp)));
1352 *out_len = MIN(max_out_len, 64);
1354 /* Hmmm, will this cause problems if less data asked for? */
1355 return_data = talloc_array(ctx, char, 64);
1356 if (return_data == NULL) {
1357 return NT_STATUS_NO_MEMORY;
1360 /* For backwards compatibility only store the dev/inode. */
1361 push_file_id_16(return_data, &fsp->file_id);
1362 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1363 push_file_id_16(return_data+32, &fsp->file_id);
1364 memset(return_data+48, 0, 16);
1365 *out_data = return_data;
1366 return NT_STATUS_OK;
1369 case FSCTL_GET_REPARSE_POINT:
1371 status = fsctl_get_reparse_point(
1372 fsp, ctx, out_data, max_out_len, out_len);
1376 case FSCTL_SET_REPARSE_POINT:
1378 status = fsctl_set_reparse_point(fsp, ctx, _in_data, in_len);
1382 case FSCTL_DELETE_REPARSE_POINT:
1384 status = fsctl_del_reparse_point(fsp, ctx, _in_data, in_len);
1388 case FSCTL_GET_SHADOW_COPY_DATA:
1391 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1392 * and return their volume names. If max_data_count is 16, then it is just
1393 * asking for the number of volumes and length of the combined names.
1395 * pdata is the data allocated by our caller, but that uses
1396 * total_data_count (which is 0 in our case) rather than max_data_count.
1397 * Allocate the correct amount and return the pointer to let
1398 * it be deallocated when we return.
1400 struct shadow_copy_data *shadow_data = NULL;
1401 bool labels = False;
1402 uint32_t labels_data_count = 0;
1404 char *cur_pdata = NULL;
1406 if (max_out_len < 16) {
1407 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1409 return NT_STATUS_INVALID_PARAMETER;
1412 if (max_out_len > 16) {
1416 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1417 if (shadow_data == NULL) {
1418 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1419 return NT_STATUS_NO_MEMORY;
1423 * Call the VFS routine to actually do the work.
1425 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1428 /* broken module didn't set errno on error */
1429 status = NT_STATUS_UNSUCCESSFUL;
1431 status = map_nt_error_from_unix(errno);
1432 if (NT_STATUS_EQUAL(status,
1433 NT_STATUS_NOT_SUPPORTED)) {
1437 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1438 "connectpath %s, failed - %s.\n",
1439 fsp->conn->connectpath,
1440 nt_errstr(status)));
1441 TALLOC_FREE(shadow_data);
1445 labels_data_count = (shadow_data->num_volumes * 2 *
1446 sizeof(SHADOW_COPY_LABEL)) + 2;
1451 *out_len = 12 + labels_data_count;
1454 if (max_out_len < *out_len) {
1455 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1456 max_out_len, *out_len));
1457 TALLOC_FREE(shadow_data);
1458 return NT_STATUS_BUFFER_TOO_SMALL;
1461 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1462 if (cur_pdata == NULL) {
1463 TALLOC_FREE(shadow_data);
1464 return NT_STATUS_NO_MEMORY;
1467 *out_data = cur_pdata;
1469 /* num_volumes 4 bytes */
1470 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1473 /* num_labels 4 bytes */
1474 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1477 /* needed_data_count 4 bytes */
1478 SIVAL(cur_pdata, 8, labels_data_count);
1482 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1483 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1484 if (labels && shadow_data->labels) {
1485 for (i=0; i<shadow_data->num_volumes; i++) {
1487 status = srvstr_push(cur_pdata, req_flags,
1488 cur_pdata, shadow_data->labels[i],
1489 2 * sizeof(SHADOW_COPY_LABEL),
1490 STR_UNICODE|STR_TERMINATE, &len);
1491 if (!NT_STATUS_IS_OK(status)) {
1492 TALLOC_FREE(*out_data);
1493 TALLOC_FREE(shadow_data);
1496 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1497 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1501 TALLOC_FREE(shadow_data);
1503 return NT_STATUS_OK;
1506 case FSCTL_FIND_FILES_BY_SID:
1508 /* pretend this succeeded -
1510 * we have to send back a list with all files owned by this SID
1512 * but I have to check that --metze
1516 struct dom_sid_buf buf;
1520 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1521 fsp_fnum_dbg(fsp)));
1524 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1525 return NT_STATUS_INVALID_PARAMETER;
1528 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1530 /* unknown 4 bytes: this is not the length of the sid :-( */
1531 /*unknown = IVAL(pdata,0);*/
1533 ret = sid_parse(_in_data + 4, sid_len, &sid);
1535 return NT_STATUS_INVALID_PARAMETER;
1537 DEBUGADD(10, ("for SID: %s\n",
1538 dom_sid_str_buf(&sid, &buf)));
1540 if (!sid_to_uid(&sid, &uid)) {
1541 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1542 dom_sid_str_buf(&sid, &buf),
1543 (unsigned long)sid_len));
1547 /* we can take a look at the find source :-)
1549 * find ./ -uid $uid -name '*' is what we need here
1552 * and send 4bytes len and then NULL terminated unicode strings
1555 * but I don't know how to deal with the paged results
1556 * (maybe we can hang the result anywhere in the fsp struct)
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 * we don't send all files at once
1562 * and at the next we should *not* start from the beginning,
1563 * so we have to cache the result
1568 /* this works for now... */
1569 return NT_STATUS_OK;
1572 case FSCTL_QUERY_ALLOCATED_RANGES:
1574 /* FIXME: This is just a dummy reply, telling that all of the
1575 * file is allocated. MKS cp needs that.
1576 * Adding the real allocated ranges via FIEMAP on Linux
1577 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1578 * this FSCTL correct for sparse files.
1580 uint64_t offset, length;
1581 char *out_data_tmp = NULL;
1584 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1586 return NT_STATUS_INVALID_PARAMETER;
1589 if (max_out_len < 16) {
1590 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1592 return NT_STATUS_INVALID_PARAMETER;
1595 offset = BVAL(in_data,0);
1596 length = BVAL(in_data,8);
1598 if (offset + length < offset) {
1599 /* No 64-bit integer wrap. */
1600 return NT_STATUS_INVALID_PARAMETER;
1603 /* Shouldn't this be SMB_VFS_STAT ... ? */
1604 status = vfs_stat_fsp(fsp);
1605 if (!NT_STATUS_IS_OK(status)) {
1610 out_data_tmp = talloc_array(ctx, char, *out_len);
1611 if (out_data_tmp == NULL) {
1612 DEBUG(10, ("unable to allocate memory for response\n"));
1613 return NT_STATUS_NO_MEMORY;
1616 if (offset > fsp->fsp_name->st.st_ex_size ||
1617 fsp->fsp_name->st.st_ex_size == 0 ||
1619 memset(out_data_tmp, 0, *out_len);
1621 uint64_t end = offset + length;
1622 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1623 SBVAL(out_data_tmp, 0, 0);
1624 SBVAL(out_data_tmp, 8, end);
1627 *out_data = out_data_tmp;
1629 return NT_STATUS_OK;
1632 case FSCTL_IS_VOLUME_DIRTY:
1634 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1635 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1637 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1638 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1640 return NT_STATUS_INVALID_PARAMETER;
1645 * Only print once ... unfortunately there could be lots of
1646 * different FSCTLs that are called.
1648 if (!vfswrap_logged_ioctl_message) {
1649 vfswrap_logged_ioctl_message = true;
1650 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1651 __func__, function));
1655 return NT_STATUS_NOT_SUPPORTED;
1658 static bool vfswrap_is_offline(struct connection_struct *conn,
1659 const struct smb_filename *fname);
1661 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1662 struct smb_filename *smb_fname,
1667 offline = vfswrap_is_offline(handle->conn, smb_fname);
1669 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1672 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1675 struct vfswrap_get_dos_attributes_state {
1676 struct vfs_aio_state aio_state;
1677 connection_struct *conn;
1678 TALLOC_CTX *mem_ctx;
1679 struct tevent_context *ev;
1680 files_struct *dir_fsp;
1681 struct smb_filename *smb_fname;
1686 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq);
1688 static struct tevent_req *vfswrap_get_dos_attributes_send(
1689 TALLOC_CTX *mem_ctx,
1690 struct tevent_context *ev,
1691 struct vfs_handle_struct *handle,
1692 files_struct *dir_fsp,
1693 struct smb_filename *smb_fname)
1695 struct tevent_req *req = NULL;
1696 struct tevent_req *subreq = NULL;
1697 struct vfswrap_get_dos_attributes_state *state = NULL;
1699 req = tevent_req_create(mem_ctx, &state,
1700 struct vfswrap_get_dos_attributes_state);
1705 *state = (struct vfswrap_get_dos_attributes_state) {
1706 .conn = dir_fsp->conn,
1710 .smb_fname = smb_fname,
1713 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1717 SAMBA_XATTR_DOS_ATTRIB,
1719 if (tevent_req_nomem(subreq, req)) {
1720 return tevent_req_post(req, ev);
1722 tevent_req_set_callback(subreq,
1723 vfswrap_get_dos_attributes_getxattr_done,
1729 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq)
1731 struct tevent_req *req =
1732 tevent_req_callback_data(subreq,
1734 struct vfswrap_get_dos_attributes_state *state =
1735 tevent_req_data(req,
1736 struct vfswrap_get_dos_attributes_state);
1738 DATA_BLOB blob = {0};
1740 char *tofree = NULL;
1741 char pathbuf[PATH_MAX+1];
1743 struct smb_filename smb_fname;
1747 xattr_size = SMB_VFS_GETXATTRAT_RECV(subreq,
1751 TALLOC_FREE(subreq);
1752 if (xattr_size == -1) {
1753 status = map_nt_error_from_unix(state->aio_state.error);
1755 if (state->as_root) {
1756 tevent_req_nterror(req, status);
1759 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1760 tevent_req_nterror(req, status);
1764 state->as_root = true;
1767 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1771 SAMBA_XATTR_DOS_ATTRIB,
1774 if (tevent_req_nomem(subreq, req)) {
1777 tevent_req_set_callback(subreq,
1778 vfswrap_get_dos_attributes_getxattr_done,
1783 blob.length = xattr_size;
1785 status = parse_dos_attribute_blob(state->smb_fname,
1788 if (!NT_STATUS_IS_OK(status)) {
1789 tevent_req_nterror(req, status);
1793 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
1794 state->smb_fname->base_name,
1799 if (pathlen == -1) {
1800 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1804 smb_fname = (struct smb_filename) {
1806 .st = state->smb_fname->st,
1807 .flags = state->smb_fname->flags,
1808 .twrp = state->smb_fname->twrp,
1811 offline = vfswrap_is_offline(state->conn, &smb_fname);
1813 state->dosmode |= FILE_ATTRIBUTE_OFFLINE;
1815 TALLOC_FREE(tofree);
1817 tevent_req_done(req);
1821 static NTSTATUS vfswrap_get_dos_attributes_recv(struct tevent_req *req,
1822 struct vfs_aio_state *aio_state,
1825 struct vfswrap_get_dos_attributes_state *state =
1826 tevent_req_data(req,
1827 struct vfswrap_get_dos_attributes_state);
1830 if (tevent_req_is_nterror(req, &status)) {
1831 tevent_req_received(req);
1835 *aio_state = state->aio_state;
1836 *dosmode = state->dosmode;
1837 tevent_req_received(req);
1838 return NT_STATUS_OK;
1841 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1842 struct files_struct *fsp,
1847 offline = vfswrap_is_offline(handle->conn, fsp->fsp_name);
1849 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1852 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1855 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1856 const struct smb_filename *smb_fname,
1859 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1862 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1863 struct files_struct *fsp,
1866 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1869 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1871 struct vfswrap_offload_read_state {
1875 static struct tevent_req *vfswrap_offload_read_send(
1876 TALLOC_CTX *mem_ctx,
1877 struct tevent_context *ev,
1878 struct vfs_handle_struct *handle,
1879 struct files_struct *fsp,
1885 struct tevent_req *req = NULL;
1886 struct vfswrap_offload_read_state *state = NULL;
1889 req = tevent_req_create(mem_ctx, &state,
1890 struct vfswrap_offload_read_state);
1895 status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1896 &vfswrap_offload_ctx);
1897 if (tevent_req_nterror(req, status)) {
1898 return tevent_req_post(req, ev);
1901 if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1902 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1903 return tevent_req_post(req, ev);
1906 status = vfs_offload_token_create_blob(state, fsp, fsctl,
1908 if (tevent_req_nterror(req, status)) {
1909 return tevent_req_post(req, ev);
1912 status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1914 if (tevent_req_nterror(req, status)) {
1915 return tevent_req_post(req, ev);
1918 tevent_req_done(req);
1919 return tevent_req_post(req, ev);
1922 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
1923 struct vfs_handle_struct *handle,
1924 TALLOC_CTX *mem_ctx,
1927 struct vfswrap_offload_read_state *state = tevent_req_data(
1928 req, struct vfswrap_offload_read_state);
1931 if (tevent_req_is_nterror(req, &status)) {
1932 tevent_req_received(req);
1936 token->length = state->token.length;
1937 token->data = talloc_move(mem_ctx, &state->token.data);
1939 tevent_req_received(req);
1940 return NT_STATUS_OK;
1943 struct vfswrap_offload_write_state {
1945 bool read_lck_locked;
1946 bool write_lck_locked;
1948 struct tevent_context *src_ev;
1949 struct files_struct *src_fsp;
1951 struct tevent_context *dst_ev;
1952 struct files_struct *dst_fsp;
1956 size_t next_io_size;
1959 static void vfswrap_offload_write_cleanup(struct tevent_req *req,
1960 enum tevent_req_state req_state)
1962 struct vfswrap_offload_write_state *state = tevent_req_data(
1963 req, struct vfswrap_offload_write_state);
1966 if (state->dst_fsp == NULL) {
1970 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
1972 state->dst_fsp = NULL;
1975 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
1977 static struct tevent_req *vfswrap_offload_write_send(
1978 struct vfs_handle_struct *handle,
1979 TALLOC_CTX *mem_ctx,
1980 struct tevent_context *ev,
1983 off_t transfer_offset,
1984 struct files_struct *dest_fsp,
1988 struct tevent_req *req;
1989 struct vfswrap_offload_write_state *state = NULL;
1990 /* off_t is signed! */
1991 off_t max_offset = INT64_MAX - to_copy;
1992 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
1993 files_struct *src_fsp = NULL;
1997 req = tevent_req_create(mem_ctx, &state,
1998 struct vfswrap_offload_write_state);
2003 *state = (struct vfswrap_offload_write_state) {
2005 .src_off = transfer_offset,
2007 .dst_fsp = dest_fsp,
2008 .dst_off = dest_off,
2010 .remaining = to_copy,
2013 tevent_req_set_cleanup_fn(req, vfswrap_offload_write_cleanup);
2016 case FSCTL_SRV_COPYCHUNK:
2017 case FSCTL_SRV_COPYCHUNK_WRITE:
2020 case FSCTL_OFFLOAD_WRITE:
2021 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
2022 return tevent_req_post(req, ev);
2024 case FSCTL_DUP_EXTENTS_TO_FILE:
2025 DBG_DEBUG("COW clones not supported by vfs_default\n");
2026 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2027 return tevent_req_post(req, ev);
2030 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2031 return tevent_req_post(req, ev);
2035 * From here on we assume a copy-chunk fsctl
2039 tevent_req_done(req);
2040 return tevent_req_post(req, ev);
2043 if (state->src_off > max_offset) {
2045 * Protect integer checks below.
2047 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2048 return tevent_req_post(req, ev);
2050 if (state->src_off < 0) {
2052 * Protect integer checks below.
2054 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2055 return tevent_req_post(req, ev);
2057 if (state->dst_off > max_offset) {
2059 * Protect integer checks below.
2061 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2062 return tevent_req_post(req, ev);
2064 if (state->dst_off < 0) {
2066 * Protect integer checks below.
2068 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2069 return tevent_req_post(req, ev);
2072 status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
2074 if (tevent_req_nterror(req, status)) {
2075 return tevent_req_post(req, ev);
2078 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
2080 status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
2081 if (!NT_STATUS_IS_OK(status)) {
2082 tevent_req_nterror(req, status);
2083 return tevent_req_post(req, ev);
2086 ok = change_to_user_and_service_by_fsp(src_fsp);
2088 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2089 return tevent_req_post(req, ev);
2092 state->src_ev = src_fsp->conn->sconn->ev_ctx;
2093 state->src_fsp = src_fsp;
2095 status = vfs_stat_fsp(src_fsp);
2096 if (tevent_req_nterror(req, status)) {
2097 return tevent_req_post(req, ev);
2100 if (src_fsp->fsp_name->st.st_ex_size < state->src_off + to_copy) {
2102 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
2103 * If the SourceOffset or SourceOffset + Length extends beyond
2104 * the end of file, the server SHOULD<240> treat this as a
2105 * STATUS_END_OF_FILE error.
2107 * <240> Section 3.3.5.15.6: Windows servers will return
2108 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
2110 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
2111 return tevent_req_post(req, ev);
2114 state->buf = talloc_array(state, uint8_t, num);
2115 if (tevent_req_nomem(state->buf, req)) {
2116 return tevent_req_post(req, ev);
2119 status = vfswrap_offload_write_loop(req);
2120 if (!NT_STATUS_IS_OK(status)) {
2121 tevent_req_nterror(req, status);
2122 return tevent_req_post(req, ev);
2128 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
2130 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
2132 struct vfswrap_offload_write_state *state = tevent_req_data(
2133 req, struct vfswrap_offload_write_state);
2134 struct tevent_req *subreq = NULL;
2135 struct lock_struct read_lck;
2139 * This is called under the context of state->src_fsp.
2142 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
2144 init_strict_lock_struct(state->src_fsp,
2145 state->src_fsp->op->global->open_persistent_id,
2147 state->next_io_size,
2151 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
2155 return NT_STATUS_FILE_LOCK_CONFLICT;
2158 subreq = SMB_VFS_PREAD_SEND(state,
2162 state->next_io_size,
2164 if (subreq == NULL) {
2165 return NT_STATUS_NO_MEMORY;
2167 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
2169 return NT_STATUS_OK;
2172 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
2174 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
2176 struct tevent_req *req = tevent_req_callback_data(
2177 subreq, struct tevent_req);
2178 struct vfswrap_offload_write_state *state = tevent_req_data(
2179 req, struct vfswrap_offload_write_state);
2180 struct vfs_aio_state aio_state;
2181 struct lock_struct write_lck;
2185 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
2186 TALLOC_FREE(subreq);
2188 DBG_ERR("read failed: %s\n", strerror(aio_state.error));
2189 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2192 if (nread != state->next_io_size) {
2193 DBG_ERR("Short read, only %zd of %zu\n",
2194 nread, state->next_io_size);
2195 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2199 state->src_off += nread;
2201 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2203 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2207 init_strict_lock_struct(state->dst_fsp,
2208 state->dst_fsp->op->global->open_persistent_id,
2210 state->next_io_size,
2214 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
2218 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
2222 subreq = SMB_VFS_PWRITE_SEND(state,
2226 state->next_io_size,
2228 if (subreq == NULL) {
2229 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2232 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
2235 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
2237 struct tevent_req *req = tevent_req_callback_data(
2238 subreq, struct tevent_req);
2239 struct vfswrap_offload_write_state *state = tevent_req_data(
2240 req, struct vfswrap_offload_write_state);
2241 struct vfs_aio_state aio_state;
2246 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
2247 TALLOC_FREE(subreq);
2248 if (nwritten == -1) {
2249 DBG_ERR("write failed: %s\n", strerror(aio_state.error));
2250 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2253 if (nwritten != state->next_io_size) {
2254 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
2255 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2259 state->dst_off += nwritten;
2261 if (state->remaining < nwritten) {
2262 /* Paranoia check */
2263 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2266 state->remaining -= nwritten;
2267 if (state->remaining == 0) {
2268 tevent_req_done(req);
2272 ok = change_to_user_and_service_by_fsp(state->src_fsp);
2274 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2278 status = vfswrap_offload_write_loop(req);
2279 if (!NT_STATUS_IS_OK(status)) {
2280 tevent_req_nterror(req, status);
2287 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
2288 struct tevent_req *req,
2291 struct vfswrap_offload_write_state *state = tevent_req_data(
2292 req, struct vfswrap_offload_write_state);
2295 if (tevent_req_is_nterror(req, &status)) {
2296 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
2298 tevent_req_received(req);
2302 *copied = state->to_copy;
2303 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
2304 tevent_req_received(req);
2306 return NT_STATUS_OK;
2309 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
2310 TALLOC_CTX *mem_ctx,
2311 struct files_struct *fsp,
2312 struct smb_filename *smb_fname,
2313 uint16_t *_compression_fmt)
2315 return NT_STATUS_INVALID_DEVICE_REQUEST;
2318 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
2319 TALLOC_CTX *mem_ctx,
2320 struct files_struct *fsp,
2321 uint16_t compression_fmt)
2323 return NT_STATUS_INVALID_DEVICE_REQUEST;
2326 /********************************************************************
2327 Given a stat buffer return the allocated size on disk, taking into
2328 account sparse files.
2329 ********************************************************************/
2330 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
2331 struct files_struct *fsp,
2332 const SMB_STRUCT_STAT *sbuf)
2336 START_PROFILE(syscall_get_alloc_size);
2338 if(S_ISDIR(sbuf->st_ex_mode)) {
2343 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2344 /* The type of st_blocksize is blkcnt_t which *MUST* be
2345 signed (according to POSIX) and can be less than 64-bits.
2346 Ensure when we're converting to 64 bits wide we don't
2348 #if defined(SIZEOF_BLKCNT_T_8)
2349 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2350 #elif defined(SIZEOF_BLKCNT_T_4)
2352 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2353 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2356 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2360 * Some file systems do not allocate a block for very
2361 * small files. But for non-empty file should report a
2365 uint64_t filesize = get_file_size_stat(sbuf);
2367 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2371 result = get_file_size_stat(sbuf);
2374 if (fsp && fsp->initial_allocation_size)
2375 result = MAX(result,fsp->initial_allocation_size);
2377 result = smb_roundup(handle->conn, result);
2380 END_PROFILE(syscall_get_alloc_size);
2384 static int vfswrap_unlinkat(vfs_handle_struct *handle,
2385 struct files_struct *dirfsp,
2386 const struct smb_filename *smb_fname,
2391 START_PROFILE(syscall_unlinkat);
2393 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2395 if (is_named_stream(smb_fname)) {
2399 result = unlinkat(dirfsp->fh->fd,
2400 smb_fname->base_name,
2404 END_PROFILE(syscall_unlinkat);
2408 static int vfswrap_chmod(vfs_handle_struct *handle,
2409 const struct smb_filename *smb_fname,
2414 START_PROFILE(syscall_chmod);
2415 result = chmod(smb_fname->base_name, mode);
2416 END_PROFILE(syscall_chmod);
2420 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2424 START_PROFILE(syscall_fchmod);
2425 #if defined(HAVE_FCHMOD)
2426 result = fchmod(fsp->fh->fd, mode);
2432 END_PROFILE(syscall_fchmod);
2436 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2441 START_PROFILE(syscall_fchown);
2442 result = fchown(fsp->fh->fd, uid, gid);
2443 END_PROFILE(syscall_fchown);
2451 static int vfswrap_lchown(vfs_handle_struct *handle,
2452 const struct smb_filename *smb_fname,
2458 START_PROFILE(syscall_lchown);
2459 result = lchown(smb_fname->base_name, uid, gid);
2460 END_PROFILE(syscall_lchown);
2464 static int vfswrap_chdir(vfs_handle_struct *handle,
2465 const struct smb_filename *smb_fname)
2469 START_PROFILE(syscall_chdir);
2470 result = chdir(smb_fname->base_name);
2471 END_PROFILE(syscall_chdir);
2475 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2479 struct smb_filename *smb_fname = NULL;
2481 START_PROFILE(syscall_getwd);
2482 result = sys_getwd();
2483 END_PROFILE(syscall_getwd);
2485 if (result == NULL) {
2488 smb_fname = synthetic_smb_fname(ctx,
2495 * sys_getwd() *always* returns malloced memory.
2496 * We must free here to avoid leaks:
2497 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2503 /*********************************************************************
2504 nsec timestamp resolution call. Convert down to whatever the underlying
2505 system will support.
2506 **********************************************************************/
2508 static int vfswrap_ntimes(vfs_handle_struct *handle,
2509 const struct smb_filename *smb_fname,
2510 struct smb_file_time *ft)
2514 START_PROFILE(syscall_ntimes);
2516 if (is_named_stream(smb_fname)) {
2522 if (is_omit_timespec(&ft->atime)) {
2523 ft->atime= smb_fname->st.st_ex_atime;
2526 if (is_omit_timespec(&ft->mtime)) {
2527 ft->mtime = smb_fname->st.st_ex_mtime;
2530 if (!is_omit_timespec(&ft->create_time)) {
2531 set_create_timespec_ea(handle->conn,
2536 if ((timespec_compare(&ft->atime,
2537 &smb_fname->st.st_ex_atime) == 0) &&
2538 (timespec_compare(&ft->mtime,
2539 &smb_fname->st.st_ex_mtime) == 0)) {
2544 #if defined(HAVE_UTIMENSAT)
2546 struct timespec ts[2];
2549 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2551 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2553 if (!((result == -1) && (errno == ENOSYS))) {
2557 #if defined(HAVE_UTIMES)
2559 struct timeval tv[2];
2560 tv[0] = convert_timespec_to_timeval(ft->atime);
2561 tv[1] = convert_timespec_to_timeval(ft->mtime);
2562 result = utimes(smb_fname->base_name, tv);
2564 result = utimes(smb_fname->base_name, NULL);
2566 if (!((result == -1) && (errno == ENOSYS))) {
2570 #if defined(HAVE_UTIME)
2572 struct utimbuf times;
2573 times.actime = convert_timespec_to_time_t(ft->atime);
2574 times.modtime = convert_timespec_to_time_t(ft->mtime);
2575 result = utime(smb_fname->base_name, ×);
2577 result = utime(smb_fname->base_name, NULL);
2579 if (!((result == -1) && (errno == ENOSYS))) {
2587 END_PROFILE(syscall_ntimes);
2591 /*********************************************************************
2592 A version of ftruncate that will write the space on disk if strict
2594 **********************************************************************/
2596 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2598 off_t space_to_write;
2599 uint64_t space_avail;
2600 uint64_t bsize,dfree,dsize;
2603 SMB_STRUCT_STAT *pst;
2606 ok = vfs_valid_pwrite_range(len, 0);
2612 status = vfs_stat_fsp(fsp);
2613 if (!NT_STATUS_IS_OK(status)) {
2616 pst = &fsp->fsp_name->st;
2619 if (S_ISFIFO(pst->st_ex_mode))
2623 if (pst->st_ex_size == len)
2626 /* Shrink - just ftruncate. */
2627 if (pst->st_ex_size > len)
2628 return ftruncate(fsp->fh->fd, len);
2630 space_to_write = len - pst->st_ex_size;
2632 /* for allocation try fallocate first. This can fail on some
2633 platforms e.g. when the filesystem doesn't support it and no
2634 emulation is being done by the libc (like on AIX with JFS1). In that
2635 case we do our own emulation. fallocate implementations can
2636 return ENOTSUP or EINVAL in cases like that. */
2637 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2638 if (ret == -1 && errno == ENOSPC) {
2644 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2645 "error %d. Falling back to slow manual allocation\n", errno));
2647 /* available disk space is enough or not? */
2649 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2650 /* space_avail is 1k blocks */
2651 if (space_avail == (uint64_t)-1 ||
2652 ((uint64_t)space_to_write/1024 > space_avail) ) {
2657 /* Write out the real space on disk. */
2658 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2666 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2669 SMB_STRUCT_STAT *pst;
2673 START_PROFILE(syscall_ftruncate);
2675 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->fsp_flags.is_sparse) {
2676 result = strict_allocate_ftruncate(handle, fsp, len);
2677 END_PROFILE(syscall_ftruncate);
2681 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2682 ftruncate if the system supports it. Then I discovered that
2683 you can have some filesystems that support ftruncate
2684 expansion and some that don't! On Linux fat can't do
2685 ftruncate extend but ext2 can. */
2687 result = ftruncate(fsp->fh->fd, len);
2689 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2690 extend a file with ftruncate. Provide alternate implementation
2693 /* Do an fstat to see if the file is longer than the requested
2694 size in which case the ftruncate above should have
2695 succeeded or shorter, in which case seek to len - 1 and
2696 write 1 byte of zero */
2697 status = vfs_stat_fsp(fsp);
2698 if (!NT_STATUS_IS_OK(status)) {
2702 /* We need to update the files_struct after successful ftruncate */
2707 pst = &fsp->fsp_name->st;
2710 if (S_ISFIFO(pst->st_ex_mode)) {
2716 if (pst->st_ex_size == len) {
2721 if (pst->st_ex_size > len) {
2722 /* the ftruncate should have worked */
2726 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2734 END_PROFILE(syscall_ftruncate);
2738 static int vfswrap_fallocate(vfs_handle_struct *handle,
2746 START_PROFILE(syscall_fallocate);
2748 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2750 * posix_fallocate returns 0 on success, errno on error
2751 * and doesn't set errno. Make it behave like fallocate()
2752 * which returns -1, and sets errno on failure.
2759 /* sys_fallocate handles filtering of unsupported mode flags */
2760 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2762 END_PROFILE(syscall_fallocate);
2766 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2770 START_PROFILE(syscall_fcntl_lock);
2772 if (fsp->fsp_flags.use_ofd_locks) {
2773 op = map_process_lock_to_ofd_lock(op);
2776 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2777 END_PROFILE(syscall_fcntl_lock);
2781 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2782 uint32_t share_access, uint32_t access_mask)
2784 START_PROFILE(syscall_kernel_flock);
2785 kernel_flock(fsp->fh->fd, share_access, access_mask);
2786 END_PROFILE(syscall_kernel_flock);
2790 static int vfswrap_fcntl(vfs_handle_struct *handle, files_struct *fsp, int cmd,
2794 va_list dup_cmd_arg;
2798 START_PROFILE(syscall_fcntl);
2800 va_copy(dup_cmd_arg, cmd_arg);
2806 #if defined(HAVE_OFD_LOCKS)
2811 #if defined(HAVE_F_OWNER_EX)
2815 #if defined(HAVE_RW_HINTS)
2818 case F_GET_FILE_RW_HINT:
2819 case F_SET_FILE_RW_HINT:
2821 argp = va_arg(dup_cmd_arg, void *);
2822 result = sys_fcntl_ptr(fsp->fh->fd, cmd, argp);
2825 val = va_arg(dup_cmd_arg, int);
2826 result = sys_fcntl_int(fsp->fh->fd, cmd, val);
2829 va_end(dup_cmd_arg);
2831 END_PROFILE(syscall_fcntl);
2835 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2840 START_PROFILE(syscall_fcntl_getlock);
2842 if (fsp->fsp_flags.use_ofd_locks) {
2843 op = map_process_lock_to_ofd_lock(op);
2846 result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2847 END_PROFILE(syscall_fcntl_getlock);
2851 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2856 START_PROFILE(syscall_linux_setlease);
2858 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2859 result = linux_setlease(fsp->fh->fd, leasetype);
2863 END_PROFILE(syscall_linux_setlease);
2867 static int vfswrap_symlinkat(vfs_handle_struct *handle,
2868 const struct smb_filename *link_target,
2869 struct files_struct *dirfsp,
2870 const struct smb_filename *new_smb_fname)
2874 START_PROFILE(syscall_symlinkat);
2876 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2878 result = symlinkat(link_target->base_name,
2880 new_smb_fname->base_name);
2881 END_PROFILE(syscall_symlinkat);
2885 static int vfswrap_readlinkat(vfs_handle_struct *handle,
2886 files_struct *dirfsp,
2887 const struct smb_filename *smb_fname,
2893 START_PROFILE(syscall_readlinkat);
2895 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2897 result = readlinkat(dirfsp->fh->fd,
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 SMB_ASSERT(srcfsp == srcfsp->conn->cwd_fsp);
2918 SMB_ASSERT(dstfsp == dstfsp->conn->cwd_fsp);
2920 result = linkat(srcfsp->fh->fd,
2921 old_smb_fname->base_name,
2923 new_smb_fname->base_name,
2926 END_PROFILE(syscall_linkat);
2930 static int vfswrap_mknodat(vfs_handle_struct *handle,
2931 files_struct *dirfsp,
2932 const struct smb_filename *smb_fname,
2938 START_PROFILE(syscall_mknodat);
2940 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2942 result = sys_mknodat(dirfsp->fh->fd,
2943 smb_fname->base_name,
2947 END_PROFILE(syscall_mknodat);
2951 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2953 const struct smb_filename *smb_fname)
2956 struct smb_filename *result_fname = NULL;
2958 START_PROFILE(syscall_realpath);
2959 result = sys_realpath(smb_fname->base_name);
2960 END_PROFILE(syscall_realpath);
2962 result_fname = synthetic_smb_fname(ctx,
2970 return result_fname;
2973 static int vfswrap_chflags(vfs_handle_struct *handle,
2974 const struct smb_filename *smb_fname,
2978 return chflags(smb_fname->base_name, flags);
2985 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2986 const SMB_STRUCT_STAT *sbuf)
2990 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2994 key.devid = sbuf->st_ex_dev;
2995 key.inode = sbuf->st_ex_ino;
2996 /* key.extid is unused by default. */
3001 static uint64_t vfswrap_fs_file_id(struct vfs_handle_struct *handle,
3002 const SMB_STRUCT_STAT *psbuf)
3006 if (!(psbuf->st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)) {
3007 return psbuf->st_ex_file_id;
3010 if (handle->conn->base_share_dev == psbuf->st_ex_dev) {
3011 return (uint64_t)psbuf->st_ex_ino;
3015 file_id = ((psbuf->st_ex_ino) & UINT32_MAX);
3018 file_id |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32;
3023 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
3024 struct files_struct *fsp,
3025 const struct smb_filename *smb_fname,
3026 TALLOC_CTX *mem_ctx,
3027 unsigned int *pnum_streams,
3028 struct stream_struct **pstreams)
3030 SMB_STRUCT_STAT sbuf;
3031 struct stream_struct *tmp_streams = NULL;
3034 if ((fsp != NULL) && (fsp->fsp_flags.is_directory)) {
3036 * No default streams on directories
3041 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
3042 ret = SMB_VFS_FSTAT(fsp, &sbuf);
3045 struct smb_filename *smb_fname_cp = NULL;
3047 smb_fname_cp = cp_smb_filename_nostream(talloc_tos(), smb_fname);
3048 if (smb_fname_cp == NULL) {
3049 return NT_STATUS_NO_MEMORY;
3052 if (smb_fname_cp->flags & SMB_FILENAME_POSIX_PATH) {
3053 ret = SMB_VFS_LSTAT(handle->conn, smb_fname_cp);
3055 ret = SMB_VFS_STAT(handle->conn, smb_fname_cp);
3057 sbuf = smb_fname_cp->st;
3058 TALLOC_FREE(smb_fname_cp);
3062 return map_nt_error_from_unix(errno);
3065 if (S_ISDIR(sbuf.st_ex_mode)) {
3069 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
3070 (*pnum_streams) + 1);
3071 if (tmp_streams == NULL) {
3072 return NT_STATUS_NO_MEMORY;
3074 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
3075 if (tmp_streams[*pnum_streams].name == NULL) {
3076 return NT_STATUS_NO_MEMORY;
3078 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
3079 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
3082 *pstreams = tmp_streams;
3084 return NT_STATUS_OK;
3087 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
3088 const struct smb_filename *path,
3090 TALLOC_CTX *mem_ctx,
3094 * Don't fall back to get_real_filename so callers can differentiate
3095 * between a full directory scan and an actual case-insensitive stat.
3101 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
3102 const struct smb_filename *smb_fname)
3104 return handle->conn->connectpath;
3107 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
3108 struct byte_range_lock *br_lck,
3109 struct lock_struct *plock)
3111 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3113 /* Note: blr is not used in the default implementation. */
3114 return brl_lock_windows_default(br_lck, plock);
3117 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
3118 struct byte_range_lock *br_lck,
3119 const struct lock_struct *plock)
3121 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3123 return brl_unlock_windows_default(br_lck, plock);
3126 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
3128 struct lock_struct *plock)
3130 SMB_ASSERT(plock->lock_type == READ_LOCK ||
3131 plock->lock_type == WRITE_LOCK);
3133 return strict_lock_check_default(fsp, plock);
3136 /* NT ACL operations. */
3138 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
3140 uint32_t security_info,
3141 TALLOC_CTX *mem_ctx,
3142 struct security_descriptor **ppdesc)
3146 START_PROFILE(fget_nt_acl);
3147 result = posix_fget_nt_acl(fsp, security_info,
3149 END_PROFILE(fget_nt_acl);
3153 static NTSTATUS vfswrap_get_nt_acl_at(vfs_handle_struct *handle,
3154 struct files_struct *dirfsp,
3155 const struct smb_filename *smb_fname,
3156 uint32_t security_info,
3157 TALLOC_CTX *mem_ctx,
3158 struct security_descriptor **ppdesc)
3162 START_PROFILE(get_nt_acl_at);
3164 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
3166 result = posix_get_nt_acl(handle->conn,
3171 END_PROFILE(get_nt_acl_at);
3175 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
3179 START_PROFILE(fset_nt_acl);
3180 result = set_nt_acl(fsp, security_info_sent, psd);
3181 END_PROFILE(fset_nt_acl);
3185 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
3186 struct smb_filename *file,
3187 struct security_acl *sacl,
3188 uint32_t access_requested,
3189 uint32_t access_denied)
3191 return NT_STATUS_OK; /* Nothing to do here ... */
3194 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
3195 const struct smb_filename *smb_fname,
3196 SMB_ACL_TYPE_T type,
3197 TALLOC_CTX *mem_ctx)
3199 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
3202 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
3204 TALLOC_CTX *mem_ctx)
3206 return sys_acl_get_fd(handle, fsp, mem_ctx);
3209 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
3210 const struct smb_filename *smb_fname,
3211 SMB_ACL_TYPE_T acltype,
3214 return sys_acl_set_file(handle, smb_fname, acltype, theacl);
3217 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
3219 return sys_acl_set_fd(handle, fsp, theacl);
3222 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
3223 const struct smb_filename *smb_fname)
3225 return sys_acl_delete_def_file(handle, smb_fname);
3228 /****************************************************************
3229 Extended attribute operations.
3230 *****************************************************************/
3232 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
3233 const struct smb_filename *smb_fname,
3238 return getxattr(smb_fname->base_name, name, value, size);
3241 struct vfswrap_getxattrat_state {
3242 struct tevent_context *ev;
3243 files_struct *dir_fsp;
3244 const struct smb_filename *smb_fname;
3247 * The following variables are talloced off "state" which is protected
3248 * by a destructor and thus are guaranteed to be safe to be used in the
3249 * job function in the worker thread.
3252 const char *xattr_name;
3253 uint8_t *xattr_value;
3254 struct security_unix_token *token;
3257 struct vfs_aio_state vfs_aio_state;
3258 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
3261 static int vfswrap_getxattrat_state_destructor(
3262 struct vfswrap_getxattrat_state *state)
3267 static void vfswrap_getxattrat_do_sync(struct tevent_req *req);
3268 static void vfswrap_getxattrat_do_async(void *private_data);
3269 static void vfswrap_getxattrat_done(struct tevent_req *subreq);
3271 static struct tevent_req *vfswrap_getxattrat_send(
3272 TALLOC_CTX *mem_ctx,
3273 struct tevent_context *ev,
3274 struct vfs_handle_struct *handle,
3275 files_struct *dir_fsp,
3276 const struct smb_filename *smb_fname,
3277 const char *xattr_name,
3280 struct tevent_req *req = NULL;
3281 struct tevent_req *subreq = NULL;
3282 struct vfswrap_getxattrat_state *state = NULL;
3283 size_t max_threads = 0;
3284 bool have_per_thread_cwd = false;
3285 bool have_per_thread_creds = false;
3286 bool do_async = false;
3288 req = tevent_req_create(mem_ctx, &state,
3289 struct vfswrap_getxattrat_state);
3293 *state = (struct vfswrap_getxattrat_state) {
3296 .smb_fname = smb_fname,
3299 max_threads = pthreadpool_tevent_max_threads(dir_fsp->conn->sconn->pool);
3300 if (max_threads >= 1) {
3302 * We need a non sync threadpool!
3304 have_per_thread_cwd = per_thread_cwd_supported();
3306 #ifdef HAVE_LINUX_THREAD_CREDENTIALS
3307 have_per_thread_creds = true;
3309 if (have_per_thread_cwd && have_per_thread_creds) {
3313 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat, profile_p,
3314 state->profile_bytes, 0);
3316 if (dir_fsp->fh->fd == -1) {
3317 DBG_ERR("Need a valid directory fd\n");
3318 tevent_req_error(req, EINVAL);
3319 return tevent_req_post(req, ev);
3322 if (alloc_hint > 0) {
3323 state->xattr_value = talloc_zero_array(state,
3326 if (tevent_req_nomem(state->xattr_value, req)) {
3327 return tevent_req_post(req, ev);
3332 vfswrap_getxattrat_do_sync(req);
3333 return tevent_req_post(req, ev);
3337 * Now allocate all parameters from a memory context that won't go away
3338 * no matter what. These paremeters will get used in threads and we
3339 * can't reliably cancel threads, so all buffers passed to the threads
3340 * must not be freed before all referencing threads terminate.
3343 state->name = talloc_strdup(state, smb_fname->base_name);
3344 if (tevent_req_nomem(state->name, req)) {
3345 return tevent_req_post(req, ev);
3348 state->xattr_name = talloc_strdup(state, xattr_name);
3349 if (tevent_req_nomem(state->xattr_name, req)) {
3350 return tevent_req_post(req, ev);
3354 * This is a hot codepath so at first glance one might think we should
3355 * somehow optimize away the token allocation and do a
3356 * talloc_reference() or similar black magic instead. But due to the
3357 * talloc_stackframe pool per SMB2 request this should be a simple copy
3358 * without a malloc in most cases.
3360 if (geteuid() == sec_initial_uid()) {
3361 state->token = root_unix_token(state);
3363 state->token = copy_unix_token(
3365 dir_fsp->conn->session_info->unix_token);
3367 if (tevent_req_nomem(state->token, req)) {
3368 return tevent_req_post(req, ev);
3371 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3373 subreq = pthreadpool_tevent_job_send(
3376 dir_fsp->conn->sconn->pool,
3377 vfswrap_getxattrat_do_async,
3379 if (tevent_req_nomem(subreq, req)) {
3380 return tevent_req_post(req, ev);
3382 tevent_req_set_callback(subreq, vfswrap_getxattrat_done, req);
3384 talloc_set_destructor(state, vfswrap_getxattrat_state_destructor);
3389 static void vfswrap_getxattrat_do_sync(struct tevent_req *req)
3391 struct vfswrap_getxattrat_state *state = tevent_req_data(
3392 req, struct vfswrap_getxattrat_state);
3394 char *tofree = NULL;
3395 char pathbuf[PATH_MAX+1];
3399 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
3400 state->smb_fname->base_name,
3405 if (pathlen == -1) {
3406 tevent_req_error(req, ENOMEM);
3410 state->xattr_size = getxattr(path,
3413 talloc_array_length(state->xattr_value));
3415 TALLOC_FREE(tofree);
3416 if (state->xattr_size == -1) {
3417 tevent_req_error(req, err);
3421 tevent_req_done(req);
3425 static void vfswrap_getxattrat_do_async(void *private_data)
3427 struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3428 private_data, struct vfswrap_getxattrat_state);
3429 struct timespec start_time;
3430 struct timespec end_time;
3433 PROFILE_TIMESTAMP(&start_time);
3434 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
3437 * Here we simulate a getxattrat()
3438 * call using fchdir();getxattr()
3441 per_thread_cwd_activate();
3443 /* Become the correct credential on this thread. */
3444 ret = set_thread_credentials(state->token->uid,
3446 (size_t)state->token->ngroups,
3447 state->token->groups);
3449 state->xattr_size = -1;
3450 state->vfs_aio_state.error = errno;
3454 ret = fchdir(state->dir_fsp->fh->fd);
3456 state->xattr_size = -1;
3457 state->vfs_aio_state.error = errno;
3461 state->xattr_size = getxattr(state->name,
3464 talloc_array_length(state->xattr_value));
3465 if (state->xattr_size == -1) {
3466 state->vfs_aio_state.error = errno;
3470 PROFILE_TIMESTAMP(&end_time);
3471 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
3472 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3475 static void vfswrap_getxattrat_done(struct tevent_req *subreq)
3477 struct tevent_req *req = tevent_req_callback_data(
3478 subreq, struct tevent_req);
3479 struct vfswrap_getxattrat_state *state = tevent_req_data(
3480 req, struct vfswrap_getxattrat_state);
3485 * Make sure we run as the user again
3487 ok = change_to_user_and_service_by_fsp(state->dir_fsp);
3490 ret = pthreadpool_tevent_job_recv(subreq);
3491 TALLOC_FREE(subreq);
3492 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
3493 talloc_set_destructor(state, NULL);
3495 if (ret != EAGAIN) {
3496 tevent_req_error(req, ret);
3500 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
3501 * means the lower level pthreadpool failed to create a new
3502 * thread. Fallback to sync processing in that case to allow
3503 * some progress for the client.
3505 vfswrap_getxattrat_do_sync(req);
3509 if (state->xattr_size == -1) {
3510 tevent_req_error(req, state->vfs_aio_state.error);
3514 if (state->xattr_value == NULL) {
3516 * The caller only wanted the size.
3518 tevent_req_done(req);
3523 * shrink the buffer to the returned size.
3524 * (can't fail). It means NULL if size is 0.
3526 state->xattr_value = talloc_realloc(state,
3531 tevent_req_done(req);
3534 static ssize_t vfswrap_getxattrat_recv(struct tevent_req *req,
3535 struct vfs_aio_state *aio_state,
3536 TALLOC_CTX *mem_ctx,
3537 uint8_t **xattr_value)
3539 struct vfswrap_getxattrat_state *state = tevent_req_data(
3540 req, struct vfswrap_getxattrat_state);
3543 if (tevent_req_is_unix_error(req, &aio_state->error)) {
3544 tevent_req_received(req);
3548 *aio_state = state->vfs_aio_state;
3549 xattr_size = state->xattr_size;
3550 if (xattr_value != NULL) {
3551 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
3554 tevent_req_received(req);
3558 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle,
3559 struct files_struct *fsp,
3564 return fgetxattr(fsp->fh->fd, name, value, size);
3567 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
3568 const struct smb_filename *smb_fname,
3572 return listxattr(smb_fname->base_name, list, size);
3575 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
3577 return flistxattr(fsp->fh->fd, list, size);
3580 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
3581 const struct smb_filename *smb_fname,
3584 return removexattr(smb_fname->base_name, name);
3587 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
3589 return fremovexattr(fsp->fh->fd, name);
3592 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
3593 const struct smb_filename *smb_fname,
3599 return setxattr(smb_fname->base_name, name, value, size, flags);
3602 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
3604 return fsetxattr(fsp->fh->fd, name, value, size, flags);
3607 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
3612 static bool vfswrap_is_offline(struct connection_struct *conn,
3613 const struct smb_filename *fname)
3617 bool offline = false;
3619 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
3623 if (!lp_dmapi_support(SNUM(conn)) || !dmapi_have_session()) {
3624 #if defined(ENOTSUP)
3630 status = get_full_smb_filename(talloc_tos(), fname, &path);
3631 if (!NT_STATUS_IS_OK(status)) {
3632 errno = map_errno_from_nt_status(status);
3636 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
3643 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
3644 struct files_struct *fsp,
3645 TALLOC_CTX *mem_ctx,
3648 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
3651 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
3652 struct files_struct *fsp,
3653 const DATA_BLOB old_cookie,
3654 TALLOC_CTX *mem_ctx,
3655 DATA_BLOB *new_cookie)
3657 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
3661 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
3662 struct smb_request *smb1req,
3663 struct smbXsrv_open *op,
3664 const DATA_BLOB old_cookie,
3665 TALLOC_CTX *mem_ctx,
3666 struct files_struct **fsp,
3667 DATA_BLOB *new_cookie)
3669 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
3670 old_cookie, mem_ctx,
3674 static struct vfs_fn_pointers vfs_default_fns = {
3675 /* Disk operations */
3677 .connect_fn = vfswrap_connect,
3678 .disconnect_fn = vfswrap_disconnect,
3679 .disk_free_fn = vfswrap_disk_free,
3680 .get_quota_fn = vfswrap_get_quota,
3681 .set_quota_fn = vfswrap_set_quota,
3682 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3683 .statvfs_fn = vfswrap_statvfs,
3684 .fs_capabilities_fn = vfswrap_fs_capabilities,
3685 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3686 .create_dfs_pathat_fn = vfswrap_create_dfs_pathat,
3687 .read_dfs_pathat_fn = vfswrap_read_dfs_pathat,
3688 .snap_check_path_fn = vfswrap_snap_check_path,
3689 .snap_create_fn = vfswrap_snap_create,
3690 .snap_delete_fn = vfswrap_snap_delete,
3692 /* Directory operations */
3694 .fdopendir_fn = vfswrap_fdopendir,
3695 .readdir_fn = vfswrap_readdir,
3696 .readdir_attr_fn = vfswrap_readdir_attr,
3697 .seekdir_fn = vfswrap_seekdir,
3698 .telldir_fn = vfswrap_telldir,
3699 .rewind_dir_fn = vfswrap_rewinddir,
3700 .mkdirat_fn = vfswrap_mkdirat,
3701 .closedir_fn = vfswrap_closedir,
3703 /* File operations */
3705 .openat_fn = vfswrap_openat,
3706 .create_file_fn = vfswrap_create_file,
3707 .close_fn = vfswrap_close,
3708 .pread_fn = vfswrap_pread,
3709 .pread_send_fn = vfswrap_pread_send,
3710 .pread_recv_fn = vfswrap_pread_recv,
3711 .pwrite_fn = vfswrap_pwrite,
3712 .pwrite_send_fn = vfswrap_pwrite_send,
3713 .pwrite_recv_fn = vfswrap_pwrite_recv,
3714 .lseek_fn = vfswrap_lseek,
3715 .sendfile_fn = vfswrap_sendfile,
3716 .recvfile_fn = vfswrap_recvfile,
3717 .renameat_fn = vfswrap_renameat,
3718 .fsync_send_fn = vfswrap_fsync_send,
3719 .fsync_recv_fn = vfswrap_fsync_recv,
3720 .stat_fn = vfswrap_stat,
3721 .fstat_fn = vfswrap_fstat,
3722 .lstat_fn = vfswrap_lstat,
3723 .get_alloc_size_fn = vfswrap_get_alloc_size,
3724 .unlinkat_fn = vfswrap_unlinkat,
3725 .chmod_fn = vfswrap_chmod,
3726 .fchmod_fn = vfswrap_fchmod,
3727 .fchown_fn = vfswrap_fchown,
3728 .lchown_fn = vfswrap_lchown,
3729 .chdir_fn = vfswrap_chdir,
3730 .getwd_fn = vfswrap_getwd,
3731 .ntimes_fn = vfswrap_ntimes,
3732 .ftruncate_fn = vfswrap_ftruncate,
3733 .fallocate_fn = vfswrap_fallocate,
3734 .lock_fn = vfswrap_lock,
3735 .kernel_flock_fn = vfswrap_kernel_flock,
3736 .fcntl_fn = vfswrap_fcntl,
3737 .linux_setlease_fn = vfswrap_linux_setlease,
3738 .getlock_fn = vfswrap_getlock,
3739 .symlinkat_fn = vfswrap_symlinkat,
3740 .readlinkat_fn = vfswrap_readlinkat,
3741 .linkat_fn = vfswrap_linkat,
3742 .mknodat_fn = vfswrap_mknodat,
3743 .realpath_fn = vfswrap_realpath,
3744 .chflags_fn = vfswrap_chflags,
3745 .file_id_create_fn = vfswrap_file_id_create,
3746 .fs_file_id_fn = vfswrap_fs_file_id,
3747 .streaminfo_fn = vfswrap_streaminfo,
3748 .get_real_filename_fn = vfswrap_get_real_filename,
3749 .connectpath_fn = vfswrap_connectpath,
3750 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
3751 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3752 .strict_lock_check_fn = vfswrap_strict_lock_check,
3753 .translate_name_fn = vfswrap_translate_name,
3754 .fsctl_fn = vfswrap_fsctl,
3755 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
3756 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
3757 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
3758 .get_dos_attributes_send_fn = vfswrap_get_dos_attributes_send,
3759 .get_dos_attributes_recv_fn = vfswrap_get_dos_attributes_recv,
3760 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
3761 .offload_read_send_fn = vfswrap_offload_read_send,
3762 .offload_read_recv_fn = vfswrap_offload_read_recv,
3763 .offload_write_send_fn = vfswrap_offload_write_send,
3764 .offload_write_recv_fn = vfswrap_offload_write_recv,
3765 .get_compression_fn = vfswrap_get_compression,
3766 .set_compression_fn = vfswrap_set_compression,
3768 /* NT ACL operations. */
3770 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
3771 .get_nt_acl_at_fn = vfswrap_get_nt_acl_at,
3772 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
3773 .audit_file_fn = vfswrap_audit_file,
3775 /* POSIX ACL operations. */
3777 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
3778 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3779 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
3780 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3781 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
3782 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3783 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
3785 /* EA operations. */
3786 .getxattr_fn = vfswrap_getxattr,
3787 .getxattrat_send_fn = vfswrap_getxattrat_send,
3788 .getxattrat_recv_fn = vfswrap_getxattrat_recv,
3789 .fgetxattr_fn = vfswrap_fgetxattr,
3790 .listxattr_fn = vfswrap_listxattr,
3791 .flistxattr_fn = vfswrap_flistxattr,
3792 .removexattr_fn = vfswrap_removexattr,
3793 .fremovexattr_fn = vfswrap_fremovexattr,
3794 .setxattr_fn = vfswrap_setxattr,
3795 .fsetxattr_fn = vfswrap_fsetxattr,
3797 /* aio operations */
3798 .aio_force_fn = vfswrap_aio_force,
3800 /* durable handle operations */
3801 .durable_cookie_fn = vfswrap_durable_cookie,
3802 .durable_disconnect_fn = vfswrap_durable_disconnect,
3803 .durable_reconnect_fn = vfswrap_durable_reconnect,
3807 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3810 * Here we need to implement every call!
3812 * As this is the end of the vfs module chain.
3814 smb_vfs_assert_all_fns(&vfs_default_fns, DEFAULT_VFS_MODULE_NAME);
3815 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3816 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);