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 files_struct **dirfsp,
714 struct smb_filename *smb_fname,
715 uint32_t access_mask,
716 uint32_t share_access,
717 uint32_t create_disposition,
718 uint32_t create_options,
719 uint32_t file_attributes,
720 uint32_t oplock_request,
721 const struct smb2_lease *lease,
722 uint64_t allocation_size,
723 uint32_t private_flags,
724 struct security_descriptor *sd,
725 struct ea_list *ea_list,
726 files_struct **result,
728 const struct smb2_create_blobs *in_context_blobs,
729 struct smb2_create_blobs *out_context_blobs)
731 return create_file_default(handle->conn, req, dirfsp, smb_fname,
732 access_mask, share_access,
733 create_disposition, create_options,
734 file_attributes, oplock_request, lease,
735 allocation_size, private_flags,
737 pinfo, in_context_blobs, out_context_blobs);
740 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
744 START_PROFILE(syscall_close);
745 result = fd_close_posix(fsp);
746 END_PROFILE(syscall_close);
750 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
751 size_t n, off_t offset)
755 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
756 START_PROFILE_BYTES(syscall_pread, n);
757 result = sys_pread_full(fsp->fh->fd, data, n, offset);
758 END_PROFILE_BYTES(syscall_pread);
760 if (result == -1 && errno == ESPIPE) {
761 /* Maintain the fiction that pipes can be seeked (sought?) on. */
762 result = sys_read(fsp->fh->fd, data, n);
766 #else /* HAVE_PREAD */
769 #endif /* HAVE_PREAD */
774 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
775 size_t n, off_t offset)
779 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
780 START_PROFILE_BYTES(syscall_pwrite, n);
781 result = sys_pwrite_full(fsp->fh->fd, data, n, offset);
782 END_PROFILE_BYTES(syscall_pwrite);
784 if (result == -1 && errno == ESPIPE) {
785 /* Maintain the fiction that pipes can be sought on. */
786 result = sys_write(fsp->fh->fd, data, n);
789 #else /* HAVE_PWRITE */
792 #endif /* HAVE_PWRITE */
797 struct vfswrap_pread_state {
804 struct vfs_aio_state vfs_aio_state;
805 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
808 static void vfs_pread_do(void *private_data);
809 static void vfs_pread_done(struct tevent_req *subreq);
810 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state);
812 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
814 struct tevent_context *ev,
815 struct files_struct *fsp,
817 size_t n, off_t offset)
819 struct tevent_req *req, *subreq;
820 struct vfswrap_pread_state *state;
822 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
828 state->fd = fsp->fh->fd;
831 state->offset = offset;
833 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
834 state->profile_bytes, n);
835 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
837 subreq = pthreadpool_tevent_job_send(
838 state, ev, handle->conn->sconn->pool,
839 vfs_pread_do, state);
840 if (tevent_req_nomem(subreq, req)) {
841 return tevent_req_post(req, ev);
843 tevent_req_set_callback(subreq, vfs_pread_done, req);
845 talloc_set_destructor(state, vfs_pread_state_destructor);
850 static void vfs_pread_do(void *private_data)
852 struct vfswrap_pread_state *state = talloc_get_type_abort(
853 private_data, struct vfswrap_pread_state);
854 struct timespec start_time;
855 struct timespec end_time;
857 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
859 PROFILE_TIMESTAMP(&start_time);
861 state->ret = sys_pread_full(state->fd,
866 if (state->ret == -1) {
867 state->vfs_aio_state.error = errno;
870 PROFILE_TIMESTAMP(&end_time);
872 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
874 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
877 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state)
882 static void vfs_pread_done(struct tevent_req *subreq)
884 struct tevent_req *req = tevent_req_callback_data(
885 subreq, struct tevent_req);
886 struct vfswrap_pread_state *state = tevent_req_data(
887 req, struct vfswrap_pread_state);
890 ret = pthreadpool_tevent_job_recv(subreq);
892 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
893 talloc_set_destructor(state, NULL);
896 tevent_req_error(req, ret);
900 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
901 * means the lower level pthreadpool failed to create a new
902 * thread. Fallback to sync processing in that case to allow
903 * some progress for the client.
908 tevent_req_done(req);
911 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
912 struct vfs_aio_state *vfs_aio_state)
914 struct vfswrap_pread_state *state = tevent_req_data(
915 req, struct vfswrap_pread_state);
917 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
921 *vfs_aio_state = state->vfs_aio_state;
925 struct vfswrap_pwrite_state {
932 struct vfs_aio_state vfs_aio_state;
933 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
936 static void vfs_pwrite_do(void *private_data);
937 static void vfs_pwrite_done(struct tevent_req *subreq);
938 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state);
940 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
942 struct tevent_context *ev,
943 struct files_struct *fsp,
945 size_t n, off_t offset)
947 struct tevent_req *req, *subreq;
948 struct vfswrap_pwrite_state *state;
950 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
956 state->fd = fsp->fh->fd;
959 state->offset = offset;
961 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
962 state->profile_bytes, n);
963 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
965 subreq = pthreadpool_tevent_job_send(
966 state, ev, handle->conn->sconn->pool,
967 vfs_pwrite_do, state);
968 if (tevent_req_nomem(subreq, req)) {
969 return tevent_req_post(req, ev);
971 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
973 talloc_set_destructor(state, vfs_pwrite_state_destructor);
978 static void vfs_pwrite_do(void *private_data)
980 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
981 private_data, struct vfswrap_pwrite_state);
982 struct timespec start_time;
983 struct timespec end_time;
985 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
987 PROFILE_TIMESTAMP(&start_time);
989 state->ret = sys_pwrite_full(state->fd,
994 if (state->ret == -1) {
995 state->vfs_aio_state.error = errno;
998 PROFILE_TIMESTAMP(&end_time);
1000 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1002 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1005 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state)
1010 static void vfs_pwrite_done(struct tevent_req *subreq)
1012 struct tevent_req *req = tevent_req_callback_data(
1013 subreq, struct tevent_req);
1014 struct vfswrap_pwrite_state *state = tevent_req_data(
1015 req, struct vfswrap_pwrite_state);
1018 ret = pthreadpool_tevent_job_recv(subreq);
1019 TALLOC_FREE(subreq);
1020 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1021 talloc_set_destructor(state, NULL);
1023 if (ret != EAGAIN) {
1024 tevent_req_error(req, ret);
1028 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1029 * means the lower level pthreadpool failed to create a new
1030 * thread. Fallback to sync processing in that case to allow
1031 * some progress for the client.
1033 vfs_pwrite_do(state);
1036 tevent_req_done(req);
1039 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
1040 struct vfs_aio_state *vfs_aio_state)
1042 struct vfswrap_pwrite_state *state = tevent_req_data(
1043 req, struct vfswrap_pwrite_state);
1045 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1049 *vfs_aio_state = state->vfs_aio_state;
1053 struct vfswrap_fsync_state {
1057 struct vfs_aio_state vfs_aio_state;
1058 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
1061 static void vfs_fsync_do(void *private_data);
1062 static void vfs_fsync_done(struct tevent_req *subreq);
1063 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state);
1065 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
1066 TALLOC_CTX *mem_ctx,
1067 struct tevent_context *ev,
1068 struct files_struct *fsp)
1070 struct tevent_req *req, *subreq;
1071 struct vfswrap_fsync_state *state;
1073 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
1079 state->fd = fsp->fh->fd;
1081 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_fsync, profile_p,
1082 state->profile_bytes, 0);
1083 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1085 subreq = pthreadpool_tevent_job_send(
1086 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
1087 if (tevent_req_nomem(subreq, req)) {
1088 return tevent_req_post(req, ev);
1090 tevent_req_set_callback(subreq, vfs_fsync_done, req);
1092 talloc_set_destructor(state, vfs_fsync_state_destructor);
1097 static void vfs_fsync_do(void *private_data)
1099 struct vfswrap_fsync_state *state = talloc_get_type_abort(
1100 private_data, struct vfswrap_fsync_state);
1101 struct timespec start_time;
1102 struct timespec end_time;
1104 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
1106 PROFILE_TIMESTAMP(&start_time);
1109 state->ret = fsync(state->fd);
1110 } while ((state->ret == -1) && (errno == EINTR));
1112 if (state->ret == -1) {
1113 state->vfs_aio_state.error = errno;
1116 PROFILE_TIMESTAMP(&end_time);
1118 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1120 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1123 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state)
1128 static void vfs_fsync_done(struct tevent_req *subreq)
1130 struct tevent_req *req = tevent_req_callback_data(
1131 subreq, struct tevent_req);
1132 struct vfswrap_fsync_state *state = tevent_req_data(
1133 req, struct vfswrap_fsync_state);
1136 ret = pthreadpool_tevent_job_recv(subreq);
1137 TALLOC_FREE(subreq);
1138 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1139 talloc_set_destructor(state, NULL);
1141 if (ret != EAGAIN) {
1142 tevent_req_error(req, ret);
1146 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1147 * means the lower level pthreadpool failed to create a new
1148 * thread. Fallback to sync processing in that case to allow
1149 * some progress for the client.
1151 vfs_fsync_do(state);
1154 tevent_req_done(req);
1157 static int vfswrap_fsync_recv(struct tevent_req *req,
1158 struct vfs_aio_state *vfs_aio_state)
1160 struct vfswrap_fsync_state *state = tevent_req_data(
1161 req, struct vfswrap_fsync_state);
1163 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1167 *vfs_aio_state = state->vfs_aio_state;
1171 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1175 START_PROFILE(syscall_lseek);
1177 result = lseek(fsp->fh->fd, offset, whence);
1179 * We want to maintain the fiction that we can seek
1180 * on a fifo for file system purposes. This allows
1181 * people to set up UNIX fifo's that feed data to Windows
1182 * applications. JRA.
1185 if((result == -1) && (errno == ESPIPE)) {
1190 END_PROFILE(syscall_lseek);
1194 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1195 off_t offset, size_t n)
1199 START_PROFILE_BYTES(syscall_sendfile, n);
1200 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
1201 END_PROFILE_BYTES(syscall_sendfile);
1205 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1207 files_struct *tofsp,
1213 START_PROFILE_BYTES(syscall_recvfile, n);
1214 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
1215 END_PROFILE_BYTES(syscall_recvfile);
1219 static int vfswrap_renameat(vfs_handle_struct *handle,
1220 files_struct *srcfsp,
1221 const struct smb_filename *smb_fname_src,
1222 files_struct *dstfsp,
1223 const struct smb_filename *smb_fname_dst)
1227 START_PROFILE(syscall_renameat);
1229 if (is_named_stream(smb_fname_src) || is_named_stream(smb_fname_dst)) {
1234 result = renameat(srcfsp->fh->fd,
1235 smb_fname_src->base_name,
1237 smb_fname_dst->base_name);
1240 END_PROFILE(syscall_renameat);
1244 static int vfswrap_stat(vfs_handle_struct *handle,
1245 struct smb_filename *smb_fname)
1249 START_PROFILE(syscall_stat);
1251 if (is_named_stream(smb_fname)) {
1256 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1257 lp_fake_directory_create_times(SNUM(handle->conn)));
1259 END_PROFILE(syscall_stat);
1263 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1267 START_PROFILE(syscall_fstat);
1268 result = sys_fstat(fsp->fh->fd,
1269 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1270 END_PROFILE(syscall_fstat);
1274 static int vfswrap_lstat(vfs_handle_struct *handle,
1275 struct smb_filename *smb_fname)
1279 START_PROFILE(syscall_lstat);
1281 if (is_named_stream(smb_fname)) {
1286 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1287 lp_fake_directory_create_times(SNUM(handle->conn)));
1289 END_PROFILE(syscall_lstat);
1293 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1295 enum vfs_translate_direction direction,
1296 TALLOC_CTX *mem_ctx,
1299 return NT_STATUS_NONE_MAPPED;
1303 * Implement the default fsctl operation.
1305 static bool vfswrap_logged_ioctl_message = false;
1307 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1308 struct files_struct *fsp,
1311 uint16_t req_flags, /* Needed for UNICODE ... */
1312 const uint8_t *_in_data,
1314 uint8_t **_out_data,
1315 uint32_t max_out_len,
1318 const char *in_data = (const char *)_in_data;
1319 char **out_data = (char **)_out_data;
1323 case FSCTL_SET_SPARSE:
1325 bool set_sparse = true;
1327 if (in_len >= 1 && in_data[0] == 0) {
1331 status = file_set_sparse(handle->conn, fsp, set_sparse);
1333 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1334 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1335 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1336 nt_errstr(status)));
1341 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1343 unsigned char objid[16];
1344 char *return_data = NULL;
1346 /* This should return the object-id on this file.
1347 * I think I'll make this be the inode+dev. JRA.
1350 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1351 fsp_fnum_dbg(fsp)));
1353 *out_len = MIN(max_out_len, 64);
1355 /* Hmmm, will this cause problems if less data asked for? */
1356 return_data = talloc_array(ctx, char, 64);
1357 if (return_data == NULL) {
1358 return NT_STATUS_NO_MEMORY;
1361 /* For backwards compatibility only store the dev/inode. */
1362 push_file_id_16(return_data, &fsp->file_id);
1363 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1364 push_file_id_16(return_data+32, &fsp->file_id);
1365 memset(return_data+48, 0, 16);
1366 *out_data = return_data;
1367 return NT_STATUS_OK;
1370 case FSCTL_GET_REPARSE_POINT:
1372 status = fsctl_get_reparse_point(
1373 fsp, ctx, out_data, max_out_len, out_len);
1377 case FSCTL_SET_REPARSE_POINT:
1379 status = fsctl_set_reparse_point(fsp, ctx, _in_data, in_len);
1383 case FSCTL_DELETE_REPARSE_POINT:
1385 status = fsctl_del_reparse_point(fsp, ctx, _in_data, in_len);
1389 case FSCTL_GET_SHADOW_COPY_DATA:
1392 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1393 * and return their volume names. If max_data_count is 16, then it is just
1394 * asking for the number of volumes and length of the combined names.
1396 * pdata is the data allocated by our caller, but that uses
1397 * total_data_count (which is 0 in our case) rather than max_data_count.
1398 * Allocate the correct amount and return the pointer to let
1399 * it be deallocated when we return.
1401 struct shadow_copy_data *shadow_data = NULL;
1402 bool labels = False;
1403 uint32_t labels_data_count = 0;
1405 char *cur_pdata = NULL;
1407 if (max_out_len < 16) {
1408 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1410 return NT_STATUS_INVALID_PARAMETER;
1413 if (max_out_len > 16) {
1417 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1418 if (shadow_data == NULL) {
1419 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1420 return NT_STATUS_NO_MEMORY;
1424 * Call the VFS routine to actually do the work.
1426 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1429 /* broken module didn't set errno on error */
1430 status = NT_STATUS_UNSUCCESSFUL;
1432 status = map_nt_error_from_unix(errno);
1433 if (NT_STATUS_EQUAL(status,
1434 NT_STATUS_NOT_SUPPORTED)) {
1438 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1439 "connectpath %s, failed - %s.\n",
1440 fsp->conn->connectpath,
1441 nt_errstr(status)));
1442 TALLOC_FREE(shadow_data);
1446 labels_data_count = (shadow_data->num_volumes * 2 *
1447 sizeof(SHADOW_COPY_LABEL)) + 2;
1452 *out_len = 12 + labels_data_count;
1455 if (max_out_len < *out_len) {
1456 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1457 max_out_len, *out_len));
1458 TALLOC_FREE(shadow_data);
1459 return NT_STATUS_BUFFER_TOO_SMALL;
1462 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1463 if (cur_pdata == NULL) {
1464 TALLOC_FREE(shadow_data);
1465 return NT_STATUS_NO_MEMORY;
1468 *out_data = cur_pdata;
1470 /* num_volumes 4 bytes */
1471 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1474 /* num_labels 4 bytes */
1475 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1478 /* needed_data_count 4 bytes */
1479 SIVAL(cur_pdata, 8, labels_data_count);
1483 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1484 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1485 if (labels && shadow_data->labels) {
1486 for (i=0; i<shadow_data->num_volumes; i++) {
1488 status = srvstr_push(cur_pdata, req_flags,
1489 cur_pdata, shadow_data->labels[i],
1490 2 * sizeof(SHADOW_COPY_LABEL),
1491 STR_UNICODE|STR_TERMINATE, &len);
1492 if (!NT_STATUS_IS_OK(status)) {
1493 TALLOC_FREE(*out_data);
1494 TALLOC_FREE(shadow_data);
1497 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1498 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1502 TALLOC_FREE(shadow_data);
1504 return NT_STATUS_OK;
1507 case FSCTL_FIND_FILES_BY_SID:
1509 /* pretend this succeeded -
1511 * we have to send back a list with all files owned by this SID
1513 * but I have to check that --metze
1517 struct dom_sid_buf buf;
1521 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1522 fsp_fnum_dbg(fsp)));
1525 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1526 return NT_STATUS_INVALID_PARAMETER;
1529 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1531 /* unknown 4 bytes: this is not the length of the sid :-( */
1532 /*unknown = IVAL(pdata,0);*/
1534 ret = sid_parse(_in_data + 4, sid_len, &sid);
1536 return NT_STATUS_INVALID_PARAMETER;
1538 DEBUGADD(10, ("for SID: %s\n",
1539 dom_sid_str_buf(&sid, &buf)));
1541 if (!sid_to_uid(&sid, &uid)) {
1542 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1543 dom_sid_str_buf(&sid, &buf),
1544 (unsigned long)sid_len));
1548 /* we can take a look at the find source :-)
1550 * find ./ -uid $uid -name '*' is what we need here
1553 * and send 4bytes len and then NULL terminated unicode strings
1556 * but I don't know how to deal with the paged results
1557 * (maybe we can hang the result anywhere in the fsp struct)
1559 * but I don't know how to deal with the paged results
1560 * (maybe we can hang the result anywhere in the fsp struct)
1562 * we don't send all files at once
1563 * and at the next we should *not* start from the beginning,
1564 * so we have to cache the result
1569 /* this works for now... */
1570 return NT_STATUS_OK;
1573 case FSCTL_QUERY_ALLOCATED_RANGES:
1575 /* FIXME: This is just a dummy reply, telling that all of the
1576 * file is allocated. MKS cp needs that.
1577 * Adding the real allocated ranges via FIEMAP on Linux
1578 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1579 * this FSCTL correct for sparse files.
1581 uint64_t offset, length;
1582 char *out_data_tmp = NULL;
1585 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1587 return NT_STATUS_INVALID_PARAMETER;
1590 if (max_out_len < 16) {
1591 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1593 return NT_STATUS_INVALID_PARAMETER;
1596 offset = BVAL(in_data,0);
1597 length = BVAL(in_data,8);
1599 if (offset + length < offset) {
1600 /* No 64-bit integer wrap. */
1601 return NT_STATUS_INVALID_PARAMETER;
1604 /* Shouldn't this be SMB_VFS_STAT ... ? */
1605 status = vfs_stat_fsp(fsp);
1606 if (!NT_STATUS_IS_OK(status)) {
1611 out_data_tmp = talloc_array(ctx, char, *out_len);
1612 if (out_data_tmp == NULL) {
1613 DEBUG(10, ("unable to allocate memory for response\n"));
1614 return NT_STATUS_NO_MEMORY;
1617 if (offset > fsp->fsp_name->st.st_ex_size ||
1618 fsp->fsp_name->st.st_ex_size == 0 ||
1620 memset(out_data_tmp, 0, *out_len);
1622 uint64_t end = offset + length;
1623 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1624 SBVAL(out_data_tmp, 0, 0);
1625 SBVAL(out_data_tmp, 8, end);
1628 *out_data = out_data_tmp;
1630 return NT_STATUS_OK;
1633 case FSCTL_IS_VOLUME_DIRTY:
1635 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1636 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1638 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1639 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1641 return NT_STATUS_INVALID_PARAMETER;
1646 * Only print once ... unfortunately there could be lots of
1647 * different FSCTLs that are called.
1649 if (!vfswrap_logged_ioctl_message) {
1650 vfswrap_logged_ioctl_message = true;
1651 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1652 __func__, function));
1656 return NT_STATUS_NOT_SUPPORTED;
1659 static bool vfswrap_is_offline(struct connection_struct *conn,
1660 const struct smb_filename *fname);
1662 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1663 struct smb_filename *smb_fname,
1668 offline = vfswrap_is_offline(handle->conn, smb_fname);
1670 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1673 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1676 struct vfswrap_get_dos_attributes_state {
1677 struct vfs_aio_state aio_state;
1678 connection_struct *conn;
1679 TALLOC_CTX *mem_ctx;
1680 struct tevent_context *ev;
1681 files_struct *dir_fsp;
1682 struct smb_filename *smb_fname;
1687 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq);
1689 static struct tevent_req *vfswrap_get_dos_attributes_send(
1690 TALLOC_CTX *mem_ctx,
1691 struct tevent_context *ev,
1692 struct vfs_handle_struct *handle,
1693 files_struct *dir_fsp,
1694 struct smb_filename *smb_fname)
1696 struct tevent_req *req = NULL;
1697 struct tevent_req *subreq = NULL;
1698 struct vfswrap_get_dos_attributes_state *state = NULL;
1700 req = tevent_req_create(mem_ctx, &state,
1701 struct vfswrap_get_dos_attributes_state);
1706 *state = (struct vfswrap_get_dos_attributes_state) {
1707 .conn = dir_fsp->conn,
1711 .smb_fname = smb_fname,
1714 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1718 SAMBA_XATTR_DOS_ATTRIB,
1720 if (tevent_req_nomem(subreq, req)) {
1721 return tevent_req_post(req, ev);
1723 tevent_req_set_callback(subreq,
1724 vfswrap_get_dos_attributes_getxattr_done,
1730 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq)
1732 struct tevent_req *req =
1733 tevent_req_callback_data(subreq,
1735 struct vfswrap_get_dos_attributes_state *state =
1736 tevent_req_data(req,
1737 struct vfswrap_get_dos_attributes_state);
1739 DATA_BLOB blob = {0};
1741 char *tofree = NULL;
1742 char pathbuf[PATH_MAX+1];
1744 struct smb_filename smb_fname;
1748 xattr_size = SMB_VFS_GETXATTRAT_RECV(subreq,
1752 TALLOC_FREE(subreq);
1753 if (xattr_size == -1) {
1754 status = map_nt_error_from_unix(state->aio_state.error);
1756 if (state->as_root) {
1757 tevent_req_nterror(req, status);
1760 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1761 tevent_req_nterror(req, status);
1765 state->as_root = true;
1768 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1772 SAMBA_XATTR_DOS_ATTRIB,
1775 if (tevent_req_nomem(subreq, req)) {
1778 tevent_req_set_callback(subreq,
1779 vfswrap_get_dos_attributes_getxattr_done,
1784 blob.length = xattr_size;
1786 status = parse_dos_attribute_blob(state->smb_fname,
1789 if (!NT_STATUS_IS_OK(status)) {
1790 tevent_req_nterror(req, status);
1794 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
1795 state->smb_fname->base_name,
1800 if (pathlen == -1) {
1801 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1805 smb_fname = (struct smb_filename) {
1807 .st = state->smb_fname->st,
1808 .flags = state->smb_fname->flags,
1809 .twrp = state->smb_fname->twrp,
1812 offline = vfswrap_is_offline(state->conn, &smb_fname);
1814 state->dosmode |= FILE_ATTRIBUTE_OFFLINE;
1816 TALLOC_FREE(tofree);
1818 tevent_req_done(req);
1822 static NTSTATUS vfswrap_get_dos_attributes_recv(struct tevent_req *req,
1823 struct vfs_aio_state *aio_state,
1826 struct vfswrap_get_dos_attributes_state *state =
1827 tevent_req_data(req,
1828 struct vfswrap_get_dos_attributes_state);
1831 if (tevent_req_is_nterror(req, &status)) {
1832 tevent_req_received(req);
1836 *aio_state = state->aio_state;
1837 *dosmode = state->dosmode;
1838 tevent_req_received(req);
1839 return NT_STATUS_OK;
1842 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1843 struct files_struct *fsp,
1848 offline = vfswrap_is_offline(handle->conn, fsp->fsp_name);
1850 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1853 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1856 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1857 const struct smb_filename *smb_fname,
1860 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1863 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1864 struct files_struct *fsp,
1867 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1870 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1872 struct vfswrap_offload_read_state {
1876 static struct tevent_req *vfswrap_offload_read_send(
1877 TALLOC_CTX *mem_ctx,
1878 struct tevent_context *ev,
1879 struct vfs_handle_struct *handle,
1880 struct files_struct *fsp,
1886 struct tevent_req *req = NULL;
1887 struct vfswrap_offload_read_state *state = NULL;
1890 req = tevent_req_create(mem_ctx, &state,
1891 struct vfswrap_offload_read_state);
1896 status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1897 &vfswrap_offload_ctx);
1898 if (tevent_req_nterror(req, status)) {
1899 return tevent_req_post(req, ev);
1902 if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1903 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1904 return tevent_req_post(req, ev);
1907 status = vfs_offload_token_create_blob(state, fsp, fsctl,
1909 if (tevent_req_nterror(req, status)) {
1910 return tevent_req_post(req, ev);
1913 status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1915 if (tevent_req_nterror(req, status)) {
1916 return tevent_req_post(req, ev);
1919 tevent_req_done(req);
1920 return tevent_req_post(req, ev);
1923 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
1924 struct vfs_handle_struct *handle,
1925 TALLOC_CTX *mem_ctx,
1928 struct vfswrap_offload_read_state *state = tevent_req_data(
1929 req, struct vfswrap_offload_read_state);
1932 if (tevent_req_is_nterror(req, &status)) {
1933 tevent_req_received(req);
1937 token->length = state->token.length;
1938 token->data = talloc_move(mem_ctx, &state->token.data);
1940 tevent_req_received(req);
1941 return NT_STATUS_OK;
1944 struct vfswrap_offload_write_state {
1946 bool read_lck_locked;
1947 bool write_lck_locked;
1949 struct tevent_context *src_ev;
1950 struct files_struct *src_fsp;
1952 struct tevent_context *dst_ev;
1953 struct files_struct *dst_fsp;
1957 size_t next_io_size;
1960 static void vfswrap_offload_write_cleanup(struct tevent_req *req,
1961 enum tevent_req_state req_state)
1963 struct vfswrap_offload_write_state *state = tevent_req_data(
1964 req, struct vfswrap_offload_write_state);
1967 if (state->dst_fsp == NULL) {
1971 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
1973 state->dst_fsp = NULL;
1976 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
1978 static struct tevent_req *vfswrap_offload_write_send(
1979 struct vfs_handle_struct *handle,
1980 TALLOC_CTX *mem_ctx,
1981 struct tevent_context *ev,
1984 off_t transfer_offset,
1985 struct files_struct *dest_fsp,
1989 struct tevent_req *req;
1990 struct vfswrap_offload_write_state *state = NULL;
1991 /* off_t is signed! */
1992 off_t max_offset = INT64_MAX - to_copy;
1993 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
1994 files_struct *src_fsp = NULL;
1998 req = tevent_req_create(mem_ctx, &state,
1999 struct vfswrap_offload_write_state);
2004 *state = (struct vfswrap_offload_write_state) {
2006 .src_off = transfer_offset,
2008 .dst_fsp = dest_fsp,
2009 .dst_off = dest_off,
2011 .remaining = to_copy,
2014 tevent_req_set_cleanup_fn(req, vfswrap_offload_write_cleanup);
2017 case FSCTL_SRV_COPYCHUNK:
2018 case FSCTL_SRV_COPYCHUNK_WRITE:
2021 case FSCTL_OFFLOAD_WRITE:
2022 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
2023 return tevent_req_post(req, ev);
2025 case FSCTL_DUP_EXTENTS_TO_FILE:
2026 DBG_DEBUG("COW clones not supported by vfs_default\n");
2027 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2028 return tevent_req_post(req, ev);
2031 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2032 return tevent_req_post(req, ev);
2036 * From here on we assume a copy-chunk fsctl
2040 tevent_req_done(req);
2041 return tevent_req_post(req, ev);
2044 if (state->src_off > max_offset) {
2046 * Protect integer checks below.
2048 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2049 return tevent_req_post(req, ev);
2051 if (state->src_off < 0) {
2053 * Protect integer checks below.
2055 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2056 return tevent_req_post(req, ev);
2058 if (state->dst_off > max_offset) {
2060 * Protect integer checks below.
2062 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2063 return tevent_req_post(req, ev);
2065 if (state->dst_off < 0) {
2067 * Protect integer checks below.
2069 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2070 return tevent_req_post(req, ev);
2073 status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
2075 if (tevent_req_nterror(req, status)) {
2076 return tevent_req_post(req, ev);
2079 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
2081 status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
2082 if (!NT_STATUS_IS_OK(status)) {
2083 tevent_req_nterror(req, status);
2084 return tevent_req_post(req, ev);
2087 ok = change_to_user_and_service_by_fsp(src_fsp);
2089 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2090 return tevent_req_post(req, ev);
2093 state->src_ev = src_fsp->conn->sconn->ev_ctx;
2094 state->src_fsp = src_fsp;
2096 status = vfs_stat_fsp(src_fsp);
2097 if (tevent_req_nterror(req, status)) {
2098 return tevent_req_post(req, ev);
2101 if (src_fsp->fsp_name->st.st_ex_size < state->src_off + to_copy) {
2103 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
2104 * If the SourceOffset or SourceOffset + Length extends beyond
2105 * the end of file, the server SHOULD<240> treat this as a
2106 * STATUS_END_OF_FILE error.
2108 * <240> Section 3.3.5.15.6: Windows servers will return
2109 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
2111 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
2112 return tevent_req_post(req, ev);
2115 state->buf = talloc_array(state, uint8_t, num);
2116 if (tevent_req_nomem(state->buf, req)) {
2117 return tevent_req_post(req, ev);
2120 status = vfswrap_offload_write_loop(req);
2121 if (!NT_STATUS_IS_OK(status)) {
2122 tevent_req_nterror(req, status);
2123 return tevent_req_post(req, ev);
2129 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
2131 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
2133 struct vfswrap_offload_write_state *state = tevent_req_data(
2134 req, struct vfswrap_offload_write_state);
2135 struct tevent_req *subreq = NULL;
2136 struct lock_struct read_lck;
2140 * This is called under the context of state->src_fsp.
2143 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
2145 init_strict_lock_struct(state->src_fsp,
2146 state->src_fsp->op->global->open_persistent_id,
2148 state->next_io_size,
2152 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
2156 return NT_STATUS_FILE_LOCK_CONFLICT;
2159 subreq = SMB_VFS_PREAD_SEND(state,
2163 state->next_io_size,
2165 if (subreq == NULL) {
2166 return NT_STATUS_NO_MEMORY;
2168 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
2170 return NT_STATUS_OK;
2173 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
2175 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
2177 struct tevent_req *req = tevent_req_callback_data(
2178 subreq, struct tevent_req);
2179 struct vfswrap_offload_write_state *state = tevent_req_data(
2180 req, struct vfswrap_offload_write_state);
2181 struct vfs_aio_state aio_state;
2182 struct lock_struct write_lck;
2186 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
2187 TALLOC_FREE(subreq);
2189 DBG_ERR("read failed: %s\n", strerror(aio_state.error));
2190 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2193 if (nread != state->next_io_size) {
2194 DBG_ERR("Short read, only %zd of %zu\n",
2195 nread, state->next_io_size);
2196 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2200 state->src_off += nread;
2202 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2204 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2208 init_strict_lock_struct(state->dst_fsp,
2209 state->dst_fsp->op->global->open_persistent_id,
2211 state->next_io_size,
2215 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
2219 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
2223 subreq = SMB_VFS_PWRITE_SEND(state,
2227 state->next_io_size,
2229 if (subreq == NULL) {
2230 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2233 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
2236 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
2238 struct tevent_req *req = tevent_req_callback_data(
2239 subreq, struct tevent_req);
2240 struct vfswrap_offload_write_state *state = tevent_req_data(
2241 req, struct vfswrap_offload_write_state);
2242 struct vfs_aio_state aio_state;
2247 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
2248 TALLOC_FREE(subreq);
2249 if (nwritten == -1) {
2250 DBG_ERR("write failed: %s\n", strerror(aio_state.error));
2251 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2254 if (nwritten != state->next_io_size) {
2255 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
2256 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2260 state->dst_off += nwritten;
2262 if (state->remaining < nwritten) {
2263 /* Paranoia check */
2264 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2267 state->remaining -= nwritten;
2268 if (state->remaining == 0) {
2269 tevent_req_done(req);
2273 ok = change_to_user_and_service_by_fsp(state->src_fsp);
2275 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2279 status = vfswrap_offload_write_loop(req);
2280 if (!NT_STATUS_IS_OK(status)) {
2281 tevent_req_nterror(req, status);
2288 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
2289 struct tevent_req *req,
2292 struct vfswrap_offload_write_state *state = tevent_req_data(
2293 req, struct vfswrap_offload_write_state);
2296 if (tevent_req_is_nterror(req, &status)) {
2297 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
2299 tevent_req_received(req);
2303 *copied = state->to_copy;
2304 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
2305 tevent_req_received(req);
2307 return NT_STATUS_OK;
2310 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
2311 TALLOC_CTX *mem_ctx,
2312 struct files_struct *fsp,
2313 struct smb_filename *smb_fname,
2314 uint16_t *_compression_fmt)
2316 return NT_STATUS_INVALID_DEVICE_REQUEST;
2319 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
2320 TALLOC_CTX *mem_ctx,
2321 struct files_struct *fsp,
2322 uint16_t compression_fmt)
2324 return NT_STATUS_INVALID_DEVICE_REQUEST;
2327 /********************************************************************
2328 Given a stat buffer return the allocated size on disk, taking into
2329 account sparse files.
2330 ********************************************************************/
2331 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
2332 struct files_struct *fsp,
2333 const SMB_STRUCT_STAT *sbuf)
2337 START_PROFILE(syscall_get_alloc_size);
2339 if(S_ISDIR(sbuf->st_ex_mode)) {
2344 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2345 /* The type of st_blocksize is blkcnt_t which *MUST* be
2346 signed (according to POSIX) and can be less than 64-bits.
2347 Ensure when we're converting to 64 bits wide we don't
2349 #if defined(SIZEOF_BLKCNT_T_8)
2350 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2351 #elif defined(SIZEOF_BLKCNT_T_4)
2353 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2354 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2357 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2361 * Some file systems do not allocate a block for very
2362 * small files. But for non-empty file should report a
2366 uint64_t filesize = get_file_size_stat(sbuf);
2368 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2372 result = get_file_size_stat(sbuf);
2375 if (fsp && fsp->initial_allocation_size)
2376 result = MAX(result,fsp->initial_allocation_size);
2378 result = smb_roundup(handle->conn, result);
2381 END_PROFILE(syscall_get_alloc_size);
2385 static int vfswrap_unlinkat(vfs_handle_struct *handle,
2386 struct files_struct *dirfsp,
2387 const struct smb_filename *smb_fname,
2392 START_PROFILE(syscall_unlinkat);
2394 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2396 if (is_named_stream(smb_fname)) {
2400 result = unlinkat(dirfsp->fh->fd,
2401 smb_fname->base_name,
2405 END_PROFILE(syscall_unlinkat);
2409 static int vfswrap_chmod(vfs_handle_struct *handle,
2410 const struct smb_filename *smb_fname,
2415 START_PROFILE(syscall_chmod);
2416 result = chmod(smb_fname->base_name, mode);
2417 END_PROFILE(syscall_chmod);
2421 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2425 START_PROFILE(syscall_fchmod);
2426 #if defined(HAVE_FCHMOD)
2427 result = fchmod(fsp->fh->fd, mode);
2433 END_PROFILE(syscall_fchmod);
2437 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2442 START_PROFILE(syscall_fchown);
2443 result = fchown(fsp->fh->fd, uid, gid);
2444 END_PROFILE(syscall_fchown);
2452 static int vfswrap_lchown(vfs_handle_struct *handle,
2453 const struct smb_filename *smb_fname,
2459 START_PROFILE(syscall_lchown);
2460 result = lchown(smb_fname->base_name, uid, gid);
2461 END_PROFILE(syscall_lchown);
2465 static int vfswrap_chdir(vfs_handle_struct *handle,
2466 const struct smb_filename *smb_fname)
2470 START_PROFILE(syscall_chdir);
2471 result = chdir(smb_fname->base_name);
2472 END_PROFILE(syscall_chdir);
2476 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2480 struct smb_filename *smb_fname = NULL;
2482 START_PROFILE(syscall_getwd);
2483 result = sys_getwd();
2484 END_PROFILE(syscall_getwd);
2486 if (result == NULL) {
2489 smb_fname = synthetic_smb_fname(ctx,
2496 * sys_getwd() *always* returns malloced memory.
2497 * We must free here to avoid leaks:
2498 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2504 /*********************************************************************
2505 nsec timestamp resolution call. Convert down to whatever the underlying
2506 system will support.
2507 **********************************************************************/
2509 static int vfswrap_ntimes(vfs_handle_struct *handle,
2510 const struct smb_filename *smb_fname,
2511 struct smb_file_time *ft)
2515 START_PROFILE(syscall_ntimes);
2517 if (is_named_stream(smb_fname)) {
2523 if (is_omit_timespec(&ft->atime)) {
2524 ft->atime= smb_fname->st.st_ex_atime;
2527 if (is_omit_timespec(&ft->mtime)) {
2528 ft->mtime = smb_fname->st.st_ex_mtime;
2531 if (!is_omit_timespec(&ft->create_time)) {
2532 set_create_timespec_ea(handle->conn,
2537 if ((timespec_compare(&ft->atime,
2538 &smb_fname->st.st_ex_atime) == 0) &&
2539 (timespec_compare(&ft->mtime,
2540 &smb_fname->st.st_ex_mtime) == 0)) {
2545 #if defined(HAVE_UTIMENSAT)
2547 struct timespec ts[2];
2550 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2552 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2554 if (!((result == -1) && (errno == ENOSYS))) {
2558 #if defined(HAVE_UTIMES)
2560 struct timeval tv[2];
2561 tv[0] = convert_timespec_to_timeval(ft->atime);
2562 tv[1] = convert_timespec_to_timeval(ft->mtime);
2563 result = utimes(smb_fname->base_name, tv);
2565 result = utimes(smb_fname->base_name, NULL);
2567 if (!((result == -1) && (errno == ENOSYS))) {
2571 #if defined(HAVE_UTIME)
2573 struct utimbuf times;
2574 times.actime = convert_timespec_to_time_t(ft->atime);
2575 times.modtime = convert_timespec_to_time_t(ft->mtime);
2576 result = utime(smb_fname->base_name, ×);
2578 result = utime(smb_fname->base_name, NULL);
2580 if (!((result == -1) && (errno == ENOSYS))) {
2588 END_PROFILE(syscall_ntimes);
2592 /*********************************************************************
2593 A version of ftruncate that will write the space on disk if strict
2595 **********************************************************************/
2597 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2599 off_t space_to_write;
2600 uint64_t space_avail;
2601 uint64_t bsize,dfree,dsize;
2604 SMB_STRUCT_STAT *pst;
2607 ok = vfs_valid_pwrite_range(len, 0);
2613 status = vfs_stat_fsp(fsp);
2614 if (!NT_STATUS_IS_OK(status)) {
2617 pst = &fsp->fsp_name->st;
2620 if (S_ISFIFO(pst->st_ex_mode))
2624 if (pst->st_ex_size == len)
2627 /* Shrink - just ftruncate. */
2628 if (pst->st_ex_size > len)
2629 return ftruncate(fsp->fh->fd, len);
2631 space_to_write = len - pst->st_ex_size;
2633 /* for allocation try fallocate first. This can fail on some
2634 platforms e.g. when the filesystem doesn't support it and no
2635 emulation is being done by the libc (like on AIX with JFS1). In that
2636 case we do our own emulation. fallocate implementations can
2637 return ENOTSUP or EINVAL in cases like that. */
2638 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2639 if (ret == -1 && errno == ENOSPC) {
2645 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2646 "error %d. Falling back to slow manual allocation\n", errno));
2648 /* available disk space is enough or not? */
2650 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2651 /* space_avail is 1k blocks */
2652 if (space_avail == (uint64_t)-1 ||
2653 ((uint64_t)space_to_write/1024 > space_avail) ) {
2658 /* Write out the real space on disk. */
2659 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2667 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2670 SMB_STRUCT_STAT *pst;
2674 START_PROFILE(syscall_ftruncate);
2676 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->fsp_flags.is_sparse) {
2677 result = strict_allocate_ftruncate(handle, fsp, len);
2678 END_PROFILE(syscall_ftruncate);
2682 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2683 ftruncate if the system supports it. Then I discovered that
2684 you can have some filesystems that support ftruncate
2685 expansion and some that don't! On Linux fat can't do
2686 ftruncate extend but ext2 can. */
2688 result = ftruncate(fsp->fh->fd, len);
2690 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2691 extend a file with ftruncate. Provide alternate implementation
2694 /* Do an fstat to see if the file is longer than the requested
2695 size in which case the ftruncate above should have
2696 succeeded or shorter, in which case seek to len - 1 and
2697 write 1 byte of zero */
2698 status = vfs_stat_fsp(fsp);
2699 if (!NT_STATUS_IS_OK(status)) {
2703 /* We need to update the files_struct after successful ftruncate */
2708 pst = &fsp->fsp_name->st;
2711 if (S_ISFIFO(pst->st_ex_mode)) {
2717 if (pst->st_ex_size == len) {
2722 if (pst->st_ex_size > len) {
2723 /* the ftruncate should have worked */
2727 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2735 END_PROFILE(syscall_ftruncate);
2739 static int vfswrap_fallocate(vfs_handle_struct *handle,
2747 START_PROFILE(syscall_fallocate);
2749 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2751 * posix_fallocate returns 0 on success, errno on error
2752 * and doesn't set errno. Make it behave like fallocate()
2753 * which returns -1, and sets errno on failure.
2760 /* sys_fallocate handles filtering of unsupported mode flags */
2761 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2763 END_PROFILE(syscall_fallocate);
2767 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2771 START_PROFILE(syscall_fcntl_lock);
2773 if (fsp->fsp_flags.use_ofd_locks) {
2774 op = map_process_lock_to_ofd_lock(op);
2777 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2778 END_PROFILE(syscall_fcntl_lock);
2782 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2783 uint32_t share_access, uint32_t access_mask)
2785 START_PROFILE(syscall_kernel_flock);
2786 kernel_flock(fsp->fh->fd, share_access, access_mask);
2787 END_PROFILE(syscall_kernel_flock);
2791 static int vfswrap_fcntl(vfs_handle_struct *handle, files_struct *fsp, int cmd,
2795 va_list dup_cmd_arg;
2799 START_PROFILE(syscall_fcntl);
2801 va_copy(dup_cmd_arg, cmd_arg);
2807 #if defined(HAVE_OFD_LOCKS)
2812 #if defined(HAVE_F_OWNER_EX)
2816 #if defined(HAVE_RW_HINTS)
2819 case F_GET_FILE_RW_HINT:
2820 case F_SET_FILE_RW_HINT:
2822 argp = va_arg(dup_cmd_arg, void *);
2823 result = sys_fcntl_ptr(fsp->fh->fd, cmd, argp);
2826 val = va_arg(dup_cmd_arg, int);
2827 result = sys_fcntl_int(fsp->fh->fd, cmd, val);
2830 va_end(dup_cmd_arg);
2832 END_PROFILE(syscall_fcntl);
2836 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2841 START_PROFILE(syscall_fcntl_getlock);
2843 if (fsp->fsp_flags.use_ofd_locks) {
2844 op = map_process_lock_to_ofd_lock(op);
2847 result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2848 END_PROFILE(syscall_fcntl_getlock);
2852 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2857 START_PROFILE(syscall_linux_setlease);
2859 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2860 result = linux_setlease(fsp->fh->fd, leasetype);
2864 END_PROFILE(syscall_linux_setlease);
2868 static int vfswrap_symlinkat(vfs_handle_struct *handle,
2869 const struct smb_filename *link_target,
2870 struct files_struct *dirfsp,
2871 const struct smb_filename *new_smb_fname)
2875 START_PROFILE(syscall_symlinkat);
2877 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2879 result = symlinkat(link_target->base_name,
2881 new_smb_fname->base_name);
2882 END_PROFILE(syscall_symlinkat);
2886 static int vfswrap_readlinkat(vfs_handle_struct *handle,
2887 files_struct *dirfsp,
2888 const struct smb_filename *smb_fname,
2894 START_PROFILE(syscall_readlinkat);
2896 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2898 result = readlinkat(dirfsp->fh->fd,
2899 smb_fname->base_name,
2903 END_PROFILE(syscall_readlinkat);
2907 static int vfswrap_linkat(vfs_handle_struct *handle,
2908 files_struct *srcfsp,
2909 const struct smb_filename *old_smb_fname,
2910 files_struct *dstfsp,
2911 const struct smb_filename *new_smb_fname,
2916 START_PROFILE(syscall_linkat);
2918 SMB_ASSERT(srcfsp == srcfsp->conn->cwd_fsp);
2919 SMB_ASSERT(dstfsp == dstfsp->conn->cwd_fsp);
2921 result = linkat(srcfsp->fh->fd,
2922 old_smb_fname->base_name,
2924 new_smb_fname->base_name,
2927 END_PROFILE(syscall_linkat);
2931 static int vfswrap_mknodat(vfs_handle_struct *handle,
2932 files_struct *dirfsp,
2933 const struct smb_filename *smb_fname,
2939 START_PROFILE(syscall_mknodat);
2941 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2943 result = sys_mknodat(dirfsp->fh->fd,
2944 smb_fname->base_name,
2948 END_PROFILE(syscall_mknodat);
2952 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2954 const struct smb_filename *smb_fname)
2957 struct smb_filename *result_fname = NULL;
2959 START_PROFILE(syscall_realpath);
2960 result = sys_realpath(smb_fname->base_name);
2961 END_PROFILE(syscall_realpath);
2963 result_fname = synthetic_smb_fname(ctx,
2971 return result_fname;
2974 static int vfswrap_chflags(vfs_handle_struct *handle,
2975 const struct smb_filename *smb_fname,
2979 return chflags(smb_fname->base_name, flags);
2986 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2987 const SMB_STRUCT_STAT *sbuf)
2991 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2995 key.devid = sbuf->st_ex_dev;
2996 key.inode = sbuf->st_ex_ino;
2997 /* key.extid is unused by default. */
3002 static uint64_t vfswrap_fs_file_id(struct vfs_handle_struct *handle,
3003 const SMB_STRUCT_STAT *psbuf)
3007 if (!(psbuf->st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)) {
3008 return psbuf->st_ex_file_id;
3011 if (handle->conn->base_share_dev == psbuf->st_ex_dev) {
3012 return (uint64_t)psbuf->st_ex_ino;
3016 file_id = ((psbuf->st_ex_ino) & UINT32_MAX);
3019 file_id |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32;
3024 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
3025 struct files_struct *fsp,
3026 const struct smb_filename *smb_fname,
3027 TALLOC_CTX *mem_ctx,
3028 unsigned int *pnum_streams,
3029 struct stream_struct **pstreams)
3031 SMB_STRUCT_STAT sbuf;
3032 struct stream_struct *tmp_streams = NULL;
3035 if ((fsp != NULL) && (fsp->fsp_flags.is_directory)) {
3037 * No default streams on directories
3042 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
3043 ret = SMB_VFS_FSTAT(fsp, &sbuf);
3046 struct smb_filename *smb_fname_cp = NULL;
3048 smb_fname_cp = cp_smb_filename_nostream(talloc_tos(), smb_fname);
3049 if (smb_fname_cp == NULL) {
3050 return NT_STATUS_NO_MEMORY;
3053 if (smb_fname_cp->flags & SMB_FILENAME_POSIX_PATH) {
3054 ret = SMB_VFS_LSTAT(handle->conn, smb_fname_cp);
3056 ret = SMB_VFS_STAT(handle->conn, smb_fname_cp);
3058 sbuf = smb_fname_cp->st;
3059 TALLOC_FREE(smb_fname_cp);
3063 return map_nt_error_from_unix(errno);
3066 if (S_ISDIR(sbuf.st_ex_mode)) {
3070 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
3071 (*pnum_streams) + 1);
3072 if (tmp_streams == NULL) {
3073 return NT_STATUS_NO_MEMORY;
3075 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
3076 if (tmp_streams[*pnum_streams].name == NULL) {
3077 return NT_STATUS_NO_MEMORY;
3079 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
3080 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
3083 *pstreams = tmp_streams;
3085 return NT_STATUS_OK;
3088 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
3089 const struct smb_filename *path,
3091 TALLOC_CTX *mem_ctx,
3095 * Don't fall back to get_real_filename so callers can differentiate
3096 * between a full directory scan and an actual case-insensitive stat.
3102 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
3103 const struct smb_filename *smb_fname)
3105 return handle->conn->connectpath;
3108 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
3109 struct byte_range_lock *br_lck,
3110 struct lock_struct *plock)
3112 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3114 /* Note: blr is not used in the default implementation. */
3115 return brl_lock_windows_default(br_lck, plock);
3118 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
3119 struct byte_range_lock *br_lck,
3120 const struct lock_struct *plock)
3122 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3124 return brl_unlock_windows_default(br_lck, plock);
3127 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
3129 struct lock_struct *plock)
3131 SMB_ASSERT(plock->lock_type == READ_LOCK ||
3132 plock->lock_type == WRITE_LOCK);
3134 return strict_lock_check_default(fsp, plock);
3137 /* NT ACL operations. */
3139 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
3141 uint32_t security_info,
3142 TALLOC_CTX *mem_ctx,
3143 struct security_descriptor **ppdesc)
3147 START_PROFILE(fget_nt_acl);
3148 result = posix_fget_nt_acl(fsp, security_info,
3150 END_PROFILE(fget_nt_acl);
3154 static NTSTATUS vfswrap_get_nt_acl_at(vfs_handle_struct *handle,
3155 struct files_struct *dirfsp,
3156 const struct smb_filename *smb_fname,
3157 uint32_t security_info,
3158 TALLOC_CTX *mem_ctx,
3159 struct security_descriptor **ppdesc)
3163 START_PROFILE(get_nt_acl_at);
3165 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
3167 result = posix_get_nt_acl(handle->conn,
3172 END_PROFILE(get_nt_acl_at);
3176 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
3180 START_PROFILE(fset_nt_acl);
3181 result = set_nt_acl(fsp, security_info_sent, psd);
3182 END_PROFILE(fset_nt_acl);
3186 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
3187 struct smb_filename *file,
3188 struct security_acl *sacl,
3189 uint32_t access_requested,
3190 uint32_t access_denied)
3192 return NT_STATUS_OK; /* Nothing to do here ... */
3195 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
3196 const struct smb_filename *smb_fname,
3197 SMB_ACL_TYPE_T type,
3198 TALLOC_CTX *mem_ctx)
3200 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
3203 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
3205 TALLOC_CTX *mem_ctx)
3207 return sys_acl_get_fd(handle, fsp, mem_ctx);
3210 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
3211 const struct smb_filename *smb_fname,
3212 SMB_ACL_TYPE_T acltype,
3215 return sys_acl_set_file(handle, smb_fname, acltype, theacl);
3218 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
3220 return sys_acl_set_fd(handle, fsp, theacl);
3223 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
3224 const struct smb_filename *smb_fname)
3226 return sys_acl_delete_def_file(handle, smb_fname);
3229 /****************************************************************
3230 Extended attribute operations.
3231 *****************************************************************/
3233 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
3234 const struct smb_filename *smb_fname,
3239 return getxattr(smb_fname->base_name, name, value, size);
3242 struct vfswrap_getxattrat_state {
3243 struct tevent_context *ev;
3244 files_struct *dir_fsp;
3245 const struct smb_filename *smb_fname;
3248 * The following variables are talloced off "state" which is protected
3249 * by a destructor and thus are guaranteed to be safe to be used in the
3250 * job function in the worker thread.
3253 const char *xattr_name;
3254 uint8_t *xattr_value;
3255 struct security_unix_token *token;
3258 struct vfs_aio_state vfs_aio_state;
3259 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
3262 static int vfswrap_getxattrat_state_destructor(
3263 struct vfswrap_getxattrat_state *state)
3268 static void vfswrap_getxattrat_do_sync(struct tevent_req *req);
3269 static void vfswrap_getxattrat_do_async(void *private_data);
3270 static void vfswrap_getxattrat_done(struct tevent_req *subreq);
3272 static struct tevent_req *vfswrap_getxattrat_send(
3273 TALLOC_CTX *mem_ctx,
3274 struct tevent_context *ev,
3275 struct vfs_handle_struct *handle,
3276 files_struct *dir_fsp,
3277 const struct smb_filename *smb_fname,
3278 const char *xattr_name,
3281 struct tevent_req *req = NULL;
3282 struct tevent_req *subreq = NULL;
3283 struct vfswrap_getxattrat_state *state = NULL;
3284 size_t max_threads = 0;
3285 bool have_per_thread_cwd = false;
3286 bool have_per_thread_creds = false;
3287 bool do_async = false;
3289 req = tevent_req_create(mem_ctx, &state,
3290 struct vfswrap_getxattrat_state);
3294 *state = (struct vfswrap_getxattrat_state) {
3297 .smb_fname = smb_fname,
3300 max_threads = pthreadpool_tevent_max_threads(dir_fsp->conn->sconn->pool);
3301 if (max_threads >= 1) {
3303 * We need a non sync threadpool!
3305 have_per_thread_cwd = per_thread_cwd_supported();
3307 #ifdef HAVE_LINUX_THREAD_CREDENTIALS
3308 have_per_thread_creds = true;
3310 if (have_per_thread_cwd && have_per_thread_creds) {
3314 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat, profile_p,
3315 state->profile_bytes, 0);
3317 if (dir_fsp->fh->fd == -1) {
3318 DBG_ERR("Need a valid directory fd\n");
3319 tevent_req_error(req, EINVAL);
3320 return tevent_req_post(req, ev);
3323 if (alloc_hint > 0) {
3324 state->xattr_value = talloc_zero_array(state,
3327 if (tevent_req_nomem(state->xattr_value, req)) {
3328 return tevent_req_post(req, ev);
3333 vfswrap_getxattrat_do_sync(req);
3334 return tevent_req_post(req, ev);
3338 * Now allocate all parameters from a memory context that won't go away
3339 * no matter what. These paremeters will get used in threads and we
3340 * can't reliably cancel threads, so all buffers passed to the threads
3341 * must not be freed before all referencing threads terminate.
3344 state->name = talloc_strdup(state, smb_fname->base_name);
3345 if (tevent_req_nomem(state->name, req)) {
3346 return tevent_req_post(req, ev);
3349 state->xattr_name = talloc_strdup(state, xattr_name);
3350 if (tevent_req_nomem(state->xattr_name, req)) {
3351 return tevent_req_post(req, ev);
3355 * This is a hot codepath so at first glance one might think we should
3356 * somehow optimize away the token allocation and do a
3357 * talloc_reference() or similar black magic instead. But due to the
3358 * talloc_stackframe pool per SMB2 request this should be a simple copy
3359 * without a malloc in most cases.
3361 if (geteuid() == sec_initial_uid()) {
3362 state->token = root_unix_token(state);
3364 state->token = copy_unix_token(
3366 dir_fsp->conn->session_info->unix_token);
3368 if (tevent_req_nomem(state->token, req)) {
3369 return tevent_req_post(req, ev);
3372 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3374 subreq = pthreadpool_tevent_job_send(
3377 dir_fsp->conn->sconn->pool,
3378 vfswrap_getxattrat_do_async,
3380 if (tevent_req_nomem(subreq, req)) {
3381 return tevent_req_post(req, ev);
3383 tevent_req_set_callback(subreq, vfswrap_getxattrat_done, req);
3385 talloc_set_destructor(state, vfswrap_getxattrat_state_destructor);
3390 static void vfswrap_getxattrat_do_sync(struct tevent_req *req)
3392 struct vfswrap_getxattrat_state *state = tevent_req_data(
3393 req, struct vfswrap_getxattrat_state);
3395 char *tofree = NULL;
3396 char pathbuf[PATH_MAX+1];
3400 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
3401 state->smb_fname->base_name,
3406 if (pathlen == -1) {
3407 tevent_req_error(req, ENOMEM);
3411 state->xattr_size = getxattr(path,
3414 talloc_array_length(state->xattr_value));
3416 TALLOC_FREE(tofree);
3417 if (state->xattr_size == -1) {
3418 tevent_req_error(req, err);
3422 tevent_req_done(req);
3426 static void vfswrap_getxattrat_do_async(void *private_data)
3428 struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3429 private_data, struct vfswrap_getxattrat_state);
3430 struct timespec start_time;
3431 struct timespec end_time;
3434 PROFILE_TIMESTAMP(&start_time);
3435 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
3438 * Here we simulate a getxattrat()
3439 * call using fchdir();getxattr()
3442 per_thread_cwd_activate();
3444 /* Become the correct credential on this thread. */
3445 ret = set_thread_credentials(state->token->uid,
3447 (size_t)state->token->ngroups,
3448 state->token->groups);
3450 state->xattr_size = -1;
3451 state->vfs_aio_state.error = errno;
3455 ret = fchdir(state->dir_fsp->fh->fd);
3457 state->xattr_size = -1;
3458 state->vfs_aio_state.error = errno;
3462 state->xattr_size = getxattr(state->name,
3465 talloc_array_length(state->xattr_value));
3466 if (state->xattr_size == -1) {
3467 state->vfs_aio_state.error = errno;
3471 PROFILE_TIMESTAMP(&end_time);
3472 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
3473 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3476 static void vfswrap_getxattrat_done(struct tevent_req *subreq)
3478 struct tevent_req *req = tevent_req_callback_data(
3479 subreq, struct tevent_req);
3480 struct vfswrap_getxattrat_state *state = tevent_req_data(
3481 req, struct vfswrap_getxattrat_state);
3486 * Make sure we run as the user again
3488 ok = change_to_user_and_service_by_fsp(state->dir_fsp);
3491 ret = pthreadpool_tevent_job_recv(subreq);
3492 TALLOC_FREE(subreq);
3493 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
3494 talloc_set_destructor(state, NULL);
3496 if (ret != EAGAIN) {
3497 tevent_req_error(req, ret);
3501 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
3502 * means the lower level pthreadpool failed to create a new
3503 * thread. Fallback to sync processing in that case to allow
3504 * some progress for the client.
3506 vfswrap_getxattrat_do_sync(req);
3510 if (state->xattr_size == -1) {
3511 tevent_req_error(req, state->vfs_aio_state.error);
3515 if (state->xattr_value == NULL) {
3517 * The caller only wanted the size.
3519 tevent_req_done(req);
3524 * shrink the buffer to the returned size.
3525 * (can't fail). It means NULL if size is 0.
3527 state->xattr_value = talloc_realloc(state,
3532 tevent_req_done(req);
3535 static ssize_t vfswrap_getxattrat_recv(struct tevent_req *req,
3536 struct vfs_aio_state *aio_state,
3537 TALLOC_CTX *mem_ctx,
3538 uint8_t **xattr_value)
3540 struct vfswrap_getxattrat_state *state = tevent_req_data(
3541 req, struct vfswrap_getxattrat_state);
3544 if (tevent_req_is_unix_error(req, &aio_state->error)) {
3545 tevent_req_received(req);
3549 *aio_state = state->vfs_aio_state;
3550 xattr_size = state->xattr_size;
3551 if (xattr_value != NULL) {
3552 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
3555 tevent_req_received(req);
3559 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
3561 return fgetxattr(fsp->fh->fd, name, value, size);
3564 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
3565 const struct smb_filename *smb_fname,
3569 return listxattr(smb_fname->base_name, list, size);
3572 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
3574 return flistxattr(fsp->fh->fd, list, size);
3577 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
3578 const struct smb_filename *smb_fname,
3581 return removexattr(smb_fname->base_name, name);
3584 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
3586 return fremovexattr(fsp->fh->fd, name);
3589 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
3590 const struct smb_filename *smb_fname,
3596 return setxattr(smb_fname->base_name, name, value, size, flags);
3599 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
3601 return fsetxattr(fsp->fh->fd, name, value, size, flags);
3604 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
3609 static bool vfswrap_is_offline(struct connection_struct *conn,
3610 const struct smb_filename *fname)
3614 bool offline = false;
3616 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
3620 if (!lp_dmapi_support(SNUM(conn)) || !dmapi_have_session()) {
3621 #if defined(ENOTSUP)
3627 status = get_full_smb_filename(talloc_tos(), fname, &path);
3628 if (!NT_STATUS_IS_OK(status)) {
3629 errno = map_errno_from_nt_status(status);
3633 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
3640 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
3641 struct files_struct *fsp,
3642 TALLOC_CTX *mem_ctx,
3645 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
3648 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
3649 struct files_struct *fsp,
3650 const DATA_BLOB old_cookie,
3651 TALLOC_CTX *mem_ctx,
3652 DATA_BLOB *new_cookie)
3654 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
3658 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
3659 struct smb_request *smb1req,
3660 struct smbXsrv_open *op,
3661 const DATA_BLOB old_cookie,
3662 TALLOC_CTX *mem_ctx,
3663 struct files_struct **fsp,
3664 DATA_BLOB *new_cookie)
3666 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
3667 old_cookie, mem_ctx,
3671 static struct vfs_fn_pointers vfs_default_fns = {
3672 /* Disk operations */
3674 .connect_fn = vfswrap_connect,
3675 .disconnect_fn = vfswrap_disconnect,
3676 .disk_free_fn = vfswrap_disk_free,
3677 .get_quota_fn = vfswrap_get_quota,
3678 .set_quota_fn = vfswrap_set_quota,
3679 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3680 .statvfs_fn = vfswrap_statvfs,
3681 .fs_capabilities_fn = vfswrap_fs_capabilities,
3682 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3683 .create_dfs_pathat_fn = vfswrap_create_dfs_pathat,
3684 .read_dfs_pathat_fn = vfswrap_read_dfs_pathat,
3685 .snap_check_path_fn = vfswrap_snap_check_path,
3686 .snap_create_fn = vfswrap_snap_create,
3687 .snap_delete_fn = vfswrap_snap_delete,
3689 /* Directory operations */
3691 .fdopendir_fn = vfswrap_fdopendir,
3692 .readdir_fn = vfswrap_readdir,
3693 .readdir_attr_fn = vfswrap_readdir_attr,
3694 .seekdir_fn = vfswrap_seekdir,
3695 .telldir_fn = vfswrap_telldir,
3696 .rewind_dir_fn = vfswrap_rewinddir,
3697 .mkdirat_fn = vfswrap_mkdirat,
3698 .closedir_fn = vfswrap_closedir,
3700 /* File operations */
3702 .openat_fn = vfswrap_openat,
3703 .create_file_fn = vfswrap_create_file,
3704 .close_fn = vfswrap_close,
3705 .pread_fn = vfswrap_pread,
3706 .pread_send_fn = vfswrap_pread_send,
3707 .pread_recv_fn = vfswrap_pread_recv,
3708 .pwrite_fn = vfswrap_pwrite,
3709 .pwrite_send_fn = vfswrap_pwrite_send,
3710 .pwrite_recv_fn = vfswrap_pwrite_recv,
3711 .lseek_fn = vfswrap_lseek,
3712 .sendfile_fn = vfswrap_sendfile,
3713 .recvfile_fn = vfswrap_recvfile,
3714 .renameat_fn = vfswrap_renameat,
3715 .fsync_send_fn = vfswrap_fsync_send,
3716 .fsync_recv_fn = vfswrap_fsync_recv,
3717 .stat_fn = vfswrap_stat,
3718 .fstat_fn = vfswrap_fstat,
3719 .lstat_fn = vfswrap_lstat,
3720 .get_alloc_size_fn = vfswrap_get_alloc_size,
3721 .unlinkat_fn = vfswrap_unlinkat,
3722 .chmod_fn = vfswrap_chmod,
3723 .fchmod_fn = vfswrap_fchmod,
3724 .fchown_fn = vfswrap_fchown,
3725 .lchown_fn = vfswrap_lchown,
3726 .chdir_fn = vfswrap_chdir,
3727 .getwd_fn = vfswrap_getwd,
3728 .ntimes_fn = vfswrap_ntimes,
3729 .ftruncate_fn = vfswrap_ftruncate,
3730 .fallocate_fn = vfswrap_fallocate,
3731 .lock_fn = vfswrap_lock,
3732 .kernel_flock_fn = vfswrap_kernel_flock,
3733 .fcntl_fn = vfswrap_fcntl,
3734 .linux_setlease_fn = vfswrap_linux_setlease,
3735 .getlock_fn = vfswrap_getlock,
3736 .symlinkat_fn = vfswrap_symlinkat,
3737 .readlinkat_fn = vfswrap_readlinkat,
3738 .linkat_fn = vfswrap_linkat,
3739 .mknodat_fn = vfswrap_mknodat,
3740 .realpath_fn = vfswrap_realpath,
3741 .chflags_fn = vfswrap_chflags,
3742 .file_id_create_fn = vfswrap_file_id_create,
3743 .fs_file_id_fn = vfswrap_fs_file_id,
3744 .streaminfo_fn = vfswrap_streaminfo,
3745 .get_real_filename_fn = vfswrap_get_real_filename,
3746 .connectpath_fn = vfswrap_connectpath,
3747 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
3748 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3749 .strict_lock_check_fn = vfswrap_strict_lock_check,
3750 .translate_name_fn = vfswrap_translate_name,
3751 .fsctl_fn = vfswrap_fsctl,
3752 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
3753 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
3754 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
3755 .get_dos_attributes_send_fn = vfswrap_get_dos_attributes_send,
3756 .get_dos_attributes_recv_fn = vfswrap_get_dos_attributes_recv,
3757 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
3758 .offload_read_send_fn = vfswrap_offload_read_send,
3759 .offload_read_recv_fn = vfswrap_offload_read_recv,
3760 .offload_write_send_fn = vfswrap_offload_write_send,
3761 .offload_write_recv_fn = vfswrap_offload_write_recv,
3762 .get_compression_fn = vfswrap_get_compression,
3763 .set_compression_fn = vfswrap_set_compression,
3765 /* NT ACL operations. */
3767 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
3768 .get_nt_acl_at_fn = vfswrap_get_nt_acl_at,
3769 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
3770 .audit_file_fn = vfswrap_audit_file,
3772 /* POSIX ACL operations. */
3774 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
3775 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3776 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
3777 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3778 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
3779 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3780 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
3782 /* EA operations. */
3783 .getxattr_fn = vfswrap_getxattr,
3784 .getxattrat_send_fn = vfswrap_getxattrat_send,
3785 .getxattrat_recv_fn = vfswrap_getxattrat_recv,
3786 .fgetxattr_fn = vfswrap_fgetxattr,
3787 .listxattr_fn = vfswrap_listxattr,
3788 .flistxattr_fn = vfswrap_flistxattr,
3789 .removexattr_fn = vfswrap_removexattr,
3790 .fremovexattr_fn = vfswrap_fremovexattr,
3791 .setxattr_fn = vfswrap_setxattr,
3792 .fsetxattr_fn = vfswrap_fsetxattr,
3794 /* aio operations */
3795 .aio_force_fn = vfswrap_aio_force,
3797 /* durable handle operations */
3798 .durable_cookie_fn = vfswrap_durable_cookie,
3799 .durable_disconnect_fn = vfswrap_durable_disconnect,
3800 .durable_reconnect_fn = vfswrap_durable_reconnect,
3804 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3807 * Here we need to implement every call!
3809 * As this is the end of the vfs module chain.
3811 smb_vfs_assert_all_fns(&vfs_default_fns, DEFAULT_VFS_MODULE_NAME);
3812 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3813 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);