2 Unix SMB/CIFS implementation.
3 Wrap disk only vfs functions to sidestep dodgy compilers.
4 Copyright (C) Tim Potter 1998
5 Copyright (C) Jeremy Allison 2007
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "system/time.h"
23 #include "system/filesys.h"
24 #include "smbd/smbd.h"
25 #include "smbd/globals.h"
27 #include "smbprofile.h"
28 #include "../libcli/security/security.h"
29 #include "passdb/lookup_sid.h"
30 #include "source3/include/msdfs.h"
31 #include "librpc/gen_ndr/ndr_dfsblobs.h"
32 #include "lib/util/tevent_unix.h"
33 #include "lib/util/tevent_ntstatus.h"
34 #include "lib/util/sys_rw.h"
35 #include "lib/pthreadpool/pthreadpool_tevent.h"
36 #include "librpc/gen_ndr/ndr_ioctl.h"
37 #include "offload_token.h"
38 #include "util_reparse.h"
39 #include "lib/util/string_wrappers.h"
42 #define DBGC_CLASS DBGC_VFS
44 /* Check for NULL pointer parameters in vfswrap_* functions */
46 /* We don't want to have NULL function pointers lying around. Someone
47 is sure to try and execute them. These stubs are used to prevent
50 static int vfswrap_connect(vfs_handle_struct *handle, const char *service, const char *user)
52 handle->conn->have_proc_fds = sys_have_proc_fds();
53 return 0; /* Return >= 0 for success */
56 static void vfswrap_disconnect(vfs_handle_struct *handle)
62 static uint64_t vfswrap_disk_free(vfs_handle_struct *handle,
63 const struct smb_filename *smb_fname,
68 if (sys_fsusage(smb_fname->base_name, dfree, dsize) != 0) {
76 static int vfswrap_get_quota(struct vfs_handle_struct *handle,
77 const struct smb_filename *smb_fname,
78 enum SMB_QUOTA_TYPE qtype,
82 #ifdef HAVE_SYS_QUOTAS
85 START_PROFILE(syscall_get_quota);
86 result = sys_get_quota(smb_fname->base_name, qtype, id, qt);
87 END_PROFILE(syscall_get_quota);
95 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
97 #ifdef HAVE_SYS_QUOTAS
100 START_PROFILE(syscall_set_quota);
101 result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
102 END_PROFILE(syscall_set_quota);
110 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
111 struct files_struct *fsp,
112 struct shadow_copy_data *shadow_copy_data,
116 return -1; /* Not implemented. */
119 static int vfswrap_statvfs(struct vfs_handle_struct *handle,
120 const struct smb_filename *smb_fname,
121 vfs_statvfs_struct *statbuf)
123 return sys_statvfs(smb_fname->base_name, statbuf);
126 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
127 enum timestamp_set_resolution *p_ts_res)
129 const struct loadparm_substitution *lp_sub =
130 loadparm_s3_global_substitution();
131 connection_struct *conn = handle->conn;
132 uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
133 struct smb_filename *smb_fname_cpath = NULL;
134 struct vfs_statvfs_struct statbuf;
137 smb_fname_cpath = synthetic_smb_fname(talloc_tos(),
143 if (smb_fname_cpath == NULL) {
147 ZERO_STRUCT(statbuf);
148 ret = SMB_VFS_STATVFS(conn, smb_fname_cpath, &statbuf);
150 caps = statbuf.FsCapabilities;
153 *p_ts_res = TIMESTAMP_SET_SECONDS;
155 /* Work out what timestamp resolution we can
156 * use when setting a timestamp. */
158 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
160 TALLOC_FREE(smb_fname_cpath);
164 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
165 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
166 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
167 /* If any of the normal UNIX directory timestamps
168 * have a non-zero tv_nsec component assume
169 * we might be able to set sub-second timestamps.
170 * See what filetime set primitives we have.
172 #if defined(HAVE_UTIMENSAT)
173 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
174 #elif defined(HAVE_UTIMES)
175 /* utimes allows msec timestamps to be set. */
176 *p_ts_res = TIMESTAMP_SET_MSEC;
177 #elif defined(HAVE_UTIME)
178 /* utime only allows sec timestamps to be set. */
179 *p_ts_res = TIMESTAMP_SET_SECONDS;
182 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
184 "available on share %s, directory %s\n",
185 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
186 lp_servicename(talloc_tos(), lp_sub, conn->params->service),
187 conn->connectpath ));
189 TALLOC_FREE(smb_fname_cpath);
193 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
194 struct dfs_GetDFSReferral *r)
196 struct junction_map *junction = NULL;
198 bool self_referral = false;
199 char *pathnamep = NULL;
200 char *local_dfs_path = NULL;
203 uint16_t max_referral_level = r->in.req.max_referral_level;
206 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
209 /* get the junction entry */
210 if (r->in.req.servername == NULL) {
211 return NT_STATUS_NOT_FOUND;
215 * Trim pathname sent by client so it begins with only one backslash.
216 * Two backslashes confuse some dfs clients
219 local_dfs_path = talloc_strdup(r, r->in.req.servername);
220 if (local_dfs_path == NULL) {
221 return NT_STATUS_NO_MEMORY;
223 pathnamep = local_dfs_path;
224 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
225 IS_DIRECTORY_SEP(pathnamep[1])) {
229 junction = talloc_zero(r, struct junction_map);
230 if (junction == NULL) {
231 return NT_STATUS_NO_MEMORY;
234 /* The following call can change cwd. */
235 status = get_referred_path(r,
236 handle->conn->session_info,
238 handle->conn->sconn->remote_address,
239 handle->conn->sconn->local_address,
240 !handle->conn->sconn->using_smb2,
241 junction, &consumedcnt, &self_referral);
242 if (!NT_STATUS_IS_OK(status)) {
243 struct smb_filename connectpath_fname = {
244 .base_name = handle->conn->connectpath
246 vfs_ChDir(handle->conn, &connectpath_fname);
250 struct smb_filename connectpath_fname = {
251 .base_name = handle->conn->connectpath
253 vfs_ChDir(handle->conn, &connectpath_fname);
256 if (!self_referral) {
257 pathnamep[consumedcnt] = '\0';
260 dbgtext("Path %s to alternate path(s):",
262 for (i=0; i < junction->referral_count; i++) {
264 junction->referral_list[i].alternate_path);
270 if (r->in.req.max_referral_level <= 2) {
271 max_referral_level = 2;
273 if (r->in.req.max_referral_level >= 3) {
274 max_referral_level = 3;
277 r->out.resp = talloc_zero(r, struct dfs_referral_resp);
278 if (r->out.resp == NULL) {
279 return NT_STATUS_NO_MEMORY;
282 r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
283 r->out.resp->nb_referrals = junction->referral_count;
285 r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
287 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
290 r->out.resp->referral_entries = talloc_zero_array(r,
291 struct dfs_referral_type,
292 r->out.resp->nb_referrals);
293 if (r->out.resp->referral_entries == NULL) {
294 return NT_STATUS_NO_MEMORY;
297 switch (max_referral_level) {
299 for(i=0; i < junction->referral_count; i++) {
300 struct referral *ref = &junction->referral_list[i];
301 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
302 struct dfs_referral_type *t =
303 &r->out.resp->referral_entries[i];
304 struct dfs_referral_v2 *v2 = &t->referral.v2;
307 v2->size = VERSION2_REFERRAL_SIZE;
309 v2->server_type = DFS_SERVER_ROOT;
311 v2->server_type = DFS_SERVER_NON_ROOT;
314 v2->proximity = ref->proximity;
316 v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
317 if (v2->DFS_path == NULL) {
318 return NT_STATUS_NO_MEMORY;
320 v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
321 if (v2->DFS_alt_path == NULL) {
322 return NT_STATUS_NO_MEMORY;
324 v2->netw_address = talloc_strdup(mem_ctx,
325 ref->alternate_path);
326 if (v2->netw_address == NULL) {
327 return NT_STATUS_NO_MEMORY;
333 for(i=0; i < junction->referral_count; i++) {
334 struct referral *ref = &junction->referral_list[i];
335 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
336 struct dfs_referral_type *t =
337 &r->out.resp->referral_entries[i];
338 struct dfs_referral_v3 *v3 = &t->referral.v3;
339 struct dfs_normal_referral *r1 = &v3->referrals.r1;
342 v3->size = VERSION3_REFERRAL_SIZE;
344 v3->server_type = DFS_SERVER_ROOT;
346 v3->server_type = DFS_SERVER_NON_ROOT;
350 r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
351 if (r1->DFS_path == NULL) {
352 return NT_STATUS_NO_MEMORY;
354 r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
355 if (r1->DFS_alt_path == NULL) {
356 return NT_STATUS_NO_MEMORY;
358 r1->netw_address = talloc_strdup(mem_ctx,
359 ref->alternate_path);
360 if (r1->netw_address == NULL) {
361 return NT_STATUS_NO_MEMORY;
366 DEBUG(0,("Invalid dfs referral version: %d\n",
367 max_referral_level));
368 return NT_STATUS_INVALID_LEVEL;
372 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
378 static NTSTATUS vfswrap_create_dfs_pathat(struct vfs_handle_struct *handle,
379 struct files_struct *dirfsp,
380 const struct smb_filename *smb_fname,
381 const struct referral *reflist,
382 size_t referral_count)
384 TALLOC_CTX *frame = talloc_stackframe();
385 NTSTATUS status = NT_STATUS_NO_MEMORY;
387 char *msdfs_link = NULL;
389 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
391 /* Form the msdfs_link contents */
392 msdfs_link = msdfs_link_string(frame,
395 if (msdfs_link == NULL) {
399 ret = symlinkat(msdfs_link,
400 fsp_get_io_fd(dirfsp),
401 smb_fname->base_name);
403 status = NT_STATUS_OK;
405 status = map_nt_error_from_unix(errno);
415 * Read and return the contents of a DFS redirect given a
416 * pathname. A caller can pass in NULL for ppreflist and
417 * preferral_count but still determine if this was a
418 * DFS redirect point by getting NT_STATUS_OK back
419 * without incurring the overhead of reading and parsing
420 * the referral contents.
423 static NTSTATUS vfswrap_read_dfs_pathat(struct vfs_handle_struct *handle,
425 struct files_struct *dirfsp,
426 struct smb_filename *smb_fname,
427 struct referral **ppreflist,
428 size_t *preferral_count)
430 NTSTATUS status = NT_STATUS_NO_MEMORY;
432 char *link_target = NULL;
435 #if defined(HAVE_BROKEN_READLINK)
436 char link_target_buf[PATH_MAX];
438 char link_target_buf[7];
442 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
444 if (is_named_stream(smb_fname)) {
445 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
449 if (ppreflist == NULL && preferral_count == NULL) {
451 * We're only checking if this is a DFS
452 * redirect. We don't need to return data.
454 bufsize = sizeof(link_target_buf);
455 link_target = link_target_buf;
458 link_target = talloc_array(mem_ctx, char, bufsize);
464 referral_len = readlinkat(fsp_get_io_fd(dirfsp),
465 smb_fname->base_name,
468 if (referral_len == -1) {
469 if (errno == EINVAL) {
471 * If the path isn't a link, readlinkat
472 * returns EINVAL. Allow the caller to
475 DBG_INFO("%s is not a link.\n", smb_fname->base_name);
476 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
478 status = map_nt_error_from_unix(errno);
479 DBG_ERR("Error reading "
480 "msdfs link %s: %s\n",
481 smb_fname->base_name,
486 link_target[referral_len] = '\0';
488 DBG_INFO("%s -> %s\n",
489 smb_fname->base_name,
492 if (!strnequal(link_target, "msdfs:", 6)) {
493 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
497 ret = sys_lstat(smb_fname->base_name,
499 lp_fake_directory_create_times(SNUM(handle->conn)));
501 status = map_nt_error_from_unix(errno);
505 if (ppreflist == NULL && preferral_count == NULL) {
506 /* Early return for checking if this is a DFS link. */
510 ok = parse_msdfs_symlink(mem_ctx,
511 lp_msdfs_shuffle_referrals(SNUM(handle->conn)),
517 status = NT_STATUS_OK;
519 status = NT_STATUS_NO_MEMORY;
524 if (link_target != link_target_buf) {
525 TALLOC_FREE(link_target);
530 static NTSTATUS vfswrap_snap_check_path(struct vfs_handle_struct *handle,
532 const char *service_path,
535 return NT_STATUS_NOT_SUPPORTED;
538 static NTSTATUS vfswrap_snap_create(struct vfs_handle_struct *handle,
540 const char *base_volume,
546 return NT_STATUS_NOT_SUPPORTED;
549 static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle,
554 return NT_STATUS_NOT_SUPPORTED;
557 /* Directory operations */
559 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
566 START_PROFILE(syscall_fdopendir);
567 result = sys_fdopendir(fsp_get_io_fd(fsp));
568 END_PROFILE(syscall_fdopendir);
573 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
575 SMB_STRUCT_STAT *sbuf)
577 struct dirent *result;
579 START_PROFILE(syscall_readdir);
580 result = readdir(dirp);
581 END_PROFILE(syscall_readdir);
583 /* Default Posix readdir() does not give us stat info.
584 * Set to invalid to indicate we didn't return this info. */
585 SET_STAT_INVALID(*sbuf);
586 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
587 if (result != NULL) {
588 /* See if we can efficiently return this. */
590 int flags = AT_SYMLINK_NOFOLLOW;
591 int ret = fstatat(dirfd(dirp),
596 * As this is an optimization,
597 * ignore it if we stat'ed a
598 * symlink. Make the caller
599 * do it again as we don't
600 * know if they wanted the link
601 * info, or its target info.
603 if ((ret == 0) && (!S_ISLNK(st.st_mode))) {
604 init_stat_ex_from_stat(sbuf,
606 lp_fake_directory_create_times(
607 SNUM(handle->conn)));
615 static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
616 const struct smb_filename *fname,
618 struct readdir_attr_data **attr_data)
620 return NT_STATUS_NOT_SUPPORTED;
623 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
625 START_PROFILE(syscall_seekdir);
626 seekdir(dirp, offset);
627 END_PROFILE(syscall_seekdir);
630 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
633 START_PROFILE(syscall_telldir);
634 result = telldir(dirp);
635 END_PROFILE(syscall_telldir);
639 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
641 START_PROFILE(syscall_rewinddir);
643 END_PROFILE(syscall_rewinddir);
646 static int vfswrap_mkdirat(vfs_handle_struct *handle,
647 struct files_struct *dirfsp,
648 const struct smb_filename *smb_fname,
652 struct smb_filename *parent = NULL;
655 START_PROFILE(syscall_mkdirat);
657 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
659 if (lp_inherit_acls(SNUM(handle->conn))) {
660 ok = parent_smb_fname(talloc_tos(), smb_fname, &parent, NULL);
661 if (ok && directory_has_default_acl(handle->conn,
665 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
671 result = mkdirat(fsp_get_pathref_fd(dirfsp), smb_fname->base_name, mode);
673 END_PROFILE(syscall_mkdirat);
677 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
681 START_PROFILE(syscall_closedir);
682 result = closedir(dirp);
683 END_PROFILE(syscall_closedir);
687 /* File operations */
689 static int vfswrap_openat(vfs_handle_struct *handle,
690 const struct files_struct *dirfsp,
691 const struct smb_filename *smb_fname,
696 bool have_opath = false;
697 bool became_root = false;
700 START_PROFILE(syscall_openat);
702 if (is_named_stream(smb_fname)) {
710 if (fsp->fsp_flags.is_pathref) {
715 if (fsp->fsp_flags.is_pathref && !have_opath) {
720 result = openat(fsp_get_pathref_fd(dirfsp),
721 smb_fname->base_name,
729 fsp->fsp_flags.have_proc_fds = fsp->conn->have_proc_fds;
732 END_PROFILE(syscall_openat);
735 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
736 struct smb_request *req,
737 struct smb_filename *smb_fname,
738 uint32_t access_mask,
739 uint32_t share_access,
740 uint32_t create_disposition,
741 uint32_t create_options,
742 uint32_t file_attributes,
743 uint32_t oplock_request,
744 const struct smb2_lease *lease,
745 uint64_t allocation_size,
746 uint32_t private_flags,
747 struct security_descriptor *sd,
748 struct ea_list *ea_list,
749 files_struct **result,
751 const struct smb2_create_blobs *in_context_blobs,
752 struct smb2_create_blobs *out_context_blobs)
754 return create_file_default(handle->conn, req, smb_fname,
755 access_mask, share_access,
756 create_disposition, create_options,
757 file_attributes, oplock_request, lease,
758 allocation_size, private_flags,
760 pinfo, in_context_blobs, out_context_blobs);
763 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
767 START_PROFILE(syscall_close);
768 result = fd_close_posix(fsp);
769 END_PROFILE(syscall_close);
773 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
774 size_t n, off_t offset)
778 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
779 START_PROFILE_BYTES(syscall_pread, n);
780 result = sys_pread_full(fsp_get_io_fd(fsp), data, n, offset);
781 END_PROFILE_BYTES(syscall_pread);
783 if (result == -1 && errno == ESPIPE) {
784 /* Maintain the fiction that pipes can be seeked (sought?) on. */
785 result = sys_read(fsp_get_io_fd(fsp), data, n);
786 fh_set_pos(fsp->fh, 0);
789 #else /* HAVE_PREAD */
792 #endif /* HAVE_PREAD */
797 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
798 size_t n, off_t offset)
802 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
803 START_PROFILE_BYTES(syscall_pwrite, n);
804 result = sys_pwrite_full(fsp_get_io_fd(fsp), data, n, offset);
805 END_PROFILE_BYTES(syscall_pwrite);
807 if (result == -1 && errno == ESPIPE) {
808 /* Maintain the fiction that pipes can be sought on. */
809 result = sys_write(fsp_get_io_fd(fsp), data, n);
812 #else /* HAVE_PWRITE */
815 #endif /* HAVE_PWRITE */
820 struct vfswrap_pread_state {
827 struct vfs_aio_state vfs_aio_state;
828 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
831 static void vfs_pread_do(void *private_data);
832 static void vfs_pread_done(struct tevent_req *subreq);
833 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state);
835 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
837 struct tevent_context *ev,
838 struct files_struct *fsp,
840 size_t n, off_t offset)
842 struct tevent_req *req, *subreq;
843 struct vfswrap_pread_state *state;
845 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
851 state->fd = fsp_get_io_fd(fsp);
854 state->offset = offset;
856 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
857 state->profile_bytes, n);
858 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
860 subreq = pthreadpool_tevent_job_send(
861 state, ev, handle->conn->sconn->pool,
862 vfs_pread_do, state);
863 if (tevent_req_nomem(subreq, req)) {
864 return tevent_req_post(req, ev);
866 tevent_req_set_callback(subreq, vfs_pread_done, req);
868 talloc_set_destructor(state, vfs_pread_state_destructor);
873 static void vfs_pread_do(void *private_data)
875 struct vfswrap_pread_state *state = talloc_get_type_abort(
876 private_data, struct vfswrap_pread_state);
877 struct timespec start_time;
878 struct timespec end_time;
880 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
882 PROFILE_TIMESTAMP(&start_time);
884 state->ret = sys_pread_full(state->fd,
889 if (state->ret == -1) {
890 state->vfs_aio_state.error = errno;
893 PROFILE_TIMESTAMP(&end_time);
895 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
897 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
900 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state)
905 static void vfs_pread_done(struct tevent_req *subreq)
907 struct tevent_req *req = tevent_req_callback_data(
908 subreq, struct tevent_req);
909 struct vfswrap_pread_state *state = tevent_req_data(
910 req, struct vfswrap_pread_state);
913 ret = pthreadpool_tevent_job_recv(subreq);
915 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
916 talloc_set_destructor(state, NULL);
919 tevent_req_error(req, ret);
923 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
924 * means the lower level pthreadpool failed to create a new
925 * thread. Fallback to sync processing in that case to allow
926 * some progress for the client.
931 tevent_req_done(req);
934 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
935 struct vfs_aio_state *vfs_aio_state)
937 struct vfswrap_pread_state *state = tevent_req_data(
938 req, struct vfswrap_pread_state);
940 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
944 *vfs_aio_state = state->vfs_aio_state;
948 struct vfswrap_pwrite_state {
955 struct vfs_aio_state vfs_aio_state;
956 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
959 static void vfs_pwrite_do(void *private_data);
960 static void vfs_pwrite_done(struct tevent_req *subreq);
961 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state);
963 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
965 struct tevent_context *ev,
966 struct files_struct *fsp,
968 size_t n, off_t offset)
970 struct tevent_req *req, *subreq;
971 struct vfswrap_pwrite_state *state;
973 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
979 state->fd = fsp_get_io_fd(fsp);
982 state->offset = offset;
984 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
985 state->profile_bytes, n);
986 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
988 subreq = pthreadpool_tevent_job_send(
989 state, ev, handle->conn->sconn->pool,
990 vfs_pwrite_do, state);
991 if (tevent_req_nomem(subreq, req)) {
992 return tevent_req_post(req, ev);
994 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
996 talloc_set_destructor(state, vfs_pwrite_state_destructor);
1001 static void vfs_pwrite_do(void *private_data)
1003 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
1004 private_data, struct vfswrap_pwrite_state);
1005 struct timespec start_time;
1006 struct timespec end_time;
1008 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
1010 PROFILE_TIMESTAMP(&start_time);
1012 state->ret = sys_pwrite_full(state->fd,
1017 if (state->ret == -1) {
1018 state->vfs_aio_state.error = errno;
1021 PROFILE_TIMESTAMP(&end_time);
1023 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1025 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1028 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state)
1033 static void vfs_pwrite_done(struct tevent_req *subreq)
1035 struct tevent_req *req = tevent_req_callback_data(
1036 subreq, struct tevent_req);
1037 struct vfswrap_pwrite_state *state = tevent_req_data(
1038 req, struct vfswrap_pwrite_state);
1041 ret = pthreadpool_tevent_job_recv(subreq);
1042 TALLOC_FREE(subreq);
1043 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1044 talloc_set_destructor(state, NULL);
1046 if (ret != EAGAIN) {
1047 tevent_req_error(req, ret);
1051 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1052 * means the lower level pthreadpool failed to create a new
1053 * thread. Fallback to sync processing in that case to allow
1054 * some progress for the client.
1056 vfs_pwrite_do(state);
1059 tevent_req_done(req);
1062 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
1063 struct vfs_aio_state *vfs_aio_state)
1065 struct vfswrap_pwrite_state *state = tevent_req_data(
1066 req, struct vfswrap_pwrite_state);
1068 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1072 *vfs_aio_state = state->vfs_aio_state;
1076 struct vfswrap_fsync_state {
1080 struct vfs_aio_state vfs_aio_state;
1081 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
1084 static void vfs_fsync_do(void *private_data);
1085 static void vfs_fsync_done(struct tevent_req *subreq);
1086 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state);
1088 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
1089 TALLOC_CTX *mem_ctx,
1090 struct tevent_context *ev,
1091 struct files_struct *fsp)
1093 struct tevent_req *req, *subreq;
1094 struct vfswrap_fsync_state *state;
1096 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
1102 state->fd = fsp_get_io_fd(fsp);
1104 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_fsync, profile_p,
1105 state->profile_bytes, 0);
1106 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1108 subreq = pthreadpool_tevent_job_send(
1109 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
1110 if (tevent_req_nomem(subreq, req)) {
1111 return tevent_req_post(req, ev);
1113 tevent_req_set_callback(subreq, vfs_fsync_done, req);
1115 talloc_set_destructor(state, vfs_fsync_state_destructor);
1120 static void vfs_fsync_do(void *private_data)
1122 struct vfswrap_fsync_state *state = talloc_get_type_abort(
1123 private_data, struct vfswrap_fsync_state);
1124 struct timespec start_time;
1125 struct timespec end_time;
1127 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
1129 PROFILE_TIMESTAMP(&start_time);
1132 state->ret = fsync(state->fd);
1133 } while ((state->ret == -1) && (errno == EINTR));
1135 if (state->ret == -1) {
1136 state->vfs_aio_state.error = errno;
1139 PROFILE_TIMESTAMP(&end_time);
1141 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1143 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1146 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state)
1151 static void vfs_fsync_done(struct tevent_req *subreq)
1153 struct tevent_req *req = tevent_req_callback_data(
1154 subreq, struct tevent_req);
1155 struct vfswrap_fsync_state *state = tevent_req_data(
1156 req, struct vfswrap_fsync_state);
1159 ret = pthreadpool_tevent_job_recv(subreq);
1160 TALLOC_FREE(subreq);
1161 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1162 talloc_set_destructor(state, NULL);
1164 if (ret != EAGAIN) {
1165 tevent_req_error(req, ret);
1169 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1170 * means the lower level pthreadpool failed to create a new
1171 * thread. Fallback to sync processing in that case to allow
1172 * some progress for the client.
1174 vfs_fsync_do(state);
1177 tevent_req_done(req);
1180 static int vfswrap_fsync_recv(struct tevent_req *req,
1181 struct vfs_aio_state *vfs_aio_state)
1183 struct vfswrap_fsync_state *state = tevent_req_data(
1184 req, struct vfswrap_fsync_state);
1186 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1190 *vfs_aio_state = state->vfs_aio_state;
1194 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1198 START_PROFILE(syscall_lseek);
1200 result = lseek(fsp_get_io_fd(fsp), offset, whence);
1202 * We want to maintain the fiction that we can seek
1203 * on a fifo for file system purposes. This allows
1204 * people to set up UNIX fifo's that feed data to Windows
1205 * applications. JRA.
1208 if((result == -1) && (errno == ESPIPE)) {
1213 END_PROFILE(syscall_lseek);
1217 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1218 off_t offset, size_t n)
1222 START_PROFILE_BYTES(syscall_sendfile, n);
1223 result = sys_sendfile(tofd, fsp_get_io_fd(fromfsp), hdr, offset, n);
1224 END_PROFILE_BYTES(syscall_sendfile);
1228 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1230 files_struct *tofsp,
1236 START_PROFILE_BYTES(syscall_recvfile, n);
1237 result = sys_recvfile(fromfd, fsp_get_io_fd(tofsp), offset, n);
1238 END_PROFILE_BYTES(syscall_recvfile);
1242 static int vfswrap_renameat(vfs_handle_struct *handle,
1243 files_struct *srcfsp,
1244 const struct smb_filename *smb_fname_src,
1245 files_struct *dstfsp,
1246 const struct smb_filename *smb_fname_dst)
1250 START_PROFILE(syscall_renameat);
1252 if (is_named_stream(smb_fname_src) || is_named_stream(smb_fname_dst)) {
1257 result = renameat(fsp_get_pathref_fd(srcfsp),
1258 smb_fname_src->base_name,
1259 fsp_get_pathref_fd(dstfsp),
1260 smb_fname_dst->base_name);
1263 END_PROFILE(syscall_renameat);
1267 static int vfswrap_stat(vfs_handle_struct *handle,
1268 struct smb_filename *smb_fname)
1272 START_PROFILE(syscall_stat);
1274 if (is_named_stream(smb_fname)) {
1279 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1280 lp_fake_directory_create_times(SNUM(handle->conn)));
1282 END_PROFILE(syscall_stat);
1286 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1290 START_PROFILE(syscall_fstat);
1291 result = sys_fstat(fsp_get_pathref_fd(fsp),
1292 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1293 END_PROFILE(syscall_fstat);
1297 static int vfswrap_lstat(vfs_handle_struct *handle,
1298 struct smb_filename *smb_fname)
1302 START_PROFILE(syscall_lstat);
1304 if (is_named_stream(smb_fname)) {
1309 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1310 lp_fake_directory_create_times(SNUM(handle->conn)));
1312 END_PROFILE(syscall_lstat);
1316 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1318 enum vfs_translate_direction direction,
1319 TALLOC_CTX *mem_ctx,
1322 return NT_STATUS_NONE_MAPPED;
1326 * Implement the default fsctl operation.
1328 static bool vfswrap_logged_ioctl_message = false;
1330 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1331 struct files_struct *fsp,
1334 uint16_t req_flags, /* Needed for UNICODE ... */
1335 const uint8_t *_in_data,
1337 uint8_t **_out_data,
1338 uint32_t max_out_len,
1341 const char *in_data = (const char *)_in_data;
1342 char **out_data = (char **)_out_data;
1346 case FSCTL_SET_SPARSE:
1348 bool set_sparse = true;
1350 if (in_len >= 1 && in_data[0] == 0) {
1354 status = file_set_sparse(handle->conn, fsp, set_sparse);
1356 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1357 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1358 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1359 nt_errstr(status)));
1364 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1366 unsigned char objid[16];
1367 char *return_data = NULL;
1369 /* This should return the object-id on this file.
1370 * I think I'll make this be the inode+dev. JRA.
1373 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1374 fsp_fnum_dbg(fsp)));
1376 *out_len = MIN(max_out_len, 64);
1378 /* Hmmm, will this cause problems if less data asked for? */
1379 return_data = talloc_array(ctx, char, 64);
1380 if (return_data == NULL) {
1381 return NT_STATUS_NO_MEMORY;
1384 /* For backwards compatibility only store the dev/inode. */
1385 push_file_id_16(return_data, &fsp->file_id);
1386 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1387 push_file_id_16(return_data+32, &fsp->file_id);
1388 memset(return_data+48, 0, 16);
1389 *out_data = return_data;
1390 return NT_STATUS_OK;
1393 case FSCTL_GET_REPARSE_POINT:
1395 status = fsctl_get_reparse_point(
1396 fsp, ctx, out_data, max_out_len, out_len);
1400 case FSCTL_SET_REPARSE_POINT:
1402 status = fsctl_set_reparse_point(fsp, ctx, _in_data, in_len);
1406 case FSCTL_DELETE_REPARSE_POINT:
1408 status = fsctl_del_reparse_point(fsp, ctx, _in_data, in_len);
1412 case FSCTL_GET_SHADOW_COPY_DATA:
1415 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1416 * and return their volume names. If max_data_count is 16, then it is just
1417 * asking for the number of volumes and length of the combined names.
1419 * pdata is the data allocated by our caller, but that uses
1420 * total_data_count (which is 0 in our case) rather than max_data_count.
1421 * Allocate the correct amount and return the pointer to let
1422 * it be deallocated when we return.
1424 struct shadow_copy_data *shadow_data = NULL;
1425 bool labels = False;
1426 uint32_t labels_data_count = 0;
1428 char *cur_pdata = NULL;
1430 if (max_out_len < 16) {
1431 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1433 return NT_STATUS_INVALID_PARAMETER;
1436 if (max_out_len > 16) {
1440 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1441 if (shadow_data == NULL) {
1442 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1443 return NT_STATUS_NO_MEMORY;
1447 * Call the VFS routine to actually do the work.
1449 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1452 /* broken module didn't set errno on error */
1453 status = NT_STATUS_UNSUCCESSFUL;
1455 status = map_nt_error_from_unix(errno);
1456 if (NT_STATUS_EQUAL(status,
1457 NT_STATUS_NOT_SUPPORTED)) {
1461 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1462 "connectpath %s, failed - %s.\n",
1463 fsp->conn->connectpath,
1464 nt_errstr(status)));
1465 TALLOC_FREE(shadow_data);
1469 labels_data_count = (shadow_data->num_volumes * 2 *
1470 sizeof(SHADOW_COPY_LABEL)) + 2;
1475 *out_len = 12 + labels_data_count;
1478 if (max_out_len < *out_len) {
1479 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1480 max_out_len, *out_len));
1481 TALLOC_FREE(shadow_data);
1482 return NT_STATUS_BUFFER_TOO_SMALL;
1485 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1486 if (cur_pdata == NULL) {
1487 TALLOC_FREE(shadow_data);
1488 return NT_STATUS_NO_MEMORY;
1491 *out_data = cur_pdata;
1493 /* num_volumes 4 bytes */
1494 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1497 /* num_labels 4 bytes */
1498 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1501 /* needed_data_count 4 bytes */
1502 SIVAL(cur_pdata, 8, labels_data_count);
1506 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1507 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1508 if (labels && shadow_data->labels) {
1509 for (i=0; i<shadow_data->num_volumes; i++) {
1511 status = srvstr_push(cur_pdata, req_flags,
1512 cur_pdata, shadow_data->labels[i],
1513 2 * sizeof(SHADOW_COPY_LABEL),
1514 STR_UNICODE|STR_TERMINATE, &len);
1515 if (!NT_STATUS_IS_OK(status)) {
1516 TALLOC_FREE(*out_data);
1517 TALLOC_FREE(shadow_data);
1520 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1521 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1525 TALLOC_FREE(shadow_data);
1527 return NT_STATUS_OK;
1530 case FSCTL_FIND_FILES_BY_SID:
1532 /* pretend this succeeded -
1534 * we have to send back a list with all files owned by this SID
1536 * but I have to check that --metze
1540 struct dom_sid_buf buf;
1544 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1545 fsp_fnum_dbg(fsp)));
1548 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1549 return NT_STATUS_INVALID_PARAMETER;
1552 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1554 /* unknown 4 bytes: this is not the length of the sid :-( */
1555 /*unknown = IVAL(pdata,0);*/
1557 ret = sid_parse(_in_data + 4, sid_len, &sid);
1559 return NT_STATUS_INVALID_PARAMETER;
1561 DEBUGADD(10, ("for SID: %s\n",
1562 dom_sid_str_buf(&sid, &buf)));
1564 if (!sid_to_uid(&sid, &uid)) {
1565 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1566 dom_sid_str_buf(&sid, &buf),
1567 (unsigned long)sid_len));
1571 /* we can take a look at the find source :-)
1573 * find ./ -uid $uid -name '*' is what we need here
1576 * and send 4bytes len and then NULL terminated unicode strings
1579 * but I don't know how to deal with the paged results
1580 * (maybe we can hang the result anywhere in the fsp struct)
1582 * but I don't know how to deal with the paged results
1583 * (maybe we can hang the result anywhere in the fsp struct)
1585 * we don't send all files at once
1586 * and at the next we should *not* start from the beginning,
1587 * so we have to cache the result
1592 /* this works for now... */
1593 return NT_STATUS_OK;
1596 case FSCTL_QUERY_ALLOCATED_RANGES:
1598 /* FIXME: This is just a dummy reply, telling that all of the
1599 * file is allocated. MKS cp needs that.
1600 * Adding the real allocated ranges via FIEMAP on Linux
1601 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1602 * this FSCTL correct for sparse files.
1604 uint64_t offset, length;
1605 char *out_data_tmp = NULL;
1608 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1610 return NT_STATUS_INVALID_PARAMETER;
1613 if (max_out_len < 16) {
1614 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1616 return NT_STATUS_INVALID_PARAMETER;
1619 offset = BVAL(in_data,0);
1620 length = BVAL(in_data,8);
1622 if (offset + length < offset) {
1623 /* No 64-bit integer wrap. */
1624 return NT_STATUS_INVALID_PARAMETER;
1627 /* Shouldn't this be SMB_VFS_STAT ... ? */
1628 status = vfs_stat_fsp(fsp);
1629 if (!NT_STATUS_IS_OK(status)) {
1634 out_data_tmp = talloc_array(ctx, char, *out_len);
1635 if (out_data_tmp == NULL) {
1636 DEBUG(10, ("unable to allocate memory for response\n"));
1637 return NT_STATUS_NO_MEMORY;
1640 if (offset > fsp->fsp_name->st.st_ex_size ||
1641 fsp->fsp_name->st.st_ex_size == 0 ||
1643 memset(out_data_tmp, 0, *out_len);
1645 uint64_t end = offset + length;
1646 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1647 SBVAL(out_data_tmp, 0, 0);
1648 SBVAL(out_data_tmp, 8, end);
1651 *out_data = out_data_tmp;
1653 return NT_STATUS_OK;
1656 case FSCTL_IS_VOLUME_DIRTY:
1658 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1659 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1661 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1662 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1664 return NT_STATUS_INVALID_PARAMETER;
1669 * Only print once ... unfortunately there could be lots of
1670 * different FSCTLs that are called.
1672 if (!vfswrap_logged_ioctl_message) {
1673 vfswrap_logged_ioctl_message = true;
1674 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1675 __func__, function));
1679 return NT_STATUS_NOT_SUPPORTED;
1682 static bool vfswrap_is_offline(struct connection_struct *conn,
1683 const struct smb_filename *fname);
1685 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1686 struct smb_filename *smb_fname,
1691 offline = vfswrap_is_offline(handle->conn, smb_fname);
1693 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1696 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1699 struct vfswrap_get_dos_attributes_state {
1700 struct vfs_aio_state aio_state;
1701 connection_struct *conn;
1702 TALLOC_CTX *mem_ctx;
1703 struct tevent_context *ev;
1704 files_struct *dir_fsp;
1705 struct smb_filename *smb_fname;
1710 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq);
1712 static struct tevent_req *vfswrap_get_dos_attributes_send(
1713 TALLOC_CTX *mem_ctx,
1714 struct tevent_context *ev,
1715 struct vfs_handle_struct *handle,
1716 files_struct *dir_fsp,
1717 struct smb_filename *smb_fname)
1719 struct tevent_req *req = NULL;
1720 struct tevent_req *subreq = NULL;
1721 struct vfswrap_get_dos_attributes_state *state = NULL;
1723 req = tevent_req_create(mem_ctx, &state,
1724 struct vfswrap_get_dos_attributes_state);
1729 *state = (struct vfswrap_get_dos_attributes_state) {
1730 .conn = dir_fsp->conn,
1734 .smb_fname = smb_fname,
1737 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1741 SAMBA_XATTR_DOS_ATTRIB,
1743 if (tevent_req_nomem(subreq, req)) {
1744 return tevent_req_post(req, ev);
1746 tevent_req_set_callback(subreq,
1747 vfswrap_get_dos_attributes_getxattr_done,
1753 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq)
1755 struct tevent_req *req =
1756 tevent_req_callback_data(subreq,
1758 struct vfswrap_get_dos_attributes_state *state =
1759 tevent_req_data(req,
1760 struct vfswrap_get_dos_attributes_state);
1762 DATA_BLOB blob = {0};
1764 char *tofree = NULL;
1765 char pathbuf[PATH_MAX+1];
1767 struct smb_filename smb_fname;
1771 xattr_size = SMB_VFS_GETXATTRAT_RECV(subreq,
1775 TALLOC_FREE(subreq);
1776 if (xattr_size == -1) {
1777 status = map_nt_error_from_unix(state->aio_state.error);
1779 if (state->as_root) {
1780 tevent_req_nterror(req, status);
1783 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1784 tevent_req_nterror(req, status);
1788 state->as_root = true;
1791 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1795 SAMBA_XATTR_DOS_ATTRIB,
1798 if (tevent_req_nomem(subreq, req)) {
1801 tevent_req_set_callback(subreq,
1802 vfswrap_get_dos_attributes_getxattr_done,
1807 blob.length = xattr_size;
1809 status = parse_dos_attribute_blob(state->smb_fname,
1812 if (!NT_STATUS_IS_OK(status)) {
1813 tevent_req_nterror(req, status);
1817 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
1818 state->smb_fname->base_name,
1823 if (pathlen == -1) {
1824 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1828 smb_fname = (struct smb_filename) {
1830 .st = state->smb_fname->st,
1831 .flags = state->smb_fname->flags,
1832 .twrp = state->smb_fname->twrp,
1835 offline = vfswrap_is_offline(state->conn, &smb_fname);
1837 state->dosmode |= FILE_ATTRIBUTE_OFFLINE;
1839 TALLOC_FREE(tofree);
1841 tevent_req_done(req);
1845 static NTSTATUS vfswrap_get_dos_attributes_recv(struct tevent_req *req,
1846 struct vfs_aio_state *aio_state,
1849 struct vfswrap_get_dos_attributes_state *state =
1850 tevent_req_data(req,
1851 struct vfswrap_get_dos_attributes_state);
1854 if (tevent_req_is_nterror(req, &status)) {
1855 tevent_req_received(req);
1859 *aio_state = state->aio_state;
1860 *dosmode = state->dosmode;
1861 tevent_req_received(req);
1862 return NT_STATUS_OK;
1865 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1866 struct files_struct *fsp,
1871 offline = vfswrap_is_offline(handle->conn, fsp->fsp_name);
1873 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1876 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1879 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1880 const struct smb_filename *smb_fname,
1883 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1886 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1887 struct files_struct *fsp,
1890 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1893 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1895 struct vfswrap_offload_read_state {
1899 static struct tevent_req *vfswrap_offload_read_send(
1900 TALLOC_CTX *mem_ctx,
1901 struct tevent_context *ev,
1902 struct vfs_handle_struct *handle,
1903 struct files_struct *fsp,
1909 struct tevent_req *req = NULL;
1910 struct vfswrap_offload_read_state *state = NULL;
1913 req = tevent_req_create(mem_ctx, &state,
1914 struct vfswrap_offload_read_state);
1919 status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1920 &vfswrap_offload_ctx);
1921 if (tevent_req_nterror(req, status)) {
1922 return tevent_req_post(req, ev);
1925 if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1926 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1927 return tevent_req_post(req, ev);
1930 status = vfs_offload_token_create_blob(state, fsp, fsctl,
1932 if (tevent_req_nterror(req, status)) {
1933 return tevent_req_post(req, ev);
1936 status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1938 if (tevent_req_nterror(req, status)) {
1939 return tevent_req_post(req, ev);
1942 tevent_req_done(req);
1943 return tevent_req_post(req, ev);
1946 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
1947 struct vfs_handle_struct *handle,
1948 TALLOC_CTX *mem_ctx,
1951 struct vfswrap_offload_read_state *state = tevent_req_data(
1952 req, struct vfswrap_offload_read_state);
1955 if (tevent_req_is_nterror(req, &status)) {
1956 tevent_req_received(req);
1960 token->length = state->token.length;
1961 token->data = talloc_move(mem_ctx, &state->token.data);
1963 tevent_req_received(req);
1964 return NT_STATUS_OK;
1967 struct vfswrap_offload_write_state {
1969 bool read_lck_locked;
1970 bool write_lck_locked;
1972 struct tevent_context *src_ev;
1973 struct files_struct *src_fsp;
1975 struct tevent_context *dst_ev;
1976 struct files_struct *dst_fsp;
1980 size_t next_io_size;
1983 static void vfswrap_offload_write_cleanup(struct tevent_req *req,
1984 enum tevent_req_state req_state)
1986 struct vfswrap_offload_write_state *state = tevent_req_data(
1987 req, struct vfswrap_offload_write_state);
1990 if (state->dst_fsp == NULL) {
1994 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
1996 state->dst_fsp = NULL;
1999 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
2001 static struct tevent_req *vfswrap_offload_write_send(
2002 struct vfs_handle_struct *handle,
2003 TALLOC_CTX *mem_ctx,
2004 struct tevent_context *ev,
2007 off_t transfer_offset,
2008 struct files_struct *dest_fsp,
2012 struct tevent_req *req;
2013 struct vfswrap_offload_write_state *state = NULL;
2014 /* off_t is signed! */
2015 off_t max_offset = INT64_MAX - to_copy;
2016 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
2017 files_struct *src_fsp = NULL;
2021 req = tevent_req_create(mem_ctx, &state,
2022 struct vfswrap_offload_write_state);
2027 *state = (struct vfswrap_offload_write_state) {
2029 .src_off = transfer_offset,
2031 .dst_fsp = dest_fsp,
2032 .dst_off = dest_off,
2034 .remaining = to_copy,
2037 tevent_req_set_cleanup_fn(req, vfswrap_offload_write_cleanup);
2040 case FSCTL_SRV_COPYCHUNK:
2041 case FSCTL_SRV_COPYCHUNK_WRITE:
2044 case FSCTL_OFFLOAD_WRITE:
2045 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
2046 return tevent_req_post(req, ev);
2048 case FSCTL_DUP_EXTENTS_TO_FILE:
2049 DBG_DEBUG("COW clones not supported by vfs_default\n");
2050 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2051 return tevent_req_post(req, ev);
2054 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2055 return tevent_req_post(req, ev);
2059 * From here on we assume a copy-chunk fsctl
2063 tevent_req_done(req);
2064 return tevent_req_post(req, ev);
2067 if (state->src_off > max_offset) {
2069 * Protect integer checks below.
2071 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2072 return tevent_req_post(req, ev);
2074 if (state->src_off < 0) {
2076 * Protect integer checks below.
2078 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2079 return tevent_req_post(req, ev);
2081 if (state->dst_off > max_offset) {
2083 * Protect integer checks below.
2085 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2086 return tevent_req_post(req, ev);
2088 if (state->dst_off < 0) {
2090 * Protect integer checks below.
2092 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2093 return tevent_req_post(req, ev);
2096 status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
2098 if (tevent_req_nterror(req, status)) {
2099 return tevent_req_post(req, ev);
2102 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
2104 status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
2105 if (!NT_STATUS_IS_OK(status)) {
2106 tevent_req_nterror(req, status);
2107 return tevent_req_post(req, ev);
2110 ok = change_to_user_and_service_by_fsp(src_fsp);
2112 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2113 return tevent_req_post(req, ev);
2116 state->src_ev = src_fsp->conn->sconn->ev_ctx;
2117 state->src_fsp = src_fsp;
2119 status = vfs_stat_fsp(src_fsp);
2120 if (tevent_req_nterror(req, status)) {
2121 return tevent_req_post(req, ev);
2124 if (src_fsp->fsp_name->st.st_ex_size < state->src_off + to_copy) {
2126 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
2127 * If the SourceOffset or SourceOffset + Length extends beyond
2128 * the end of file, the server SHOULD<240> treat this as a
2129 * STATUS_END_OF_FILE error.
2131 * <240> Section 3.3.5.15.6: Windows servers will return
2132 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
2134 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
2135 return tevent_req_post(req, ev);
2138 state->buf = talloc_array(state, uint8_t, num);
2139 if (tevent_req_nomem(state->buf, req)) {
2140 return tevent_req_post(req, ev);
2143 status = vfswrap_offload_write_loop(req);
2144 if (!NT_STATUS_IS_OK(status)) {
2145 tevent_req_nterror(req, status);
2146 return tevent_req_post(req, ev);
2152 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
2154 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
2156 struct vfswrap_offload_write_state *state = tevent_req_data(
2157 req, struct vfswrap_offload_write_state);
2158 struct tevent_req *subreq = NULL;
2159 struct lock_struct read_lck;
2163 * This is called under the context of state->src_fsp.
2166 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
2168 init_strict_lock_struct(state->src_fsp,
2169 state->src_fsp->op->global->open_persistent_id,
2171 state->next_io_size,
2175 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
2179 return NT_STATUS_FILE_LOCK_CONFLICT;
2182 subreq = SMB_VFS_PREAD_SEND(state,
2186 state->next_io_size,
2188 if (subreq == NULL) {
2189 return NT_STATUS_NO_MEMORY;
2191 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
2193 return NT_STATUS_OK;
2196 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
2198 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
2200 struct tevent_req *req = tevent_req_callback_data(
2201 subreq, struct tevent_req);
2202 struct vfswrap_offload_write_state *state = tevent_req_data(
2203 req, struct vfswrap_offload_write_state);
2204 struct vfs_aio_state aio_state;
2205 struct lock_struct write_lck;
2209 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
2210 TALLOC_FREE(subreq);
2212 DBG_ERR("read failed: %s\n", strerror(aio_state.error));
2213 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2216 if (nread != state->next_io_size) {
2217 DBG_ERR("Short read, only %zd of %zu\n",
2218 nread, state->next_io_size);
2219 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2223 state->src_off += nread;
2225 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2227 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2231 init_strict_lock_struct(state->dst_fsp,
2232 state->dst_fsp->op->global->open_persistent_id,
2234 state->next_io_size,
2238 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
2242 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
2246 subreq = SMB_VFS_PWRITE_SEND(state,
2250 state->next_io_size,
2252 if (subreq == NULL) {
2253 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2256 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
2259 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
2261 struct tevent_req *req = tevent_req_callback_data(
2262 subreq, struct tevent_req);
2263 struct vfswrap_offload_write_state *state = tevent_req_data(
2264 req, struct vfswrap_offload_write_state);
2265 struct vfs_aio_state aio_state;
2270 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
2271 TALLOC_FREE(subreq);
2272 if (nwritten == -1) {
2273 DBG_ERR("write failed: %s\n", strerror(aio_state.error));
2274 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2277 if (nwritten != state->next_io_size) {
2278 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
2279 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2283 state->dst_off += nwritten;
2285 if (state->remaining < nwritten) {
2286 /* Paranoia check */
2287 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2290 state->remaining -= nwritten;
2291 if (state->remaining == 0) {
2292 tevent_req_done(req);
2296 ok = change_to_user_and_service_by_fsp(state->src_fsp);
2298 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2302 status = vfswrap_offload_write_loop(req);
2303 if (!NT_STATUS_IS_OK(status)) {
2304 tevent_req_nterror(req, status);
2311 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
2312 struct tevent_req *req,
2315 struct vfswrap_offload_write_state *state = tevent_req_data(
2316 req, struct vfswrap_offload_write_state);
2319 if (tevent_req_is_nterror(req, &status)) {
2320 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
2322 tevent_req_received(req);
2326 *copied = state->to_copy;
2327 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
2328 tevent_req_received(req);
2330 return NT_STATUS_OK;
2333 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
2334 TALLOC_CTX *mem_ctx,
2335 struct files_struct *fsp,
2336 struct smb_filename *smb_fname,
2337 uint16_t *_compression_fmt)
2339 return NT_STATUS_INVALID_DEVICE_REQUEST;
2342 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
2343 TALLOC_CTX *mem_ctx,
2344 struct files_struct *fsp,
2345 uint16_t compression_fmt)
2347 return NT_STATUS_INVALID_DEVICE_REQUEST;
2350 /********************************************************************
2351 Given a stat buffer return the allocated size on disk, taking into
2352 account sparse files.
2353 ********************************************************************/
2354 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
2355 struct files_struct *fsp,
2356 const SMB_STRUCT_STAT *sbuf)
2360 START_PROFILE(syscall_get_alloc_size);
2362 if(S_ISDIR(sbuf->st_ex_mode)) {
2367 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2368 /* The type of st_blocksize is blkcnt_t which *MUST* be
2369 signed (according to POSIX) and can be less than 64-bits.
2370 Ensure when we're converting to 64 bits wide we don't
2372 #if defined(SIZEOF_BLKCNT_T_8)
2373 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2374 #elif defined(SIZEOF_BLKCNT_T_4)
2376 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2377 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2380 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2384 * Some file systems do not allocate a block for very
2385 * small files. But for non-empty file should report a
2389 uint64_t filesize = get_file_size_stat(sbuf);
2391 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2395 result = get_file_size_stat(sbuf);
2398 if (fsp && fsp->initial_allocation_size)
2399 result = MAX(result,fsp->initial_allocation_size);
2401 result = smb_roundup(handle->conn, result);
2404 END_PROFILE(syscall_get_alloc_size);
2408 static int vfswrap_unlinkat(vfs_handle_struct *handle,
2409 struct files_struct *dirfsp,
2410 const struct smb_filename *smb_fname,
2415 START_PROFILE(syscall_unlinkat);
2417 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2419 if (is_named_stream(smb_fname)) {
2423 result = unlinkat(fsp_get_pathref_fd(dirfsp),
2424 smb_fname->base_name,
2428 END_PROFILE(syscall_unlinkat);
2432 static int vfswrap_chmod(vfs_handle_struct *handle,
2433 const struct smb_filename *smb_fname,
2438 START_PROFILE(syscall_chmod);
2439 result = chmod(smb_fname->base_name, mode);
2440 END_PROFILE(syscall_chmod);
2444 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2448 START_PROFILE(syscall_fchmod);
2449 #if defined(HAVE_FCHMOD)
2450 result = fchmod(fsp_get_io_fd(fsp), mode);
2456 END_PROFILE(syscall_fchmod);
2460 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2465 START_PROFILE(syscall_fchown);
2466 result = fchown(fsp_get_io_fd(fsp), uid, gid);
2467 END_PROFILE(syscall_fchown);
2475 static int vfswrap_lchown(vfs_handle_struct *handle,
2476 const struct smb_filename *smb_fname,
2482 START_PROFILE(syscall_lchown);
2483 result = lchown(smb_fname->base_name, uid, gid);
2484 END_PROFILE(syscall_lchown);
2488 static int vfswrap_chdir(vfs_handle_struct *handle,
2489 const struct smb_filename *smb_fname)
2493 START_PROFILE(syscall_chdir);
2494 result = chdir(smb_fname->base_name);
2495 END_PROFILE(syscall_chdir);
2499 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2503 struct smb_filename *smb_fname = NULL;
2505 START_PROFILE(syscall_getwd);
2506 result = sys_getwd();
2507 END_PROFILE(syscall_getwd);
2509 if (result == NULL) {
2512 smb_fname = synthetic_smb_fname(ctx,
2519 * sys_getwd() *always* returns malloced memory.
2520 * We must free here to avoid leaks:
2521 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2527 /*********************************************************************
2528 nsec timestamp resolution call. Convert down to whatever the underlying
2529 system will support.
2530 **********************************************************************/
2532 static int vfswrap_ntimes(vfs_handle_struct *handle,
2533 const struct smb_filename *smb_fname,
2534 struct smb_file_time *ft)
2538 START_PROFILE(syscall_ntimes);
2540 if (is_named_stream(smb_fname)) {
2546 if (is_omit_timespec(&ft->atime)) {
2547 ft->atime= smb_fname->st.st_ex_atime;
2550 if (is_omit_timespec(&ft->mtime)) {
2551 ft->mtime = smb_fname->st.st_ex_mtime;
2554 if (!is_omit_timespec(&ft->create_time)) {
2555 set_create_timespec_ea(handle->conn,
2560 if ((timespec_compare(&ft->atime,
2561 &smb_fname->st.st_ex_atime) == 0) &&
2562 (timespec_compare(&ft->mtime,
2563 &smb_fname->st.st_ex_mtime) == 0)) {
2568 #if defined(HAVE_UTIMENSAT)
2570 struct timespec ts[2];
2573 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2575 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2577 if (!((result == -1) && (errno == ENOSYS))) {
2581 #if defined(HAVE_UTIMES)
2583 struct timeval tv[2];
2584 tv[0] = convert_timespec_to_timeval(ft->atime);
2585 tv[1] = convert_timespec_to_timeval(ft->mtime);
2586 result = utimes(smb_fname->base_name, tv);
2588 result = utimes(smb_fname->base_name, NULL);
2590 if (!((result == -1) && (errno == ENOSYS))) {
2594 #if defined(HAVE_UTIME)
2596 struct utimbuf times;
2597 times.actime = convert_timespec_to_time_t(ft->atime);
2598 times.modtime = convert_timespec_to_time_t(ft->mtime);
2599 result = utime(smb_fname->base_name, ×);
2601 result = utime(smb_fname->base_name, NULL);
2603 if (!((result == -1) && (errno == ENOSYS))) {
2611 END_PROFILE(syscall_ntimes);
2615 /*********************************************************************
2616 A version of ftruncate that will write the space on disk if strict
2618 **********************************************************************/
2620 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2622 off_t space_to_write;
2623 uint64_t space_avail;
2624 uint64_t bsize,dfree,dsize;
2627 SMB_STRUCT_STAT *pst;
2630 ok = vfs_valid_pwrite_range(len, 0);
2636 status = vfs_stat_fsp(fsp);
2637 if (!NT_STATUS_IS_OK(status)) {
2640 pst = &fsp->fsp_name->st;
2643 if (S_ISFIFO(pst->st_ex_mode))
2647 if (pst->st_ex_size == len)
2650 /* Shrink - just ftruncate. */
2651 if (pst->st_ex_size > len)
2652 return ftruncate(fsp_get_io_fd(fsp), len);
2654 space_to_write = len - pst->st_ex_size;
2656 /* for allocation try fallocate first. This can fail on some
2657 platforms e.g. when the filesystem doesn't support it and no
2658 emulation is being done by the libc (like on AIX with JFS1). In that
2659 case we do our own emulation. fallocate implementations can
2660 return ENOTSUP or EINVAL in cases like that. */
2661 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2662 if (ret == -1 && errno == ENOSPC) {
2668 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2669 "error %d. Falling back to slow manual allocation\n", errno));
2671 /* available disk space is enough or not? */
2673 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2674 /* space_avail is 1k blocks */
2675 if (space_avail == (uint64_t)-1 ||
2676 ((uint64_t)space_to_write/1024 > space_avail) ) {
2681 /* Write out the real space on disk. */
2682 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2690 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2693 SMB_STRUCT_STAT *pst;
2697 START_PROFILE(syscall_ftruncate);
2699 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->fsp_flags.is_sparse) {
2700 result = strict_allocate_ftruncate(handle, fsp, len);
2701 END_PROFILE(syscall_ftruncate);
2705 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2706 ftruncate if the system supports it. Then I discovered that
2707 you can have some filesystems that support ftruncate
2708 expansion and some that don't! On Linux fat can't do
2709 ftruncate extend but ext2 can. */
2711 result = ftruncate(fsp_get_io_fd(fsp), len);
2713 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2714 extend a file with ftruncate. Provide alternate implementation
2717 /* Do an fstat to see if the file is longer than the requested
2718 size in which case the ftruncate above should have
2719 succeeded or shorter, in which case seek to len - 1 and
2720 write 1 byte of zero */
2721 status = vfs_stat_fsp(fsp);
2722 if (!NT_STATUS_IS_OK(status)) {
2726 /* We need to update the files_struct after successful ftruncate */
2731 pst = &fsp->fsp_name->st;
2734 if (S_ISFIFO(pst->st_ex_mode)) {
2740 if (pst->st_ex_size == len) {
2745 if (pst->st_ex_size > len) {
2746 /* the ftruncate should have worked */
2750 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2758 END_PROFILE(syscall_ftruncate);
2762 static int vfswrap_fallocate(vfs_handle_struct *handle,
2770 START_PROFILE(syscall_fallocate);
2772 result = sys_posix_fallocate(fsp_get_io_fd(fsp), offset, len);
2774 * posix_fallocate returns 0 on success, errno on error
2775 * and doesn't set errno. Make it behave like fallocate()
2776 * which returns -1, and sets errno on failure.
2783 /* sys_fallocate handles filtering of unsupported mode flags */
2784 result = sys_fallocate(fsp_get_io_fd(fsp), mode, offset, len);
2786 END_PROFILE(syscall_fallocate);
2790 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2794 START_PROFILE(syscall_fcntl_lock);
2796 if (fsp->fsp_flags.use_ofd_locks) {
2797 op = map_process_lock_to_ofd_lock(op);
2800 result = fcntl_lock(fsp_get_io_fd(fsp), op, offset, count, type);
2801 END_PROFILE(syscall_fcntl_lock);
2805 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2806 uint32_t share_access, uint32_t access_mask)
2808 START_PROFILE(syscall_kernel_flock);
2809 kernel_flock(fsp_get_io_fd(fsp), share_access, access_mask);
2810 END_PROFILE(syscall_kernel_flock);
2814 static int vfswrap_fcntl(vfs_handle_struct *handle, files_struct *fsp, int cmd,
2818 va_list dup_cmd_arg;
2822 START_PROFILE(syscall_fcntl);
2824 va_copy(dup_cmd_arg, cmd_arg);
2830 #if defined(HAVE_OFD_LOCKS)
2835 #if defined(HAVE_F_OWNER_EX)
2839 #if defined(HAVE_RW_HINTS)
2842 case F_GET_FILE_RW_HINT:
2843 case F_SET_FILE_RW_HINT:
2845 argp = va_arg(dup_cmd_arg, void *);
2846 result = sys_fcntl_ptr(fsp_get_io_fd(fsp), cmd, argp);
2849 val = va_arg(dup_cmd_arg, int);
2850 result = sys_fcntl_int(fsp_get_io_fd(fsp), cmd, val);
2853 va_end(dup_cmd_arg);
2855 END_PROFILE(syscall_fcntl);
2859 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2864 START_PROFILE(syscall_fcntl_getlock);
2866 if (fsp->fsp_flags.use_ofd_locks) {
2867 op = map_process_lock_to_ofd_lock(op);
2870 result = fcntl_getlock(fsp_get_io_fd(fsp), op, poffset, pcount, ptype, ppid);
2871 END_PROFILE(syscall_fcntl_getlock);
2875 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2880 START_PROFILE(syscall_linux_setlease);
2882 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2883 result = linux_setlease(fsp_get_io_fd(fsp), leasetype);
2887 END_PROFILE(syscall_linux_setlease);
2891 static int vfswrap_symlinkat(vfs_handle_struct *handle,
2892 const struct smb_filename *link_target,
2893 struct files_struct *dirfsp,
2894 const struct smb_filename *new_smb_fname)
2898 START_PROFILE(syscall_symlinkat);
2900 result = symlinkat(link_target->base_name,
2901 fsp_get_pathref_fd(dirfsp),
2902 new_smb_fname->base_name);
2903 END_PROFILE(syscall_symlinkat);
2907 static int vfswrap_readlinkat(vfs_handle_struct *handle,
2908 const struct files_struct *dirfsp,
2909 const struct smb_filename *smb_fname,
2915 START_PROFILE(syscall_readlinkat);
2917 result = readlinkat(fsp_get_pathref_fd(dirfsp),
2918 smb_fname->base_name,
2922 END_PROFILE(syscall_readlinkat);
2926 static int vfswrap_linkat(vfs_handle_struct *handle,
2927 files_struct *srcfsp,
2928 const struct smb_filename *old_smb_fname,
2929 files_struct *dstfsp,
2930 const struct smb_filename *new_smb_fname,
2935 START_PROFILE(syscall_linkat);
2937 result = linkat(fsp_get_pathref_fd(srcfsp),
2938 old_smb_fname->base_name,
2939 fsp_get_pathref_fd(dstfsp),
2940 new_smb_fname->base_name,
2943 END_PROFILE(syscall_linkat);
2947 static int vfswrap_mknodat(vfs_handle_struct *handle,
2948 files_struct *dirfsp,
2949 const struct smb_filename *smb_fname,
2955 START_PROFILE(syscall_mknodat);
2957 result = sys_mknodat(fsp_get_pathref_fd(dirfsp),
2958 smb_fname->base_name,
2962 END_PROFILE(syscall_mknodat);
2966 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2968 const struct smb_filename *smb_fname)
2971 struct smb_filename *result_fname = NULL;
2973 START_PROFILE(syscall_realpath);
2974 result = sys_realpath(smb_fname->base_name);
2975 END_PROFILE(syscall_realpath);
2977 result_fname = synthetic_smb_fname(ctx,
2985 return result_fname;
2988 static int vfswrap_chflags(vfs_handle_struct *handle,
2989 const struct smb_filename *smb_fname,
2993 return chflags(smb_fname->base_name, flags);
3000 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
3001 const SMB_STRUCT_STAT *sbuf)
3005 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
3009 key.devid = sbuf->st_ex_dev;
3010 key.inode = sbuf->st_ex_ino;
3011 /* key.extid is unused by default. */
3016 static uint64_t vfswrap_fs_file_id(struct vfs_handle_struct *handle,
3017 const SMB_STRUCT_STAT *psbuf)
3021 if (!(psbuf->st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)) {
3022 return psbuf->st_ex_file_id;
3025 if (handle->conn->base_share_dev == psbuf->st_ex_dev) {
3026 return (uint64_t)psbuf->st_ex_ino;
3030 file_id = ((psbuf->st_ex_ino) & UINT32_MAX);
3033 file_id |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32;
3038 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
3039 struct files_struct *fsp,
3040 const struct smb_filename *smb_fname,
3041 TALLOC_CTX *mem_ctx,
3042 unsigned int *pnum_streams,
3043 struct stream_struct **pstreams)
3045 SMB_STRUCT_STAT sbuf;
3046 struct stream_struct *tmp_streams = NULL;
3049 if ((fsp != NULL) && (fsp->fsp_flags.is_directory)) {
3051 * No default streams on directories
3056 if ((fsp != NULL) && (fsp_get_pathref_fd(fsp) != -1)) {
3057 ret = SMB_VFS_FSTAT(fsp, &sbuf);
3060 struct smb_filename *smb_fname_cp = NULL;
3062 smb_fname_cp = cp_smb_filename_nostream(talloc_tos(), smb_fname);
3063 if (smb_fname_cp == NULL) {
3064 return NT_STATUS_NO_MEMORY;
3067 if (smb_fname_cp->flags & SMB_FILENAME_POSIX_PATH) {
3068 ret = SMB_VFS_LSTAT(handle->conn, smb_fname_cp);
3070 ret = SMB_VFS_STAT(handle->conn, smb_fname_cp);
3072 sbuf = smb_fname_cp->st;
3073 TALLOC_FREE(smb_fname_cp);
3077 return map_nt_error_from_unix(errno);
3080 if (S_ISDIR(sbuf.st_ex_mode)) {
3084 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
3085 (*pnum_streams) + 1);
3086 if (tmp_streams == NULL) {
3087 return NT_STATUS_NO_MEMORY;
3089 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
3090 if (tmp_streams[*pnum_streams].name == NULL) {
3091 return NT_STATUS_NO_MEMORY;
3093 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
3094 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
3097 *pstreams = tmp_streams;
3099 return NT_STATUS_OK;
3102 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
3103 const struct smb_filename *path,
3105 TALLOC_CTX *mem_ctx,
3109 * Don't fall back to get_real_filename so callers can differentiate
3110 * between a full directory scan and an actual case-insensitive stat.
3116 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
3117 const struct smb_filename *smb_fname)
3119 return handle->conn->connectpath;
3122 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
3123 struct byte_range_lock *br_lck,
3124 struct lock_struct *plock)
3126 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3128 /* Note: blr is not used in the default implementation. */
3129 return brl_lock_windows_default(br_lck, plock);
3132 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
3133 struct byte_range_lock *br_lck,
3134 const struct lock_struct *plock)
3136 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3138 return brl_unlock_windows_default(br_lck, plock);
3141 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
3143 struct lock_struct *plock)
3145 SMB_ASSERT(plock->lock_type == READ_LOCK ||
3146 plock->lock_type == WRITE_LOCK);
3148 return strict_lock_check_default(fsp, plock);
3151 /* NT ACL operations. */
3153 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
3155 uint32_t security_info,
3156 TALLOC_CTX *mem_ctx,
3157 struct security_descriptor **ppdesc)
3161 START_PROFILE(fget_nt_acl);
3162 result = posix_fget_nt_acl(fsp, security_info,
3164 END_PROFILE(fget_nt_acl);
3168 static NTSTATUS vfswrap_get_nt_acl_at(vfs_handle_struct *handle,
3169 struct files_struct *dirfsp,
3170 const struct smb_filename *smb_fname,
3171 uint32_t security_info,
3172 TALLOC_CTX *mem_ctx,
3173 struct security_descriptor **ppdesc)
3177 START_PROFILE(get_nt_acl_at);
3179 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
3181 result = posix_get_nt_acl(handle->conn,
3186 END_PROFILE(get_nt_acl_at);
3190 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
3194 START_PROFILE(fset_nt_acl);
3195 result = set_nt_acl(fsp, security_info_sent, psd);
3196 END_PROFILE(fset_nt_acl);
3200 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
3201 struct smb_filename *file,
3202 struct security_acl *sacl,
3203 uint32_t access_requested,
3204 uint32_t access_denied)
3206 return NT_STATUS_OK; /* Nothing to do here ... */
3209 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
3210 const struct smb_filename *smb_fname,
3211 SMB_ACL_TYPE_T type,
3212 TALLOC_CTX *mem_ctx)
3214 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
3217 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
3219 TALLOC_CTX *mem_ctx)
3221 return sys_acl_get_fd(handle, fsp, mem_ctx);
3224 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
3225 const struct smb_filename *smb_fname,
3226 SMB_ACL_TYPE_T acltype,
3229 return sys_acl_set_file(handle, smb_fname, acltype, theacl);
3232 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
3234 return sys_acl_set_fd(handle, fsp, theacl);
3237 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
3238 const struct smb_filename *smb_fname)
3240 return sys_acl_delete_def_file(handle, smb_fname);
3243 /****************************************************************
3244 Extended attribute operations.
3245 *****************************************************************/
3247 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
3248 const struct smb_filename *smb_fname,
3253 return getxattr(smb_fname->base_name, name, value, size);
3256 struct vfswrap_getxattrat_state {
3257 struct tevent_context *ev;
3258 files_struct *dir_fsp;
3259 const struct smb_filename *smb_fname;
3262 * The following variables are talloced off "state" which is protected
3263 * by a destructor and thus are guaranteed to be safe to be used in the
3264 * job function in the worker thread.
3267 const char *xattr_name;
3268 uint8_t *xattr_value;
3269 struct security_unix_token *token;
3272 struct vfs_aio_state vfs_aio_state;
3273 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
3276 static int vfswrap_getxattrat_state_destructor(
3277 struct vfswrap_getxattrat_state *state)
3282 static void vfswrap_getxattrat_do_sync(struct tevent_req *req);
3283 static void vfswrap_getxattrat_do_async(void *private_data);
3284 static void vfswrap_getxattrat_done(struct tevent_req *subreq);
3286 static struct tevent_req *vfswrap_getxattrat_send(
3287 TALLOC_CTX *mem_ctx,
3288 struct tevent_context *ev,
3289 struct vfs_handle_struct *handle,
3290 files_struct *dir_fsp,
3291 const struct smb_filename *smb_fname,
3292 const char *xattr_name,
3295 struct tevent_req *req = NULL;
3296 struct tevent_req *subreq = NULL;
3297 struct vfswrap_getxattrat_state *state = NULL;
3298 size_t max_threads = 0;
3299 bool have_per_thread_cwd = false;
3300 bool have_per_thread_creds = false;
3301 bool do_async = false;
3303 req = tevent_req_create(mem_ctx, &state,
3304 struct vfswrap_getxattrat_state);
3308 *state = (struct vfswrap_getxattrat_state) {
3311 .smb_fname = smb_fname,
3314 max_threads = pthreadpool_tevent_max_threads(dir_fsp->conn->sconn->pool);
3315 if (max_threads >= 1) {
3317 * We need a non sync threadpool!
3319 have_per_thread_cwd = per_thread_cwd_supported();
3321 #ifdef HAVE_LINUX_THREAD_CREDENTIALS
3322 have_per_thread_creds = true;
3324 if (have_per_thread_cwd && have_per_thread_creds) {
3328 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat, profile_p,
3329 state->profile_bytes, 0);
3331 if (fsp_get_pathref_fd(dir_fsp) == -1) {
3332 DBG_ERR("Need a valid directory fd\n");
3333 tevent_req_error(req, EINVAL);
3334 return tevent_req_post(req, ev);
3337 if (alloc_hint > 0) {
3338 state->xattr_value = talloc_zero_array(state,
3341 if (tevent_req_nomem(state->xattr_value, req)) {
3342 return tevent_req_post(req, ev);
3347 vfswrap_getxattrat_do_sync(req);
3348 return tevent_req_post(req, ev);
3352 * Now allocate all parameters from a memory context that won't go away
3353 * no matter what. These paremeters will get used in threads and we
3354 * can't reliably cancel threads, so all buffers passed to the threads
3355 * must not be freed before all referencing threads terminate.
3358 state->name = talloc_strdup(state, smb_fname->base_name);
3359 if (tevent_req_nomem(state->name, req)) {
3360 return tevent_req_post(req, ev);
3363 state->xattr_name = talloc_strdup(state, xattr_name);
3364 if (tevent_req_nomem(state->xattr_name, req)) {
3365 return tevent_req_post(req, ev);
3369 * This is a hot codepath so at first glance one might think we should
3370 * somehow optimize away the token allocation and do a
3371 * talloc_reference() or similar black magic instead. But due to the
3372 * talloc_stackframe pool per SMB2 request this should be a simple copy
3373 * without a malloc in most cases.
3375 if (geteuid() == sec_initial_uid()) {
3376 state->token = root_unix_token(state);
3378 state->token = copy_unix_token(
3380 dir_fsp->conn->session_info->unix_token);
3382 if (tevent_req_nomem(state->token, req)) {
3383 return tevent_req_post(req, ev);
3386 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3388 subreq = pthreadpool_tevent_job_send(
3391 dir_fsp->conn->sconn->pool,
3392 vfswrap_getxattrat_do_async,
3394 if (tevent_req_nomem(subreq, req)) {
3395 return tevent_req_post(req, ev);
3397 tevent_req_set_callback(subreq, vfswrap_getxattrat_done, req);
3399 talloc_set_destructor(state, vfswrap_getxattrat_state_destructor);
3404 static void vfswrap_getxattrat_do_sync(struct tevent_req *req)
3406 struct vfswrap_getxattrat_state *state = tevent_req_data(
3407 req, struct vfswrap_getxattrat_state);
3409 char *tofree = NULL;
3410 char pathbuf[PATH_MAX+1];
3414 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
3415 state->smb_fname->base_name,
3420 if (pathlen == -1) {
3421 tevent_req_error(req, ENOMEM);
3425 state->xattr_size = getxattr(path,
3428 talloc_array_length(state->xattr_value));
3430 TALLOC_FREE(tofree);
3431 if (state->xattr_size == -1) {
3432 tevent_req_error(req, err);
3436 tevent_req_done(req);
3440 static void vfswrap_getxattrat_do_async(void *private_data)
3442 struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3443 private_data, struct vfswrap_getxattrat_state);
3444 struct timespec start_time;
3445 struct timespec end_time;
3448 PROFILE_TIMESTAMP(&start_time);
3449 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
3452 * Here we simulate a getxattrat()
3453 * call using fchdir();getxattr()
3456 per_thread_cwd_activate();
3458 /* Become the correct credential on this thread. */
3459 ret = set_thread_credentials(state->token->uid,
3461 (size_t)state->token->ngroups,
3462 state->token->groups);
3464 state->xattr_size = -1;
3465 state->vfs_aio_state.error = errno;
3469 ret = fchdir(fsp_get_pathref_fd(state->dir_fsp));
3471 state->xattr_size = -1;
3472 state->vfs_aio_state.error = errno;
3476 state->xattr_size = getxattr(state->name,
3479 talloc_array_length(state->xattr_value));
3480 if (state->xattr_size == -1) {
3481 state->vfs_aio_state.error = errno;
3485 PROFILE_TIMESTAMP(&end_time);
3486 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
3487 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3490 static void vfswrap_getxattrat_done(struct tevent_req *subreq)
3492 struct tevent_req *req = tevent_req_callback_data(
3493 subreq, struct tevent_req);
3494 struct vfswrap_getxattrat_state *state = tevent_req_data(
3495 req, struct vfswrap_getxattrat_state);
3500 * Make sure we run as the user again
3502 ok = change_to_user_and_service_by_fsp(state->dir_fsp);
3505 ret = pthreadpool_tevent_job_recv(subreq);
3506 TALLOC_FREE(subreq);
3507 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
3508 talloc_set_destructor(state, NULL);
3510 if (ret != EAGAIN) {
3511 tevent_req_error(req, ret);
3515 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
3516 * means the lower level pthreadpool failed to create a new
3517 * thread. Fallback to sync processing in that case to allow
3518 * some progress for the client.
3520 vfswrap_getxattrat_do_sync(req);
3524 if (state->xattr_size == -1) {
3525 tevent_req_error(req, state->vfs_aio_state.error);
3529 if (state->xattr_value == NULL) {
3531 * The caller only wanted the size.
3533 tevent_req_done(req);
3538 * shrink the buffer to the returned size.
3539 * (can't fail). It means NULL if size is 0.
3541 state->xattr_value = talloc_realloc(state,
3546 tevent_req_done(req);
3549 static ssize_t vfswrap_getxattrat_recv(struct tevent_req *req,
3550 struct vfs_aio_state *aio_state,
3551 TALLOC_CTX *mem_ctx,
3552 uint8_t **xattr_value)
3554 struct vfswrap_getxattrat_state *state = tevent_req_data(
3555 req, struct vfswrap_getxattrat_state);
3558 if (tevent_req_is_unix_error(req, &aio_state->error)) {
3559 tevent_req_received(req);
3563 *aio_state = state->vfs_aio_state;
3564 xattr_size = state->xattr_size;
3565 if (xattr_value != NULL) {
3566 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
3569 tevent_req_received(req);
3573 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle,
3574 struct files_struct *fsp,
3579 int fd = fsp_get_pathref_fd(fsp);
3581 if (!fsp->fsp_flags.is_pathref) {
3582 return fgetxattr(fd, name, value, size);
3585 if (fsp->fsp_flags.have_proc_fds) {
3586 const char *p = NULL;
3589 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3594 return getxattr(p, name, value, size);
3598 * This is no longer a handle based call.
3600 return getxattr(fsp->fsp_name->base_name, name, value, size);
3603 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
3604 const struct smb_filename *smb_fname,
3608 return listxattr(smb_fname->base_name, list, size);
3611 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
3613 int fd = fsp_get_pathref_fd(fsp);
3615 if (!fsp->fsp_flags.is_pathref) {
3616 return flistxattr(fd, list, size);
3619 if (fsp->fsp_flags.have_proc_fds) {
3620 const char *p = NULL;
3623 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3628 return listxattr(p, list, size);
3632 * This is no longer a handle based call.
3634 return listxattr(fsp->fsp_name->base_name, list, size);
3637 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
3638 const struct smb_filename *smb_fname,
3641 return removexattr(smb_fname->base_name, name);
3644 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
3646 int fd = fsp_get_pathref_fd(fsp);
3648 if (!fsp->fsp_flags.is_pathref) {
3649 return fremovexattr(fd, name);
3652 if (fsp->fsp_flags.have_proc_fds) {
3653 const char *p = NULL;
3656 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3661 return removexattr(p, name);
3665 * This is no longer a handle based call.
3667 return removexattr(fsp->fsp_name->base_name, name);
3670 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
3671 const struct smb_filename *smb_fname,
3677 return setxattr(smb_fname->base_name, name, value, size, flags);
3680 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
3682 int fd = fsp_get_pathref_fd(fsp);
3684 if (!fsp->fsp_flags.is_pathref) {
3685 return fsetxattr(fd, name, value, size, flags);
3688 if (fsp->fsp_flags.have_proc_fds) {
3689 const char *p = NULL;
3692 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3697 return setxattr(p, name, value, size, flags);
3701 * This is no longer a handle based call.
3703 return setxattr(fsp->fsp_name->base_name, name, value, size, flags);
3706 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
3711 static bool vfswrap_is_offline(struct connection_struct *conn,
3712 const struct smb_filename *fname)
3716 bool offline = false;
3718 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
3722 if (!lp_dmapi_support(SNUM(conn)) || !dmapi_have_session()) {
3723 #if defined(ENOTSUP)
3729 status = get_full_smb_filename(talloc_tos(), fname, &path);
3730 if (!NT_STATUS_IS_OK(status)) {
3731 errno = map_errno_from_nt_status(status);
3735 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
3742 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
3743 struct files_struct *fsp,
3744 TALLOC_CTX *mem_ctx,
3747 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
3750 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
3751 struct files_struct *fsp,
3752 const DATA_BLOB old_cookie,
3753 TALLOC_CTX *mem_ctx,
3754 DATA_BLOB *new_cookie)
3756 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
3760 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
3761 struct smb_request *smb1req,
3762 struct smbXsrv_open *op,
3763 const DATA_BLOB old_cookie,
3764 TALLOC_CTX *mem_ctx,
3765 struct files_struct **fsp,
3766 DATA_BLOB *new_cookie)
3768 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
3769 old_cookie, mem_ctx,
3773 static struct vfs_fn_pointers vfs_default_fns = {
3774 /* Disk operations */
3776 .connect_fn = vfswrap_connect,
3777 .disconnect_fn = vfswrap_disconnect,
3778 .disk_free_fn = vfswrap_disk_free,
3779 .get_quota_fn = vfswrap_get_quota,
3780 .set_quota_fn = vfswrap_set_quota,
3781 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3782 .statvfs_fn = vfswrap_statvfs,
3783 .fs_capabilities_fn = vfswrap_fs_capabilities,
3784 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3785 .create_dfs_pathat_fn = vfswrap_create_dfs_pathat,
3786 .read_dfs_pathat_fn = vfswrap_read_dfs_pathat,
3787 .snap_check_path_fn = vfswrap_snap_check_path,
3788 .snap_create_fn = vfswrap_snap_create,
3789 .snap_delete_fn = vfswrap_snap_delete,
3791 /* Directory operations */
3793 .fdopendir_fn = vfswrap_fdopendir,
3794 .readdir_fn = vfswrap_readdir,
3795 .readdir_attr_fn = vfswrap_readdir_attr,
3796 .seekdir_fn = vfswrap_seekdir,
3797 .telldir_fn = vfswrap_telldir,
3798 .rewind_dir_fn = vfswrap_rewinddir,
3799 .mkdirat_fn = vfswrap_mkdirat,
3800 .closedir_fn = vfswrap_closedir,
3802 /* File operations */
3804 .openat_fn = vfswrap_openat,
3805 .create_file_fn = vfswrap_create_file,
3806 .close_fn = vfswrap_close,
3807 .pread_fn = vfswrap_pread,
3808 .pread_send_fn = vfswrap_pread_send,
3809 .pread_recv_fn = vfswrap_pread_recv,
3810 .pwrite_fn = vfswrap_pwrite,
3811 .pwrite_send_fn = vfswrap_pwrite_send,
3812 .pwrite_recv_fn = vfswrap_pwrite_recv,
3813 .lseek_fn = vfswrap_lseek,
3814 .sendfile_fn = vfswrap_sendfile,
3815 .recvfile_fn = vfswrap_recvfile,
3816 .renameat_fn = vfswrap_renameat,
3817 .fsync_send_fn = vfswrap_fsync_send,
3818 .fsync_recv_fn = vfswrap_fsync_recv,
3819 .stat_fn = vfswrap_stat,
3820 .fstat_fn = vfswrap_fstat,
3821 .lstat_fn = vfswrap_lstat,
3822 .get_alloc_size_fn = vfswrap_get_alloc_size,
3823 .unlinkat_fn = vfswrap_unlinkat,
3824 .chmod_fn = vfswrap_chmod,
3825 .fchmod_fn = vfswrap_fchmod,
3826 .fchown_fn = vfswrap_fchown,
3827 .lchown_fn = vfswrap_lchown,
3828 .chdir_fn = vfswrap_chdir,
3829 .getwd_fn = vfswrap_getwd,
3830 .ntimes_fn = vfswrap_ntimes,
3831 .ftruncate_fn = vfswrap_ftruncate,
3832 .fallocate_fn = vfswrap_fallocate,
3833 .lock_fn = vfswrap_lock,
3834 .kernel_flock_fn = vfswrap_kernel_flock,
3835 .fcntl_fn = vfswrap_fcntl,
3836 .linux_setlease_fn = vfswrap_linux_setlease,
3837 .getlock_fn = vfswrap_getlock,
3838 .symlinkat_fn = vfswrap_symlinkat,
3839 .readlinkat_fn = vfswrap_readlinkat,
3840 .linkat_fn = vfswrap_linkat,
3841 .mknodat_fn = vfswrap_mknodat,
3842 .realpath_fn = vfswrap_realpath,
3843 .chflags_fn = vfswrap_chflags,
3844 .file_id_create_fn = vfswrap_file_id_create,
3845 .fs_file_id_fn = vfswrap_fs_file_id,
3846 .streaminfo_fn = vfswrap_streaminfo,
3847 .get_real_filename_fn = vfswrap_get_real_filename,
3848 .connectpath_fn = vfswrap_connectpath,
3849 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
3850 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3851 .strict_lock_check_fn = vfswrap_strict_lock_check,
3852 .translate_name_fn = vfswrap_translate_name,
3853 .fsctl_fn = vfswrap_fsctl,
3854 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
3855 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
3856 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
3857 .get_dos_attributes_send_fn = vfswrap_get_dos_attributes_send,
3858 .get_dos_attributes_recv_fn = vfswrap_get_dos_attributes_recv,
3859 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
3860 .offload_read_send_fn = vfswrap_offload_read_send,
3861 .offload_read_recv_fn = vfswrap_offload_read_recv,
3862 .offload_write_send_fn = vfswrap_offload_write_send,
3863 .offload_write_recv_fn = vfswrap_offload_write_recv,
3864 .get_compression_fn = vfswrap_get_compression,
3865 .set_compression_fn = vfswrap_set_compression,
3867 /* NT ACL operations. */
3869 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
3870 .get_nt_acl_at_fn = vfswrap_get_nt_acl_at,
3871 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
3872 .audit_file_fn = vfswrap_audit_file,
3874 /* POSIX ACL operations. */
3876 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
3877 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3878 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
3879 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3880 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
3881 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3882 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
3884 /* EA operations. */
3885 .getxattr_fn = vfswrap_getxattr,
3886 .getxattrat_send_fn = vfswrap_getxattrat_send,
3887 .getxattrat_recv_fn = vfswrap_getxattrat_recv,
3888 .fgetxattr_fn = vfswrap_fgetxattr,
3889 .listxattr_fn = vfswrap_listxattr,
3890 .flistxattr_fn = vfswrap_flistxattr,
3891 .removexattr_fn = vfswrap_removexattr,
3892 .fremovexattr_fn = vfswrap_fremovexattr,
3893 .setxattr_fn = vfswrap_setxattr,
3894 .fsetxattr_fn = vfswrap_fsetxattr,
3896 /* aio operations */
3897 .aio_force_fn = vfswrap_aio_force,
3899 /* durable handle operations */
3900 .durable_cookie_fn = vfswrap_durable_cookie,
3901 .durable_disconnect_fn = vfswrap_durable_disconnect,
3902 .durable_reconnect_fn = vfswrap_durable_reconnect,
3906 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3909 * Here we need to implement every call!
3911 * As this is the end of the vfs module chain.
3913 smb_vfs_assert_all_fns(&vfs_default_fns, DEFAULT_VFS_MODULE_NAME);
3914 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3915 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);