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 /* Form the msdfs_link contents */
390 msdfs_link = msdfs_link_string(frame,
393 if (msdfs_link == NULL) {
397 ret = symlinkat(msdfs_link,
398 fsp_get_pathref_fd(dirfsp),
399 smb_fname->base_name);
401 status = NT_STATUS_OK;
403 status = map_nt_error_from_unix(errno);
413 * Read and return the contents of a DFS redirect given a
414 * pathname. A caller can pass in NULL for ppreflist and
415 * preferral_count but still determine if this was a
416 * DFS redirect point by getting NT_STATUS_OK back
417 * without incurring the overhead of reading and parsing
418 * the referral contents.
421 static NTSTATUS vfswrap_read_dfs_pathat(struct vfs_handle_struct *handle,
423 struct files_struct *dirfsp,
424 struct smb_filename *smb_fname,
425 struct referral **ppreflist,
426 size_t *preferral_count)
428 NTSTATUS status = NT_STATUS_NO_MEMORY;
430 char *link_target = NULL;
433 #if defined(HAVE_BROKEN_READLINK)
434 char link_target_buf[PATH_MAX];
436 char link_target_buf[7];
440 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
442 if (is_named_stream(smb_fname)) {
443 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
447 if (ppreflist == NULL && preferral_count == NULL) {
449 * We're only checking if this is a DFS
450 * redirect. We don't need to return data.
452 bufsize = sizeof(link_target_buf);
453 link_target = link_target_buf;
456 link_target = talloc_array(mem_ctx, char, bufsize);
462 referral_len = readlinkat(fsp_get_io_fd(dirfsp),
463 smb_fname->base_name,
466 if (referral_len == -1) {
467 if (errno == EINVAL) {
469 * If the path isn't a link, readlinkat
470 * returns EINVAL. Allow the caller to
473 DBG_INFO("%s is not a link.\n", smb_fname->base_name);
474 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
476 status = map_nt_error_from_unix(errno);
477 DBG_ERR("Error reading "
478 "msdfs link %s: %s\n",
479 smb_fname->base_name,
484 link_target[referral_len] = '\0';
486 DBG_INFO("%s -> %s\n",
487 smb_fname->base_name,
490 if (!strnequal(link_target, "msdfs:", 6)) {
491 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
495 ret = sys_lstat(smb_fname->base_name,
497 lp_fake_directory_create_times(SNUM(handle->conn)));
499 status = map_nt_error_from_unix(errno);
503 if (ppreflist == NULL && preferral_count == NULL) {
504 /* Early return for checking if this is a DFS link. */
508 ok = parse_msdfs_symlink(mem_ctx,
509 lp_msdfs_shuffle_referrals(SNUM(handle->conn)),
515 status = NT_STATUS_OK;
517 status = NT_STATUS_NO_MEMORY;
522 if (link_target != link_target_buf) {
523 TALLOC_FREE(link_target);
528 static NTSTATUS vfswrap_snap_check_path(struct vfs_handle_struct *handle,
530 const char *service_path,
533 return NT_STATUS_NOT_SUPPORTED;
536 static NTSTATUS vfswrap_snap_create(struct vfs_handle_struct *handle,
538 const char *base_volume,
544 return NT_STATUS_NOT_SUPPORTED;
547 static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle,
552 return NT_STATUS_NOT_SUPPORTED;
555 /* Directory operations */
557 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
564 START_PROFILE(syscall_fdopendir);
565 result = sys_fdopendir(fsp_get_io_fd(fsp));
566 END_PROFILE(syscall_fdopendir);
571 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
572 struct files_struct *dirfsp,
574 SMB_STRUCT_STAT *sbuf)
576 struct dirent *result;
577 bool do_stat = false;
578 bool fake_ctime = lp_fake_directory_create_times(SNUM(handle->conn));
579 int flags = AT_SYMLINK_NOFOLLOW;
583 START_PROFILE(syscall_readdir);
585 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
589 result = readdir(dirp);
590 END_PROFILE(syscall_readdir);
595 if (result == NULL) {
600 * Default Posix readdir() does not give us stat info.
601 * Set to invalid to indicate we didn't return this info.
603 SET_STAT_INVALID(*sbuf);
605 /* See if we can efficiently return this. */
610 ret = fstatat(dirfd(dirp),
619 * As this is an optimization, ignore it if we stat'ed a
620 * symlink for non-POSIX context. Make the caller do it again
621 * as we don't know if they wanted the link info, or its
624 if (S_ISLNK(st.st_mode) &&
625 !(dirfsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH))
629 init_stat_ex_from_stat(sbuf, &st, fake_ctime);
634 static NTSTATUS vfswrap_freaddir_attr(struct vfs_handle_struct *handle,
635 struct files_struct *fsp,
637 struct readdir_attr_data **attr_data)
639 return NT_STATUS_NOT_SUPPORTED;
642 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
644 START_PROFILE(syscall_seekdir);
645 seekdir(dirp, offset);
646 END_PROFILE(syscall_seekdir);
649 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
652 START_PROFILE(syscall_telldir);
653 result = telldir(dirp);
654 END_PROFILE(syscall_telldir);
658 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
660 START_PROFILE(syscall_rewinddir);
662 END_PROFILE(syscall_rewinddir);
665 static int vfswrap_mkdirat(vfs_handle_struct *handle,
666 struct files_struct *dirfsp,
667 const struct smb_filename *smb_fname,
672 START_PROFILE(syscall_mkdirat);
674 result = mkdirat(fsp_get_pathref_fd(dirfsp), smb_fname->base_name, mode);
676 END_PROFILE(syscall_mkdirat);
680 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
684 START_PROFILE(syscall_closedir);
685 result = closedir(dirp);
686 END_PROFILE(syscall_closedir);
690 /* File operations */
692 static int vfswrap_openat(vfs_handle_struct *handle,
693 const struct files_struct *dirfsp,
694 const struct smb_filename *smb_fname,
699 bool have_opath = false;
700 bool became_root = false;
703 START_PROFILE(syscall_openat);
705 if (is_named_stream(smb_fname)) {
713 if (fsp->fsp_flags.is_pathref) {
718 if (fsp->fsp_flags.is_pathref && !have_opath) {
723 result = openat(fsp_get_pathref_fd(dirfsp),
724 smb_fname->base_name,
732 fsp->fsp_flags.have_proc_fds = fsp->conn->have_proc_fds;
735 END_PROFILE(syscall_openat);
738 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
739 struct smb_request *req,
740 struct smb_filename *smb_fname,
741 uint32_t access_mask,
742 uint32_t share_access,
743 uint32_t create_disposition,
744 uint32_t create_options,
745 uint32_t file_attributes,
746 uint32_t oplock_request,
747 const struct smb2_lease *lease,
748 uint64_t allocation_size,
749 uint32_t private_flags,
750 struct security_descriptor *sd,
751 struct ea_list *ea_list,
752 files_struct **result,
754 const struct smb2_create_blobs *in_context_blobs,
755 struct smb2_create_blobs *out_context_blobs)
757 return create_file_default(handle->conn, req, smb_fname,
758 access_mask, share_access,
759 create_disposition, create_options,
760 file_attributes, oplock_request, lease,
761 allocation_size, private_flags,
763 pinfo, in_context_blobs, out_context_blobs);
766 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
770 START_PROFILE(syscall_close);
771 result = fd_close_posix(fsp);
772 END_PROFILE(syscall_close);
776 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
777 size_t n, off_t offset)
781 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
782 START_PROFILE_BYTES(syscall_pread, n);
783 result = sys_pread_full(fsp_get_io_fd(fsp), data, n, offset);
784 END_PROFILE_BYTES(syscall_pread);
786 if (result == -1 && errno == ESPIPE) {
787 /* Maintain the fiction that pipes can be seeked (sought?) on. */
788 result = sys_read(fsp_get_io_fd(fsp), data, n);
789 fh_set_pos(fsp->fh, 0);
792 #else /* HAVE_PREAD */
795 #endif /* HAVE_PREAD */
800 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
801 size_t n, off_t offset)
805 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
806 START_PROFILE_BYTES(syscall_pwrite, n);
807 result = sys_pwrite_full(fsp_get_io_fd(fsp), data, n, offset);
808 END_PROFILE_BYTES(syscall_pwrite);
810 if (result == -1 && errno == ESPIPE) {
811 /* Maintain the fiction that pipes can be sought on. */
812 result = sys_write(fsp_get_io_fd(fsp), data, n);
815 #else /* HAVE_PWRITE */
818 #endif /* HAVE_PWRITE */
823 struct vfswrap_pread_state {
830 struct vfs_aio_state vfs_aio_state;
831 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
834 static void vfs_pread_do(void *private_data);
835 static void vfs_pread_done(struct tevent_req *subreq);
836 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state);
838 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
840 struct tevent_context *ev,
841 struct files_struct *fsp,
843 size_t n, off_t offset)
845 struct tevent_req *req, *subreq;
846 struct vfswrap_pread_state *state;
848 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
854 state->fd = fsp_get_io_fd(fsp);
857 state->offset = offset;
859 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
860 state->profile_bytes, n);
861 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
863 subreq = pthreadpool_tevent_job_send(
864 state, ev, handle->conn->sconn->pool,
865 vfs_pread_do, state);
866 if (tevent_req_nomem(subreq, req)) {
867 return tevent_req_post(req, ev);
869 tevent_req_set_callback(subreq, vfs_pread_done, req);
871 talloc_set_destructor(state, vfs_pread_state_destructor);
876 static void vfs_pread_do(void *private_data)
878 struct vfswrap_pread_state *state = talloc_get_type_abort(
879 private_data, struct vfswrap_pread_state);
880 struct timespec start_time;
881 struct timespec end_time;
883 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
885 PROFILE_TIMESTAMP(&start_time);
887 state->ret = sys_pread_full(state->fd,
892 if (state->ret == -1) {
893 state->vfs_aio_state.error = errno;
896 PROFILE_TIMESTAMP(&end_time);
898 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
900 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
903 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state)
908 static void vfs_pread_done(struct tevent_req *subreq)
910 struct tevent_req *req = tevent_req_callback_data(
911 subreq, struct tevent_req);
912 struct vfswrap_pread_state *state = tevent_req_data(
913 req, struct vfswrap_pread_state);
916 ret = pthreadpool_tevent_job_recv(subreq);
918 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
919 talloc_set_destructor(state, NULL);
922 tevent_req_error(req, ret);
926 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
927 * means the lower level pthreadpool failed to create a new
928 * thread. Fallback to sync processing in that case to allow
929 * some progress for the client.
934 tevent_req_done(req);
937 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
938 struct vfs_aio_state *vfs_aio_state)
940 struct vfswrap_pread_state *state = tevent_req_data(
941 req, struct vfswrap_pread_state);
943 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
947 *vfs_aio_state = state->vfs_aio_state;
951 struct vfswrap_pwrite_state {
958 struct vfs_aio_state vfs_aio_state;
959 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
962 static void vfs_pwrite_do(void *private_data);
963 static void vfs_pwrite_done(struct tevent_req *subreq);
964 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state);
966 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
968 struct tevent_context *ev,
969 struct files_struct *fsp,
971 size_t n, off_t offset)
973 struct tevent_req *req, *subreq;
974 struct vfswrap_pwrite_state *state;
976 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
982 state->fd = fsp_get_io_fd(fsp);
985 state->offset = offset;
987 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
988 state->profile_bytes, n);
989 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
991 subreq = pthreadpool_tevent_job_send(
992 state, ev, handle->conn->sconn->pool,
993 vfs_pwrite_do, state);
994 if (tevent_req_nomem(subreq, req)) {
995 return tevent_req_post(req, ev);
997 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
999 talloc_set_destructor(state, vfs_pwrite_state_destructor);
1004 static void vfs_pwrite_do(void *private_data)
1006 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
1007 private_data, struct vfswrap_pwrite_state);
1008 struct timespec start_time;
1009 struct timespec end_time;
1011 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
1013 PROFILE_TIMESTAMP(&start_time);
1015 state->ret = sys_pwrite_full(state->fd,
1020 if (state->ret == -1) {
1021 state->vfs_aio_state.error = errno;
1024 PROFILE_TIMESTAMP(&end_time);
1026 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1028 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1031 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state)
1036 static void vfs_pwrite_done(struct tevent_req *subreq)
1038 struct tevent_req *req = tevent_req_callback_data(
1039 subreq, struct tevent_req);
1040 struct vfswrap_pwrite_state *state = tevent_req_data(
1041 req, struct vfswrap_pwrite_state);
1044 ret = pthreadpool_tevent_job_recv(subreq);
1045 TALLOC_FREE(subreq);
1046 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1047 talloc_set_destructor(state, NULL);
1049 if (ret != EAGAIN) {
1050 tevent_req_error(req, ret);
1054 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1055 * means the lower level pthreadpool failed to create a new
1056 * thread. Fallback to sync processing in that case to allow
1057 * some progress for the client.
1059 vfs_pwrite_do(state);
1062 tevent_req_done(req);
1065 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
1066 struct vfs_aio_state *vfs_aio_state)
1068 struct vfswrap_pwrite_state *state = tevent_req_data(
1069 req, struct vfswrap_pwrite_state);
1071 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1075 *vfs_aio_state = state->vfs_aio_state;
1079 struct vfswrap_fsync_state {
1083 struct vfs_aio_state vfs_aio_state;
1084 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
1087 static void vfs_fsync_do(void *private_data);
1088 static void vfs_fsync_done(struct tevent_req *subreq);
1089 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state);
1091 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
1092 TALLOC_CTX *mem_ctx,
1093 struct tevent_context *ev,
1094 struct files_struct *fsp)
1096 struct tevent_req *req, *subreq;
1097 struct vfswrap_fsync_state *state;
1099 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
1105 state->fd = fsp_get_io_fd(fsp);
1107 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_fsync, profile_p,
1108 state->profile_bytes, 0);
1109 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1111 subreq = pthreadpool_tevent_job_send(
1112 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
1113 if (tevent_req_nomem(subreq, req)) {
1114 return tevent_req_post(req, ev);
1116 tevent_req_set_callback(subreq, vfs_fsync_done, req);
1118 talloc_set_destructor(state, vfs_fsync_state_destructor);
1123 static void vfs_fsync_do(void *private_data)
1125 struct vfswrap_fsync_state *state = talloc_get_type_abort(
1126 private_data, struct vfswrap_fsync_state);
1127 struct timespec start_time;
1128 struct timespec end_time;
1130 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
1132 PROFILE_TIMESTAMP(&start_time);
1135 state->ret = fsync(state->fd);
1136 } while ((state->ret == -1) && (errno == EINTR));
1138 if (state->ret == -1) {
1139 state->vfs_aio_state.error = errno;
1142 PROFILE_TIMESTAMP(&end_time);
1144 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1146 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1149 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state)
1154 static void vfs_fsync_done(struct tevent_req *subreq)
1156 struct tevent_req *req = tevent_req_callback_data(
1157 subreq, struct tevent_req);
1158 struct vfswrap_fsync_state *state = tevent_req_data(
1159 req, struct vfswrap_fsync_state);
1162 ret = pthreadpool_tevent_job_recv(subreq);
1163 TALLOC_FREE(subreq);
1164 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1165 talloc_set_destructor(state, NULL);
1167 if (ret != EAGAIN) {
1168 tevent_req_error(req, ret);
1172 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1173 * means the lower level pthreadpool failed to create a new
1174 * thread. Fallback to sync processing in that case to allow
1175 * some progress for the client.
1177 vfs_fsync_do(state);
1180 tevent_req_done(req);
1183 static int vfswrap_fsync_recv(struct tevent_req *req,
1184 struct vfs_aio_state *vfs_aio_state)
1186 struct vfswrap_fsync_state *state = tevent_req_data(
1187 req, struct vfswrap_fsync_state);
1189 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1193 *vfs_aio_state = state->vfs_aio_state;
1197 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1201 START_PROFILE(syscall_lseek);
1203 result = lseek(fsp_get_io_fd(fsp), offset, whence);
1205 * We want to maintain the fiction that we can seek
1206 * on a fifo for file system purposes. This allows
1207 * people to set up UNIX fifo's that feed data to Windows
1208 * applications. JRA.
1211 if((result == -1) && (errno == ESPIPE)) {
1216 END_PROFILE(syscall_lseek);
1220 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1221 off_t offset, size_t n)
1225 START_PROFILE_BYTES(syscall_sendfile, n);
1226 result = sys_sendfile(tofd, fsp_get_io_fd(fromfsp), hdr, offset, n);
1227 END_PROFILE_BYTES(syscall_sendfile);
1231 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1233 files_struct *tofsp,
1239 START_PROFILE_BYTES(syscall_recvfile, n);
1240 result = sys_recvfile(fromfd, fsp_get_io_fd(tofsp), offset, n);
1241 END_PROFILE_BYTES(syscall_recvfile);
1245 static int vfswrap_renameat(vfs_handle_struct *handle,
1246 files_struct *srcfsp,
1247 const struct smb_filename *smb_fname_src,
1248 files_struct *dstfsp,
1249 const struct smb_filename *smb_fname_dst)
1253 START_PROFILE(syscall_renameat);
1255 if (is_named_stream(smb_fname_src) || is_named_stream(smb_fname_dst)) {
1260 result = renameat(fsp_get_pathref_fd(srcfsp),
1261 smb_fname_src->base_name,
1262 fsp_get_pathref_fd(dstfsp),
1263 smb_fname_dst->base_name);
1266 END_PROFILE(syscall_renameat);
1270 static int vfswrap_stat(vfs_handle_struct *handle,
1271 struct smb_filename *smb_fname)
1275 START_PROFILE(syscall_stat);
1277 if (is_named_stream(smb_fname)) {
1282 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1283 lp_fake_directory_create_times(SNUM(handle->conn)));
1285 END_PROFILE(syscall_stat);
1289 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1293 START_PROFILE(syscall_fstat);
1294 result = sys_fstat(fsp_get_pathref_fd(fsp),
1295 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1296 END_PROFILE(syscall_fstat);
1300 static int vfswrap_lstat(vfs_handle_struct *handle,
1301 struct smb_filename *smb_fname)
1305 START_PROFILE(syscall_lstat);
1307 if (is_named_stream(smb_fname)) {
1312 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1313 lp_fake_directory_create_times(SNUM(handle->conn)));
1315 END_PROFILE(syscall_lstat);
1319 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1321 enum vfs_translate_direction direction,
1322 TALLOC_CTX *mem_ctx,
1325 return NT_STATUS_NONE_MAPPED;
1329 * Return allocated parent directory and basename of path
1331 * Note: if requesting name, it is returned as talloc child of the
1332 * parent. Freeing the parent is thus sufficient to free both.
1334 static NTSTATUS vfswrap_parent_pathname(struct vfs_handle_struct *handle,
1335 TALLOC_CTX *mem_ctx,
1336 const struct smb_filename *smb_fname_in,
1337 struct smb_filename **parent_dir_out,
1338 struct smb_filename **atname_out)
1340 TALLOC_CTX *frame = talloc_stackframe();
1341 struct smb_filename *parent = NULL;
1342 struct smb_filename *name = NULL;
1345 parent = cp_smb_filename(frame, smb_fname_in);
1346 if (parent == NULL) {
1348 return NT_STATUS_NO_MEMORY;
1350 TALLOC_FREE(parent->stream_name);
1351 SET_STAT_INVALID(parent->st);
1353 p = strrchr_m(parent->base_name, '/'); /* Find final '/', if any */
1355 TALLOC_FREE(parent->base_name);
1356 parent->base_name = talloc_strdup(parent, ".");
1357 if (parent->base_name == NULL) {
1359 return NT_STATUS_NO_MEMORY;
1361 p = smb_fname_in->base_name;
1367 if (atname_out == NULL) {
1368 *parent_dir_out = talloc_move(mem_ctx, &parent);
1370 return NT_STATUS_OK;
1373 name = cp_smb_filename(frame, smb_fname_in);
1376 return NT_STATUS_NO_MEMORY;
1378 TALLOC_FREE(name->base_name);
1380 name->base_name = talloc_strdup(name, p);
1381 if (name->base_name == NULL) {
1383 return NT_STATUS_NO_MEMORY;
1386 *parent_dir_out = talloc_move(mem_ctx, &parent);
1387 *atname_out = talloc_move(*parent_dir_out, &name);
1389 return NT_STATUS_OK;
1393 * Implement the default fsctl operation.
1395 static bool vfswrap_logged_ioctl_message = false;
1397 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1398 struct files_struct *fsp,
1401 uint16_t req_flags, /* Needed for UNICODE ... */
1402 const uint8_t *_in_data,
1404 uint8_t **_out_data,
1405 uint32_t max_out_len,
1408 const char *in_data = (const char *)_in_data;
1409 char **out_data = (char **)_out_data;
1413 case FSCTL_SET_SPARSE:
1415 bool set_sparse = true;
1417 if (in_len >= 1 && in_data[0] == 0) {
1421 status = file_set_sparse(handle->conn, fsp, set_sparse);
1423 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1424 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1425 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1426 nt_errstr(status)));
1431 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1433 unsigned char objid[16];
1434 char *return_data = NULL;
1436 /* This should return the object-id on this file.
1437 * I think I'll make this be the inode+dev. JRA.
1440 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1441 fsp_fnum_dbg(fsp)));
1443 *out_len = MIN(max_out_len, 64);
1445 /* Hmmm, will this cause problems if less data asked for? */
1446 return_data = talloc_array(ctx, char, 64);
1447 if (return_data == NULL) {
1448 return NT_STATUS_NO_MEMORY;
1451 /* For backwards compatibility only store the dev/inode. */
1452 push_file_id_16(return_data, &fsp->file_id);
1453 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1454 push_file_id_16(return_data+32, &fsp->file_id);
1455 memset(return_data+48, 0, 16);
1456 *out_data = return_data;
1457 return NT_STATUS_OK;
1460 case FSCTL_GET_REPARSE_POINT:
1462 status = fsctl_get_reparse_point(
1463 fsp, ctx, out_data, max_out_len, out_len);
1467 case FSCTL_SET_REPARSE_POINT:
1469 status = fsctl_set_reparse_point(fsp, ctx, _in_data, in_len);
1473 case FSCTL_DELETE_REPARSE_POINT:
1475 status = fsctl_del_reparse_point(fsp, ctx, _in_data, in_len);
1479 case FSCTL_GET_SHADOW_COPY_DATA:
1482 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1483 * and return their volume names. If max_data_count is 16, then it is just
1484 * asking for the number of volumes and length of the combined names.
1486 * pdata is the data allocated by our caller, but that uses
1487 * total_data_count (which is 0 in our case) rather than max_data_count.
1488 * Allocate the correct amount and return the pointer to let
1489 * it be deallocated when we return.
1491 struct shadow_copy_data *shadow_data = NULL;
1492 bool labels = False;
1493 uint32_t labels_data_count = 0;
1495 char *cur_pdata = NULL;
1497 if (max_out_len < 16) {
1498 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1500 return NT_STATUS_INVALID_PARAMETER;
1503 if (max_out_len > 16) {
1507 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1508 if (shadow_data == NULL) {
1509 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1510 return NT_STATUS_NO_MEMORY;
1514 * Call the VFS routine to actually do the work.
1516 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1519 /* broken module didn't set errno on error */
1520 status = NT_STATUS_UNSUCCESSFUL;
1522 status = map_nt_error_from_unix(errno);
1523 if (NT_STATUS_EQUAL(status,
1524 NT_STATUS_NOT_SUPPORTED)) {
1528 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1529 "connectpath %s, failed - %s.\n",
1530 fsp->conn->connectpath,
1531 nt_errstr(status)));
1532 TALLOC_FREE(shadow_data);
1536 labels_data_count = (shadow_data->num_volumes * 2 *
1537 sizeof(SHADOW_COPY_LABEL)) + 2;
1542 *out_len = 12 + labels_data_count;
1545 if (max_out_len < *out_len) {
1546 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1547 max_out_len, *out_len));
1548 TALLOC_FREE(shadow_data);
1549 return NT_STATUS_BUFFER_TOO_SMALL;
1552 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1553 if (cur_pdata == NULL) {
1554 TALLOC_FREE(shadow_data);
1555 return NT_STATUS_NO_MEMORY;
1558 *out_data = cur_pdata;
1560 /* num_volumes 4 bytes */
1561 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1564 /* num_labels 4 bytes */
1565 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1568 /* needed_data_count 4 bytes */
1569 SIVAL(cur_pdata, 8, labels_data_count);
1573 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1574 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1575 if (labels && shadow_data->labels) {
1576 for (i=0; i<shadow_data->num_volumes; i++) {
1578 status = srvstr_push(cur_pdata, req_flags,
1579 cur_pdata, shadow_data->labels[i],
1580 2 * sizeof(SHADOW_COPY_LABEL),
1581 STR_UNICODE|STR_TERMINATE, &len);
1582 if (!NT_STATUS_IS_OK(status)) {
1583 TALLOC_FREE(*out_data);
1584 TALLOC_FREE(shadow_data);
1587 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1588 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1592 TALLOC_FREE(shadow_data);
1594 return NT_STATUS_OK;
1597 case FSCTL_FIND_FILES_BY_SID:
1599 /* pretend this succeeded -
1601 * we have to send back a list with all files owned by this SID
1603 * but I have to check that --metze
1607 struct dom_sid_buf buf;
1611 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1612 fsp_fnum_dbg(fsp)));
1615 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1616 return NT_STATUS_INVALID_PARAMETER;
1619 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1621 /* unknown 4 bytes: this is not the length of the sid :-( */
1622 /*unknown = IVAL(pdata,0);*/
1624 ret = sid_parse(_in_data + 4, sid_len, &sid);
1626 return NT_STATUS_INVALID_PARAMETER;
1628 DEBUGADD(10, ("for SID: %s\n",
1629 dom_sid_str_buf(&sid, &buf)));
1631 if (!sid_to_uid(&sid, &uid)) {
1632 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1633 dom_sid_str_buf(&sid, &buf),
1634 (unsigned long)sid_len));
1638 /* we can take a look at the find source :-)
1640 * find ./ -uid $uid -name '*' is what we need here
1643 * and send 4bytes len and then NULL terminated unicode strings
1646 * but I don't know how to deal with the paged results
1647 * (maybe we can hang the result anywhere in the fsp struct)
1649 * but I don't know how to deal with the paged results
1650 * (maybe we can hang the result anywhere in the fsp struct)
1652 * we don't send all files at once
1653 * and at the next we should *not* start from the beginning,
1654 * so we have to cache the result
1659 /* this works for now... */
1660 return NT_STATUS_OK;
1663 case FSCTL_QUERY_ALLOCATED_RANGES:
1665 /* FIXME: This is just a dummy reply, telling that all of the
1666 * file is allocated. MKS cp needs that.
1667 * Adding the real allocated ranges via FIEMAP on Linux
1668 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1669 * this FSCTL correct for sparse files.
1671 uint64_t offset, length;
1672 char *out_data_tmp = NULL;
1675 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1677 return NT_STATUS_INVALID_PARAMETER;
1680 if (max_out_len < 16) {
1681 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1683 return NT_STATUS_INVALID_PARAMETER;
1686 offset = BVAL(in_data,0);
1687 length = BVAL(in_data,8);
1689 if (offset + length < offset) {
1690 /* No 64-bit integer wrap. */
1691 return NT_STATUS_INVALID_PARAMETER;
1694 /* Shouldn't this be SMB_VFS_STAT ... ? */
1695 status = vfs_stat_fsp(fsp);
1696 if (!NT_STATUS_IS_OK(status)) {
1701 out_data_tmp = talloc_array(ctx, char, *out_len);
1702 if (out_data_tmp == NULL) {
1703 DEBUG(10, ("unable to allocate memory for response\n"));
1704 return NT_STATUS_NO_MEMORY;
1707 if (offset > fsp->fsp_name->st.st_ex_size ||
1708 fsp->fsp_name->st.st_ex_size == 0 ||
1710 memset(out_data_tmp, 0, *out_len);
1712 uint64_t end = offset + length;
1713 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1714 SBVAL(out_data_tmp, 0, 0);
1715 SBVAL(out_data_tmp, 8, end);
1718 *out_data = out_data_tmp;
1720 return NT_STATUS_OK;
1723 case FSCTL_IS_VOLUME_DIRTY:
1725 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1726 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1728 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1729 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1731 return NT_STATUS_INVALID_PARAMETER;
1736 * Only print once ... unfortunately there could be lots of
1737 * different FSCTLs that are called.
1739 if (!vfswrap_logged_ioctl_message) {
1740 vfswrap_logged_ioctl_message = true;
1741 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1742 __func__, function));
1746 return NT_STATUS_NOT_SUPPORTED;
1749 static bool vfswrap_is_offline(struct connection_struct *conn,
1750 const struct smb_filename *fname);
1752 struct vfswrap_get_dos_attributes_state {
1753 struct vfs_aio_state aio_state;
1754 connection_struct *conn;
1755 TALLOC_CTX *mem_ctx;
1756 struct tevent_context *ev;
1757 files_struct *dir_fsp;
1758 struct smb_filename *smb_fname;
1763 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq);
1765 static struct tevent_req *vfswrap_get_dos_attributes_send(
1766 TALLOC_CTX *mem_ctx,
1767 struct tevent_context *ev,
1768 struct vfs_handle_struct *handle,
1769 files_struct *dir_fsp,
1770 struct smb_filename *smb_fname)
1772 struct tevent_req *req = NULL;
1773 struct tevent_req *subreq = NULL;
1774 struct vfswrap_get_dos_attributes_state *state = NULL;
1776 req = tevent_req_create(mem_ctx, &state,
1777 struct vfswrap_get_dos_attributes_state);
1782 *state = (struct vfswrap_get_dos_attributes_state) {
1783 .conn = dir_fsp->conn,
1787 .smb_fname = smb_fname,
1790 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1794 SAMBA_XATTR_DOS_ATTRIB,
1796 if (tevent_req_nomem(subreq, req)) {
1797 return tevent_req_post(req, ev);
1799 tevent_req_set_callback(subreq,
1800 vfswrap_get_dos_attributes_getxattr_done,
1806 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq)
1808 struct tevent_req *req =
1809 tevent_req_callback_data(subreq,
1811 struct vfswrap_get_dos_attributes_state *state =
1812 tevent_req_data(req,
1813 struct vfswrap_get_dos_attributes_state);
1815 DATA_BLOB blob = {0};
1817 char *tofree = NULL;
1818 char pathbuf[PATH_MAX+1];
1820 struct smb_filename smb_fname;
1824 xattr_size = SMB_VFS_GETXATTRAT_RECV(subreq,
1828 TALLOC_FREE(subreq);
1829 if (xattr_size == -1) {
1830 status = map_nt_error_from_unix(state->aio_state.error);
1832 if (state->as_root) {
1833 tevent_req_nterror(req, status);
1836 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1837 tevent_req_nterror(req, status);
1841 state->as_root = true;
1844 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1848 SAMBA_XATTR_DOS_ATTRIB,
1851 if (tevent_req_nomem(subreq, req)) {
1854 tevent_req_set_callback(subreq,
1855 vfswrap_get_dos_attributes_getxattr_done,
1860 blob.length = xattr_size;
1862 status = parse_dos_attribute_blob(state->smb_fname,
1865 if (!NT_STATUS_IS_OK(status)) {
1866 tevent_req_nterror(req, status);
1870 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
1871 state->smb_fname->base_name,
1876 if (pathlen == -1) {
1877 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1881 smb_fname = (struct smb_filename) {
1883 .st = state->smb_fname->st,
1884 .flags = state->smb_fname->flags,
1885 .twrp = state->smb_fname->twrp,
1888 offline = vfswrap_is_offline(state->conn, &smb_fname);
1890 state->dosmode |= FILE_ATTRIBUTE_OFFLINE;
1892 TALLOC_FREE(tofree);
1894 tevent_req_done(req);
1898 static NTSTATUS vfswrap_get_dos_attributes_recv(struct tevent_req *req,
1899 struct vfs_aio_state *aio_state,
1902 struct vfswrap_get_dos_attributes_state *state =
1903 tevent_req_data(req,
1904 struct vfswrap_get_dos_attributes_state);
1907 if (tevent_req_is_nterror(req, &status)) {
1908 tevent_req_received(req);
1912 *aio_state = state->aio_state;
1913 *dosmode = state->dosmode;
1914 tevent_req_received(req);
1915 return NT_STATUS_OK;
1918 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1919 struct files_struct *fsp,
1924 offline = vfswrap_is_offline(handle->conn, fsp->fsp_name);
1926 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1929 return fget_ea_dos_attribute(fsp, dosmode);
1932 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1933 struct files_struct *fsp,
1936 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1939 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1941 struct vfswrap_offload_read_state {
1945 static struct tevent_req *vfswrap_offload_read_send(
1946 TALLOC_CTX *mem_ctx,
1947 struct tevent_context *ev,
1948 struct vfs_handle_struct *handle,
1949 struct files_struct *fsp,
1955 struct tevent_req *req = NULL;
1956 struct vfswrap_offload_read_state *state = NULL;
1959 req = tevent_req_create(mem_ctx, &state,
1960 struct vfswrap_offload_read_state);
1965 status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1966 &vfswrap_offload_ctx);
1967 if (tevent_req_nterror(req, status)) {
1968 return tevent_req_post(req, ev);
1971 if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1972 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1973 return tevent_req_post(req, ev);
1976 status = vfs_offload_token_create_blob(state, fsp, fsctl,
1978 if (tevent_req_nterror(req, status)) {
1979 return tevent_req_post(req, ev);
1982 status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1984 if (tevent_req_nterror(req, status)) {
1985 return tevent_req_post(req, ev);
1988 tevent_req_done(req);
1989 return tevent_req_post(req, ev);
1992 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
1993 struct vfs_handle_struct *handle,
1994 TALLOC_CTX *mem_ctx,
1997 struct vfswrap_offload_read_state *state = tevent_req_data(
1998 req, struct vfswrap_offload_read_state);
2001 if (tevent_req_is_nterror(req, &status)) {
2002 tevent_req_received(req);
2006 token->length = state->token.length;
2007 token->data = talloc_move(mem_ctx, &state->token.data);
2009 tevent_req_received(req);
2010 return NT_STATUS_OK;
2013 struct vfswrap_offload_write_state {
2015 bool read_lck_locked;
2016 bool write_lck_locked;
2018 struct tevent_context *src_ev;
2019 struct files_struct *src_fsp;
2021 struct tevent_context *dst_ev;
2022 struct files_struct *dst_fsp;
2026 size_t next_io_size;
2029 static void vfswrap_offload_write_cleanup(struct tevent_req *req,
2030 enum tevent_req_state req_state)
2032 struct vfswrap_offload_write_state *state = tevent_req_data(
2033 req, struct vfswrap_offload_write_state);
2036 if (state->dst_fsp == NULL) {
2040 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2042 state->dst_fsp = NULL;
2045 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
2047 static struct tevent_req *vfswrap_offload_write_send(
2048 struct vfs_handle_struct *handle,
2049 TALLOC_CTX *mem_ctx,
2050 struct tevent_context *ev,
2053 off_t transfer_offset,
2054 struct files_struct *dest_fsp,
2058 struct tevent_req *req;
2059 struct vfswrap_offload_write_state *state = NULL;
2060 /* off_t is signed! */
2061 off_t max_offset = INT64_MAX - to_copy;
2062 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
2063 files_struct *src_fsp = NULL;
2067 req = tevent_req_create(mem_ctx, &state,
2068 struct vfswrap_offload_write_state);
2073 *state = (struct vfswrap_offload_write_state) {
2075 .src_off = transfer_offset,
2077 .dst_fsp = dest_fsp,
2078 .dst_off = dest_off,
2080 .remaining = to_copy,
2083 tevent_req_set_cleanup_fn(req, vfswrap_offload_write_cleanup);
2086 case FSCTL_SRV_COPYCHUNK:
2087 case FSCTL_SRV_COPYCHUNK_WRITE:
2090 case FSCTL_OFFLOAD_WRITE:
2091 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
2092 return tevent_req_post(req, ev);
2094 case FSCTL_DUP_EXTENTS_TO_FILE:
2095 DBG_DEBUG("COW clones not supported by vfs_default\n");
2096 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2097 return tevent_req_post(req, ev);
2100 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2101 return tevent_req_post(req, ev);
2105 * From here on we assume a copy-chunk fsctl
2109 tevent_req_done(req);
2110 return tevent_req_post(req, ev);
2113 if (state->src_off > max_offset) {
2115 * Protect integer checks below.
2117 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2118 return tevent_req_post(req, ev);
2120 if (state->src_off < 0) {
2122 * Protect integer checks below.
2124 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2125 return tevent_req_post(req, ev);
2127 if (state->dst_off > max_offset) {
2129 * Protect integer checks below.
2131 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2132 return tevent_req_post(req, ev);
2134 if (state->dst_off < 0) {
2136 * Protect integer checks below.
2138 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2139 return tevent_req_post(req, ev);
2142 status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
2144 if (tevent_req_nterror(req, status)) {
2145 return tevent_req_post(req, ev);
2148 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
2150 status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
2151 if (!NT_STATUS_IS_OK(status)) {
2152 tevent_req_nterror(req, status);
2153 return tevent_req_post(req, ev);
2156 ok = change_to_user_and_service_by_fsp(src_fsp);
2158 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2159 return tevent_req_post(req, ev);
2162 state->src_ev = src_fsp->conn->sconn->ev_ctx;
2163 state->src_fsp = src_fsp;
2165 status = vfs_stat_fsp(src_fsp);
2166 if (tevent_req_nterror(req, status)) {
2167 return tevent_req_post(req, ev);
2170 if (src_fsp->fsp_name->st.st_ex_size < state->src_off + to_copy) {
2172 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
2173 * If the SourceOffset or SourceOffset + Length extends beyond
2174 * the end of file, the server SHOULD<240> treat this as a
2175 * STATUS_END_OF_FILE error.
2177 * <240> Section 3.3.5.15.6: Windows servers will return
2178 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
2180 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
2181 return tevent_req_post(req, ev);
2184 state->buf = talloc_array(state, uint8_t, num);
2185 if (tevent_req_nomem(state->buf, req)) {
2186 return tevent_req_post(req, ev);
2189 status = vfswrap_offload_write_loop(req);
2190 if (!NT_STATUS_IS_OK(status)) {
2191 tevent_req_nterror(req, status);
2192 return tevent_req_post(req, ev);
2198 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
2200 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
2202 struct vfswrap_offload_write_state *state = tevent_req_data(
2203 req, struct vfswrap_offload_write_state);
2204 struct tevent_req *subreq = NULL;
2205 struct lock_struct read_lck;
2209 * This is called under the context of state->src_fsp.
2212 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
2214 init_strict_lock_struct(state->src_fsp,
2215 state->src_fsp->op->global->open_persistent_id,
2217 state->next_io_size,
2221 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
2225 return NT_STATUS_FILE_LOCK_CONFLICT;
2228 subreq = SMB_VFS_PREAD_SEND(state,
2232 state->next_io_size,
2234 if (subreq == NULL) {
2235 return NT_STATUS_NO_MEMORY;
2237 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
2239 return NT_STATUS_OK;
2242 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
2244 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
2246 struct tevent_req *req = tevent_req_callback_data(
2247 subreq, struct tevent_req);
2248 struct vfswrap_offload_write_state *state = tevent_req_data(
2249 req, struct vfswrap_offload_write_state);
2250 struct vfs_aio_state aio_state;
2251 struct lock_struct write_lck;
2255 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
2256 TALLOC_FREE(subreq);
2258 DBG_ERR("read failed: %s\n", strerror(aio_state.error));
2259 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2262 if (nread != state->next_io_size) {
2263 DBG_ERR("Short read, only %zd of %zu\n",
2264 nread, state->next_io_size);
2265 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2269 state->src_off += nread;
2271 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2273 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2277 init_strict_lock_struct(state->dst_fsp,
2278 state->dst_fsp->op->global->open_persistent_id,
2280 state->next_io_size,
2284 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
2288 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
2292 subreq = SMB_VFS_PWRITE_SEND(state,
2296 state->next_io_size,
2298 if (subreq == NULL) {
2299 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2302 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
2305 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
2307 struct tevent_req *req = tevent_req_callback_data(
2308 subreq, struct tevent_req);
2309 struct vfswrap_offload_write_state *state = tevent_req_data(
2310 req, struct vfswrap_offload_write_state);
2311 struct vfs_aio_state aio_state;
2316 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
2317 TALLOC_FREE(subreq);
2318 if (nwritten == -1) {
2319 DBG_ERR("write failed: %s\n", strerror(aio_state.error));
2320 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2323 if (nwritten != state->next_io_size) {
2324 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
2325 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2329 state->dst_off += nwritten;
2331 if (state->remaining < nwritten) {
2332 /* Paranoia check */
2333 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2336 state->remaining -= nwritten;
2337 if (state->remaining == 0) {
2338 tevent_req_done(req);
2342 ok = change_to_user_and_service_by_fsp(state->src_fsp);
2344 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2348 status = vfswrap_offload_write_loop(req);
2349 if (!NT_STATUS_IS_OK(status)) {
2350 tevent_req_nterror(req, status);
2357 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
2358 struct tevent_req *req,
2361 struct vfswrap_offload_write_state *state = tevent_req_data(
2362 req, struct vfswrap_offload_write_state);
2365 if (tevent_req_is_nterror(req, &status)) {
2366 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
2368 tevent_req_received(req);
2372 *copied = state->to_copy;
2373 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
2374 tevent_req_received(req);
2376 return NT_STATUS_OK;
2379 static NTSTATUS vfswrap_fget_compression(struct vfs_handle_struct *handle,
2380 TALLOC_CTX *mem_ctx,
2381 struct files_struct *fsp,
2382 uint16_t *_compression_fmt)
2384 return NT_STATUS_INVALID_DEVICE_REQUEST;
2387 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
2388 TALLOC_CTX *mem_ctx,
2389 struct files_struct *fsp,
2390 uint16_t compression_fmt)
2392 return NT_STATUS_INVALID_DEVICE_REQUEST;
2395 /********************************************************************
2396 Given a stat buffer return the allocated size on disk, taking into
2397 account sparse files.
2398 ********************************************************************/
2399 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
2400 struct files_struct *fsp,
2401 const SMB_STRUCT_STAT *sbuf)
2405 START_PROFILE(syscall_get_alloc_size);
2407 if(S_ISDIR(sbuf->st_ex_mode)) {
2412 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2413 /* The type of st_blocksize is blkcnt_t which *MUST* be
2414 signed (according to POSIX) and can be less than 64-bits.
2415 Ensure when we're converting to 64 bits wide we don't
2417 #if defined(SIZEOF_BLKCNT_T_8)
2418 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2419 #elif defined(SIZEOF_BLKCNT_T_4)
2421 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2422 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2425 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2429 * Some file systems do not allocate a block for very
2430 * small files. But for non-empty file should report a
2434 uint64_t filesize = get_file_size_stat(sbuf);
2436 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2440 result = get_file_size_stat(sbuf);
2443 if (fsp && fsp->initial_allocation_size)
2444 result = MAX(result,fsp->initial_allocation_size);
2446 result = smb_roundup(handle->conn, result);
2449 END_PROFILE(syscall_get_alloc_size);
2453 static int vfswrap_unlinkat(vfs_handle_struct *handle,
2454 struct files_struct *dirfsp,
2455 const struct smb_filename *smb_fname,
2460 START_PROFILE(syscall_unlinkat);
2462 if (is_named_stream(smb_fname)) {
2466 result = unlinkat(fsp_get_pathref_fd(dirfsp),
2467 smb_fname->base_name,
2471 END_PROFILE(syscall_unlinkat);
2475 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2479 START_PROFILE(syscall_fchmod);
2481 if (!fsp->fsp_flags.is_pathref) {
2482 result = fchmod(fsp_get_io_fd(fsp), mode);
2483 END_PROFILE(syscall_fchmod);
2487 if (fsp->fsp_flags.have_proc_fds) {
2488 int fd = fsp_get_pathref_fd(fsp);
2489 const char *p = NULL;
2492 p = sys_proc_fd_path(fd, buf, sizeof(buf));
2494 result = chmod(p, mode);
2498 END_PROFILE(syscall_fchmod);
2503 * This is no longer a handle based call.
2505 result = chmod(fsp->fsp_name->base_name, mode);
2507 END_PROFILE(syscall_fchmod);
2511 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2516 START_PROFILE(syscall_fchown);
2517 result = fchown(fsp_get_io_fd(fsp), uid, gid);
2518 END_PROFILE(syscall_fchown);
2526 static int vfswrap_lchown(vfs_handle_struct *handle,
2527 const struct smb_filename *smb_fname,
2533 START_PROFILE(syscall_lchown);
2534 result = lchown(smb_fname->base_name, uid, gid);
2535 END_PROFILE(syscall_lchown);
2539 static int vfswrap_chdir(vfs_handle_struct *handle,
2540 const struct smb_filename *smb_fname)
2544 START_PROFILE(syscall_chdir);
2545 result = chdir(smb_fname->base_name);
2546 END_PROFILE(syscall_chdir);
2550 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2554 struct smb_filename *smb_fname = NULL;
2556 START_PROFILE(syscall_getwd);
2557 result = sys_getwd();
2558 END_PROFILE(syscall_getwd);
2560 if (result == NULL) {
2563 smb_fname = synthetic_smb_fname(ctx,
2570 * sys_getwd() *always* returns malloced memory.
2571 * We must free here to avoid leaks:
2572 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2578 /*********************************************************************
2579 nsec timestamp resolution call. Convert down to whatever the underlying
2580 system will support.
2581 **********************************************************************/
2583 static int vfswrap_fntimes(vfs_handle_struct *handle,
2585 struct smb_file_time *ft)
2588 struct timespec ts[2];
2589 struct timespec *times = NULL;
2591 START_PROFILE(syscall_fntimes);
2593 if (is_named_stream(fsp->fsp_name)) {
2599 if (is_omit_timespec(&ft->atime)) {
2600 ft->atime = fsp->fsp_name->st.st_ex_atime;
2603 if (is_omit_timespec(&ft->mtime)) {
2604 ft->mtime = fsp->fsp_name->st.st_ex_mtime;
2607 if (!is_omit_timespec(&ft->create_time)) {
2608 set_create_timespec_ea(fsp,
2612 if ((timespec_compare(&ft->atime,
2613 &fsp->fsp_name->st.st_ex_atime) == 0) &&
2614 (timespec_compare(&ft->mtime,
2615 &fsp->fsp_name->st.st_ex_mtime) == 0)) {
2627 if (!fsp->fsp_flags.is_pathref) {
2628 result = futimens(fsp_get_io_fd(fsp), times);
2632 if (fsp->fsp_flags.have_proc_fds) {
2633 int fd = fsp_get_pathref_fd(fsp);
2634 const char *p = NULL;
2637 p = sys_proc_fd_path(fd, buf, sizeof(buf));
2640 * The dirfd argument of utimensat is ignored when
2641 * pathname is an absolute path
2643 result = utimensat(AT_FDCWD, p, times, 0);
2652 * The fd is a pathref (opened with O_PATH) and there isn't fd to
2653 * path translation mechanism. Fallback to path based call.
2655 result = utimensat(AT_FDCWD, fsp->fsp_name->base_name, times, 0);
2658 END_PROFILE(syscall_fntimes);
2664 /*********************************************************************
2665 A version of ftruncate that will write the space on disk if strict
2667 **********************************************************************/
2669 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2671 off_t space_to_write;
2672 uint64_t space_avail;
2673 uint64_t bsize,dfree,dsize;
2676 SMB_STRUCT_STAT *pst;
2679 ok = vfs_valid_pwrite_range(len, 0);
2685 status = vfs_stat_fsp(fsp);
2686 if (!NT_STATUS_IS_OK(status)) {
2689 pst = &fsp->fsp_name->st;
2692 if (S_ISFIFO(pst->st_ex_mode))
2696 if (pst->st_ex_size == len)
2699 /* Shrink - just ftruncate. */
2700 if (pst->st_ex_size > len)
2701 return ftruncate(fsp_get_io_fd(fsp), len);
2703 space_to_write = len - pst->st_ex_size;
2705 /* for allocation try fallocate first. This can fail on some
2706 platforms e.g. when the filesystem doesn't support it and no
2707 emulation is being done by the libc (like on AIX with JFS1). In that
2708 case we do our own emulation. fallocate implementations can
2709 return ENOTSUP or EINVAL in cases like that. */
2710 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2711 if (ret == -1 && errno == ENOSPC) {
2717 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2718 "error %d. Falling back to slow manual allocation\n", errno));
2720 /* available disk space is enough or not? */
2722 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2723 /* space_avail is 1k blocks */
2724 if (space_avail == (uint64_t)-1 ||
2725 ((uint64_t)space_to_write/1024 > space_avail) ) {
2730 /* Write out the real space on disk. */
2731 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2739 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2742 SMB_STRUCT_STAT *pst;
2746 START_PROFILE(syscall_ftruncate);
2748 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->fsp_flags.is_sparse) {
2749 result = strict_allocate_ftruncate(handle, fsp, len);
2750 END_PROFILE(syscall_ftruncate);
2754 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2755 ftruncate if the system supports it. Then I discovered that
2756 you can have some filesystems that support ftruncate
2757 expansion and some that don't! On Linux fat can't do
2758 ftruncate extend but ext2 can. */
2760 result = ftruncate(fsp_get_io_fd(fsp), len);
2762 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2763 extend a file with ftruncate. Provide alternate implementation
2766 /* Do an fstat to see if the file is longer than the requested
2767 size in which case the ftruncate above should have
2768 succeeded or shorter, in which case seek to len - 1 and
2769 write 1 byte of zero */
2770 status = vfs_stat_fsp(fsp);
2771 if (!NT_STATUS_IS_OK(status)) {
2775 /* We need to update the files_struct after successful ftruncate */
2780 pst = &fsp->fsp_name->st;
2783 if (S_ISFIFO(pst->st_ex_mode)) {
2789 if (pst->st_ex_size == len) {
2794 if (pst->st_ex_size > len) {
2795 /* the ftruncate should have worked */
2799 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2807 END_PROFILE(syscall_ftruncate);
2811 static int vfswrap_fallocate(vfs_handle_struct *handle,
2819 START_PROFILE(syscall_fallocate);
2821 result = sys_posix_fallocate(fsp_get_io_fd(fsp), offset, len);
2823 * posix_fallocate returns 0 on success, errno on error
2824 * and doesn't set errno. Make it behave like fallocate()
2825 * which returns -1, and sets errno on failure.
2832 /* sys_fallocate handles filtering of unsupported mode flags */
2833 result = sys_fallocate(fsp_get_io_fd(fsp), mode, offset, len);
2835 END_PROFILE(syscall_fallocate);
2839 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2843 START_PROFILE(syscall_fcntl_lock);
2845 if (fsp->fsp_flags.use_ofd_locks) {
2846 op = map_process_lock_to_ofd_lock(op);
2849 result = fcntl_lock(fsp_get_io_fd(fsp), op, offset, count, type);
2850 END_PROFILE(syscall_fcntl_lock);
2854 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2855 uint32_t share_access, uint32_t access_mask)
2857 START_PROFILE(syscall_kernel_flock);
2858 kernel_flock(fsp_get_io_fd(fsp), share_access, access_mask);
2859 END_PROFILE(syscall_kernel_flock);
2863 static int vfswrap_fcntl(vfs_handle_struct *handle, files_struct *fsp, int cmd,
2867 va_list dup_cmd_arg;
2871 START_PROFILE(syscall_fcntl);
2873 va_copy(dup_cmd_arg, cmd_arg);
2879 #if defined(HAVE_OFD_LOCKS)
2884 #if defined(HAVE_F_OWNER_EX)
2888 #if defined(HAVE_RW_HINTS)
2891 case F_GET_FILE_RW_HINT:
2892 case F_SET_FILE_RW_HINT:
2894 argp = va_arg(dup_cmd_arg, void *);
2895 result = sys_fcntl_ptr(fsp_get_io_fd(fsp), cmd, argp);
2898 val = va_arg(dup_cmd_arg, int);
2899 result = sys_fcntl_int(fsp_get_io_fd(fsp), cmd, val);
2902 va_end(dup_cmd_arg);
2904 END_PROFILE(syscall_fcntl);
2908 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2913 START_PROFILE(syscall_fcntl_getlock);
2915 if (fsp->fsp_flags.use_ofd_locks) {
2916 op = map_process_lock_to_ofd_lock(op);
2919 result = fcntl_getlock(fsp_get_io_fd(fsp), op, poffset, pcount, ptype, ppid);
2920 END_PROFILE(syscall_fcntl_getlock);
2924 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2929 START_PROFILE(syscall_linux_setlease);
2931 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2932 result = linux_setlease(fsp_get_io_fd(fsp), leasetype);
2936 END_PROFILE(syscall_linux_setlease);
2940 static int vfswrap_symlinkat(vfs_handle_struct *handle,
2941 const struct smb_filename *link_target,
2942 struct files_struct *dirfsp,
2943 const struct smb_filename *new_smb_fname)
2947 START_PROFILE(syscall_symlinkat);
2949 result = symlinkat(link_target->base_name,
2950 fsp_get_pathref_fd(dirfsp),
2951 new_smb_fname->base_name);
2952 END_PROFILE(syscall_symlinkat);
2956 static int vfswrap_readlinkat(vfs_handle_struct *handle,
2957 const struct files_struct *dirfsp,
2958 const struct smb_filename *smb_fname,
2964 START_PROFILE(syscall_readlinkat);
2966 result = readlinkat(fsp_get_pathref_fd(dirfsp),
2967 smb_fname->base_name,
2971 END_PROFILE(syscall_readlinkat);
2975 static int vfswrap_linkat(vfs_handle_struct *handle,
2976 files_struct *srcfsp,
2977 const struct smb_filename *old_smb_fname,
2978 files_struct *dstfsp,
2979 const struct smb_filename *new_smb_fname,
2984 START_PROFILE(syscall_linkat);
2986 result = linkat(fsp_get_pathref_fd(srcfsp),
2987 old_smb_fname->base_name,
2988 fsp_get_pathref_fd(dstfsp),
2989 new_smb_fname->base_name,
2992 END_PROFILE(syscall_linkat);
2996 static int vfswrap_mknodat(vfs_handle_struct *handle,
2997 files_struct *dirfsp,
2998 const struct smb_filename *smb_fname,
3004 START_PROFILE(syscall_mknodat);
3006 result = sys_mknodat(fsp_get_pathref_fd(dirfsp),
3007 smb_fname->base_name,
3011 END_PROFILE(syscall_mknodat);
3015 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
3017 const struct smb_filename *smb_fname)
3020 struct smb_filename *result_fname = NULL;
3022 START_PROFILE(syscall_realpath);
3023 result = sys_realpath(smb_fname->base_name);
3024 END_PROFILE(syscall_realpath);
3026 result_fname = synthetic_smb_fname(ctx,
3034 return result_fname;
3037 static int vfswrap_chflags(vfs_handle_struct *handle,
3038 const struct smb_filename *smb_fname,
3042 return chflags(smb_fname->base_name, flags);
3049 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
3050 const SMB_STRUCT_STAT *sbuf)
3054 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
3058 key.devid = sbuf->st_ex_dev;
3059 key.inode = sbuf->st_ex_ino;
3060 /* key.extid is unused by default. */
3065 static uint64_t vfswrap_fs_file_id(struct vfs_handle_struct *handle,
3066 const SMB_STRUCT_STAT *psbuf)
3070 if (!(psbuf->st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)) {
3071 return psbuf->st_ex_file_id;
3074 if (handle->conn->base_share_dev == psbuf->st_ex_dev) {
3075 return (uint64_t)psbuf->st_ex_ino;
3079 file_id = ((psbuf->st_ex_ino) & UINT32_MAX);
3082 file_id |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32;
3087 static NTSTATUS vfswrap_fstreaminfo(vfs_handle_struct *handle,
3088 struct files_struct *fsp,
3089 TALLOC_CTX *mem_ctx,
3090 unsigned int *pnum_streams,
3091 struct stream_struct **pstreams)
3093 struct stream_struct *tmp_streams = NULL;
3094 unsigned int num_streams = *pnum_streams;
3095 struct stream_struct *streams = *pstreams;
3098 if (fsp->fsp_flags.is_directory) {
3100 * No default streams on directories
3104 status = vfs_stat_fsp(fsp);
3105 if (!NT_STATUS_IS_OK(status)) {
3109 if (num_streams + 1 < 1) {
3111 return NT_STATUS_INVALID_PARAMETER;
3114 tmp_streams = talloc_realloc(mem_ctx,
3116 struct stream_struct,
3118 if (tmp_streams == NULL) {
3119 return NT_STATUS_NO_MEMORY;
3121 tmp_streams[num_streams].name = talloc_strdup(tmp_streams, "::$DATA");
3122 if (tmp_streams[num_streams].name == NULL) {
3123 return NT_STATUS_NO_MEMORY;
3125 tmp_streams[num_streams].size = fsp->fsp_name->st.st_ex_size;
3126 tmp_streams[num_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(
3129 &fsp->fsp_name->st);
3132 *pnum_streams = num_streams;
3133 *pstreams = tmp_streams;
3135 return NT_STATUS_OK;
3138 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
3139 const struct smb_filename *path,
3141 TALLOC_CTX *mem_ctx,
3145 * Don't fall back to get_real_filename so callers can differentiate
3146 * between a full directory scan and an actual case-insensitive stat.
3152 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
3153 const struct smb_filename *smb_fname)
3155 return handle->conn->connectpath;
3158 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
3159 struct byte_range_lock *br_lck,
3160 struct lock_struct *plock)
3162 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3164 /* Note: blr is not used in the default implementation. */
3165 return brl_lock_windows_default(br_lck, plock);
3168 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
3169 struct byte_range_lock *br_lck,
3170 const struct lock_struct *plock)
3172 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3174 return brl_unlock_windows_default(br_lck, plock);
3177 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
3179 struct lock_struct *plock)
3181 SMB_ASSERT(plock->lock_type == READ_LOCK ||
3182 plock->lock_type == WRITE_LOCK);
3184 return strict_lock_check_default(fsp, plock);
3187 /* NT ACL operations. */
3189 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
3191 uint32_t security_info,
3192 TALLOC_CTX *mem_ctx,
3193 struct security_descriptor **ppdesc)
3197 START_PROFILE(fget_nt_acl);
3198 result = posix_fget_nt_acl(fsp, security_info,
3200 END_PROFILE(fget_nt_acl);
3204 static NTSTATUS vfswrap_get_nt_acl_at(vfs_handle_struct *handle,
3205 struct files_struct *dirfsp,
3206 const struct smb_filename *smb_fname,
3207 uint32_t security_info,
3208 TALLOC_CTX *mem_ctx,
3209 struct security_descriptor **ppdesc)
3213 START_PROFILE(get_nt_acl_at);
3215 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
3217 result = posix_get_nt_acl(handle->conn,
3222 END_PROFILE(get_nt_acl_at);
3226 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
3230 START_PROFILE(fset_nt_acl);
3231 result = set_nt_acl(fsp, security_info_sent, psd);
3232 END_PROFILE(fset_nt_acl);
3236 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
3237 struct smb_filename *file,
3238 struct security_acl *sacl,
3239 uint32_t access_requested,
3240 uint32_t access_denied)
3242 return NT_STATUS_OK; /* Nothing to do here ... */
3245 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
3246 const struct smb_filename *smb_fname,
3247 SMB_ACL_TYPE_T type,
3248 TALLOC_CTX *mem_ctx)
3250 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
3253 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
3255 TALLOC_CTX *mem_ctx)
3257 return sys_acl_get_fd(handle, fsp, mem_ctx);
3260 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle,
3262 SMB_ACL_TYPE_T type,
3265 if (!fsp->fsp_flags.is_pathref &&
3266 type == SMB_ACL_TYPE_ACCESS)
3268 return sys_acl_set_fd(handle, fsp, theacl);
3271 if (fsp->fsp_flags.have_proc_fds) {
3272 int fd = fsp_get_pathref_fd(fsp);
3273 struct smb_filename smb_fname;
3274 const char *p = NULL;
3277 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3282 smb_fname = (struct smb_filename) {
3286 return sys_acl_set_file(handle,
3293 * This is no longer a handle based call.
3295 return sys_acl_set_file(handle,
3301 static int vfswrap_sys_acl_delete_def_fd(vfs_handle_struct *handle,
3304 return sys_acl_delete_def_fd(handle, fsp);
3307 /****************************************************************
3308 Extended attribute operations.
3309 *****************************************************************/
3311 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
3312 const struct smb_filename *smb_fname,
3317 return getxattr(smb_fname->base_name, name, value, size);
3320 struct vfswrap_getxattrat_state {
3321 struct tevent_context *ev;
3322 files_struct *dir_fsp;
3323 const struct smb_filename *smb_fname;
3326 * The following variables are talloced off "state" which is protected
3327 * by a destructor and thus are guaranteed to be safe to be used in the
3328 * job function in the worker thread.
3331 const char *xattr_name;
3332 uint8_t *xattr_value;
3333 struct security_unix_token *token;
3336 struct vfs_aio_state vfs_aio_state;
3337 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
3340 static int vfswrap_getxattrat_state_destructor(
3341 struct vfswrap_getxattrat_state *state)
3346 static void vfswrap_getxattrat_do_sync(struct tevent_req *req);
3347 static void vfswrap_getxattrat_do_async(void *private_data);
3348 static void vfswrap_getxattrat_done(struct tevent_req *subreq);
3350 static struct tevent_req *vfswrap_getxattrat_send(
3351 TALLOC_CTX *mem_ctx,
3352 struct tevent_context *ev,
3353 struct vfs_handle_struct *handle,
3354 files_struct *dir_fsp,
3355 const struct smb_filename *smb_fname,
3356 const char *xattr_name,
3359 struct tevent_req *req = NULL;
3360 struct tevent_req *subreq = NULL;
3361 struct vfswrap_getxattrat_state *state = NULL;
3362 size_t max_threads = 0;
3363 bool have_per_thread_cwd = false;
3364 bool have_per_thread_creds = false;
3365 bool do_async = false;
3367 req = tevent_req_create(mem_ctx, &state,
3368 struct vfswrap_getxattrat_state);
3372 *state = (struct vfswrap_getxattrat_state) {
3375 .smb_fname = smb_fname,
3378 max_threads = pthreadpool_tevent_max_threads(dir_fsp->conn->sconn->pool);
3379 if (max_threads >= 1) {
3381 * We need a non sync threadpool!
3383 have_per_thread_cwd = per_thread_cwd_supported();
3385 #ifdef HAVE_LINUX_THREAD_CREDENTIALS
3386 have_per_thread_creds = true;
3388 if (have_per_thread_cwd && have_per_thread_creds) {
3392 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat, profile_p,
3393 state->profile_bytes, 0);
3395 if (fsp_get_pathref_fd(dir_fsp) == -1) {
3396 DBG_ERR("Need a valid directory fd\n");
3397 tevent_req_error(req, EINVAL);
3398 return tevent_req_post(req, ev);
3401 if (alloc_hint > 0) {
3402 state->xattr_value = talloc_zero_array(state,
3405 if (tevent_req_nomem(state->xattr_value, req)) {
3406 return tevent_req_post(req, ev);
3411 vfswrap_getxattrat_do_sync(req);
3412 return tevent_req_post(req, ev);
3416 * Now allocate all parameters from a memory context that won't go away
3417 * no matter what. These paremeters will get used in threads and we
3418 * can't reliably cancel threads, so all buffers passed to the threads
3419 * must not be freed before all referencing threads terminate.
3422 state->name = talloc_strdup(state, smb_fname->base_name);
3423 if (tevent_req_nomem(state->name, req)) {
3424 return tevent_req_post(req, ev);
3427 state->xattr_name = talloc_strdup(state, xattr_name);
3428 if (tevent_req_nomem(state->xattr_name, req)) {
3429 return tevent_req_post(req, ev);
3433 * This is a hot codepath so at first glance one might think we should
3434 * somehow optimize away the token allocation and do a
3435 * talloc_reference() or similar black magic instead. But due to the
3436 * talloc_stackframe pool per SMB2 request this should be a simple copy
3437 * without a malloc in most cases.
3439 if (geteuid() == sec_initial_uid()) {
3440 state->token = root_unix_token(state);
3442 state->token = copy_unix_token(
3444 dir_fsp->conn->session_info->unix_token);
3446 if (tevent_req_nomem(state->token, req)) {
3447 return tevent_req_post(req, ev);
3450 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3452 subreq = pthreadpool_tevent_job_send(
3455 dir_fsp->conn->sconn->pool,
3456 vfswrap_getxattrat_do_async,
3458 if (tevent_req_nomem(subreq, req)) {
3459 return tevent_req_post(req, ev);
3461 tevent_req_set_callback(subreq, vfswrap_getxattrat_done, req);
3463 talloc_set_destructor(state, vfswrap_getxattrat_state_destructor);
3468 static void vfswrap_getxattrat_do_sync(struct tevent_req *req)
3470 struct vfswrap_getxattrat_state *state = tevent_req_data(
3471 req, struct vfswrap_getxattrat_state);
3473 char *tofree = NULL;
3474 char pathbuf[PATH_MAX+1];
3478 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
3479 state->smb_fname->base_name,
3484 if (pathlen == -1) {
3485 tevent_req_error(req, ENOMEM);
3489 state->xattr_size = getxattr(path,
3492 talloc_array_length(state->xattr_value));
3494 TALLOC_FREE(tofree);
3495 if (state->xattr_size == -1) {
3496 tevent_req_error(req, err);
3500 tevent_req_done(req);
3504 static void vfswrap_getxattrat_do_async(void *private_data)
3506 struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3507 private_data, struct vfswrap_getxattrat_state);
3508 struct timespec start_time;
3509 struct timespec end_time;
3512 PROFILE_TIMESTAMP(&start_time);
3513 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
3516 * Here we simulate a getxattrat()
3517 * call using fchdir();getxattr()
3520 per_thread_cwd_activate();
3522 /* Become the correct credential on this thread. */
3523 ret = set_thread_credentials(state->token->uid,
3525 (size_t)state->token->ngroups,
3526 state->token->groups);
3528 state->xattr_size = -1;
3529 state->vfs_aio_state.error = errno;
3533 ret = fchdir(fsp_get_pathref_fd(state->dir_fsp));
3535 state->xattr_size = -1;
3536 state->vfs_aio_state.error = errno;
3540 state->xattr_size = getxattr(state->name,
3543 talloc_array_length(state->xattr_value));
3544 if (state->xattr_size == -1) {
3545 state->vfs_aio_state.error = errno;
3549 PROFILE_TIMESTAMP(&end_time);
3550 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
3551 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3554 static void vfswrap_getxattrat_done(struct tevent_req *subreq)
3556 struct tevent_req *req = tevent_req_callback_data(
3557 subreq, struct tevent_req);
3558 struct vfswrap_getxattrat_state *state = tevent_req_data(
3559 req, struct vfswrap_getxattrat_state);
3564 * Make sure we run as the user again
3566 ok = change_to_user_and_service_by_fsp(state->dir_fsp);
3569 ret = pthreadpool_tevent_job_recv(subreq);
3570 TALLOC_FREE(subreq);
3571 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
3572 talloc_set_destructor(state, NULL);
3574 if (ret != EAGAIN) {
3575 tevent_req_error(req, ret);
3579 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
3580 * means the lower level pthreadpool failed to create a new
3581 * thread. Fallback to sync processing in that case to allow
3582 * some progress for the client.
3584 vfswrap_getxattrat_do_sync(req);
3588 if (state->xattr_size == -1) {
3589 tevent_req_error(req, state->vfs_aio_state.error);
3593 if (state->xattr_value == NULL) {
3595 * The caller only wanted the size.
3597 tevent_req_done(req);
3602 * shrink the buffer to the returned size.
3603 * (can't fail). It means NULL if size is 0.
3605 state->xattr_value = talloc_realloc(state,
3610 tevent_req_done(req);
3613 static ssize_t vfswrap_getxattrat_recv(struct tevent_req *req,
3614 struct vfs_aio_state *aio_state,
3615 TALLOC_CTX *mem_ctx,
3616 uint8_t **xattr_value)
3618 struct vfswrap_getxattrat_state *state = tevent_req_data(
3619 req, struct vfswrap_getxattrat_state);
3622 if (tevent_req_is_unix_error(req, &aio_state->error)) {
3623 tevent_req_received(req);
3627 *aio_state = state->vfs_aio_state;
3628 xattr_size = state->xattr_size;
3629 if (xattr_value != NULL) {
3630 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
3633 tevent_req_received(req);
3637 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle,
3638 struct files_struct *fsp,
3643 int fd = fsp_get_pathref_fd(fsp);
3645 if (!fsp->fsp_flags.is_pathref) {
3646 return fgetxattr(fd, name, value, size);
3649 if (fsp->fsp_flags.have_proc_fds) {
3650 const char *p = NULL;
3653 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3658 return getxattr(p, name, value, size);
3662 * This is no longer a handle based call.
3664 return getxattr(fsp->fsp_name->base_name, name, value, size);
3667 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
3669 int fd = fsp_get_pathref_fd(fsp);
3671 if (!fsp->fsp_flags.is_pathref) {
3672 return flistxattr(fd, list, size);
3675 if (fsp->fsp_flags.have_proc_fds) {
3676 const char *p = NULL;
3679 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3684 return listxattr(p, list, size);
3688 * This is no longer a handle based call.
3690 return listxattr(fsp->fsp_name->base_name, list, size);
3693 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
3695 int fd = fsp_get_pathref_fd(fsp);
3697 if (!fsp->fsp_flags.is_pathref) {
3698 return fremovexattr(fd, name);
3701 if (fsp->fsp_flags.have_proc_fds) {
3702 const char *p = NULL;
3705 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3710 return removexattr(p, name);
3714 * This is no longer a handle based call.
3716 return removexattr(fsp->fsp_name->base_name, name);
3719 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
3721 int fd = fsp_get_pathref_fd(fsp);
3723 if (!fsp->fsp_flags.is_pathref) {
3724 return fsetxattr(fd, name, value, size, flags);
3727 if (fsp->fsp_flags.have_proc_fds) {
3728 const char *p = NULL;
3731 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3736 return setxattr(p, name, value, size, flags);
3740 * This is no longer a handle based call.
3742 return setxattr(fsp->fsp_name->base_name, name, value, size, flags);
3745 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
3750 static bool vfswrap_is_offline(struct connection_struct *conn,
3751 const struct smb_filename *fname)
3755 bool offline = false;
3757 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
3761 if (!lp_dmapi_support(SNUM(conn)) || !dmapi_have_session()) {
3762 #if defined(ENOTSUP)
3768 status = get_full_smb_filename(talloc_tos(), fname, &path);
3769 if (!NT_STATUS_IS_OK(status)) {
3770 errno = map_errno_from_nt_status(status);
3774 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
3781 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
3782 struct files_struct *fsp,
3783 TALLOC_CTX *mem_ctx,
3786 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
3789 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
3790 struct files_struct *fsp,
3791 const DATA_BLOB old_cookie,
3792 TALLOC_CTX *mem_ctx,
3793 DATA_BLOB *new_cookie)
3795 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
3799 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
3800 struct smb_request *smb1req,
3801 struct smbXsrv_open *op,
3802 const DATA_BLOB old_cookie,
3803 TALLOC_CTX *mem_ctx,
3804 struct files_struct **fsp,
3805 DATA_BLOB *new_cookie)
3807 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
3808 old_cookie, mem_ctx,
3812 static struct vfs_fn_pointers vfs_default_fns = {
3813 /* Disk operations */
3815 .connect_fn = vfswrap_connect,
3816 .disconnect_fn = vfswrap_disconnect,
3817 .disk_free_fn = vfswrap_disk_free,
3818 .get_quota_fn = vfswrap_get_quota,
3819 .set_quota_fn = vfswrap_set_quota,
3820 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3821 .statvfs_fn = vfswrap_statvfs,
3822 .fs_capabilities_fn = vfswrap_fs_capabilities,
3823 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3824 .create_dfs_pathat_fn = vfswrap_create_dfs_pathat,
3825 .read_dfs_pathat_fn = vfswrap_read_dfs_pathat,
3826 .snap_check_path_fn = vfswrap_snap_check_path,
3827 .snap_create_fn = vfswrap_snap_create,
3828 .snap_delete_fn = vfswrap_snap_delete,
3830 /* Directory operations */
3832 .fdopendir_fn = vfswrap_fdopendir,
3833 .readdir_fn = vfswrap_readdir,
3834 .freaddir_attr_fn = vfswrap_freaddir_attr,
3835 .seekdir_fn = vfswrap_seekdir,
3836 .telldir_fn = vfswrap_telldir,
3837 .rewind_dir_fn = vfswrap_rewinddir,
3838 .mkdirat_fn = vfswrap_mkdirat,
3839 .closedir_fn = vfswrap_closedir,
3841 /* File operations */
3843 .openat_fn = vfswrap_openat,
3844 .create_file_fn = vfswrap_create_file,
3845 .close_fn = vfswrap_close,
3846 .pread_fn = vfswrap_pread,
3847 .pread_send_fn = vfswrap_pread_send,
3848 .pread_recv_fn = vfswrap_pread_recv,
3849 .pwrite_fn = vfswrap_pwrite,
3850 .pwrite_send_fn = vfswrap_pwrite_send,
3851 .pwrite_recv_fn = vfswrap_pwrite_recv,
3852 .lseek_fn = vfswrap_lseek,
3853 .sendfile_fn = vfswrap_sendfile,
3854 .recvfile_fn = vfswrap_recvfile,
3855 .renameat_fn = vfswrap_renameat,
3856 .fsync_send_fn = vfswrap_fsync_send,
3857 .fsync_recv_fn = vfswrap_fsync_recv,
3858 .stat_fn = vfswrap_stat,
3859 .fstat_fn = vfswrap_fstat,
3860 .lstat_fn = vfswrap_lstat,
3861 .get_alloc_size_fn = vfswrap_get_alloc_size,
3862 .unlinkat_fn = vfswrap_unlinkat,
3863 .fchmod_fn = vfswrap_fchmod,
3864 .fchown_fn = vfswrap_fchown,
3865 .lchown_fn = vfswrap_lchown,
3866 .chdir_fn = vfswrap_chdir,
3867 .getwd_fn = vfswrap_getwd,
3868 .fntimes_fn = vfswrap_fntimes,
3869 .ftruncate_fn = vfswrap_ftruncate,
3870 .fallocate_fn = vfswrap_fallocate,
3871 .lock_fn = vfswrap_lock,
3872 .kernel_flock_fn = vfswrap_kernel_flock,
3873 .fcntl_fn = vfswrap_fcntl,
3874 .linux_setlease_fn = vfswrap_linux_setlease,
3875 .getlock_fn = vfswrap_getlock,
3876 .symlinkat_fn = vfswrap_symlinkat,
3877 .readlinkat_fn = vfswrap_readlinkat,
3878 .linkat_fn = vfswrap_linkat,
3879 .mknodat_fn = vfswrap_mknodat,
3880 .realpath_fn = vfswrap_realpath,
3881 .chflags_fn = vfswrap_chflags,
3882 .file_id_create_fn = vfswrap_file_id_create,
3883 .fs_file_id_fn = vfswrap_fs_file_id,
3884 .fstreaminfo_fn = vfswrap_fstreaminfo,
3885 .get_real_filename_fn = vfswrap_get_real_filename,
3886 .connectpath_fn = vfswrap_connectpath,
3887 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
3888 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3889 .strict_lock_check_fn = vfswrap_strict_lock_check,
3890 .translate_name_fn = vfswrap_translate_name,
3891 .parent_pathname_fn = vfswrap_parent_pathname,
3892 .fsctl_fn = vfswrap_fsctl,
3893 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
3894 .get_dos_attributes_send_fn = vfswrap_get_dos_attributes_send,
3895 .get_dos_attributes_recv_fn = vfswrap_get_dos_attributes_recv,
3896 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
3897 .offload_read_send_fn = vfswrap_offload_read_send,
3898 .offload_read_recv_fn = vfswrap_offload_read_recv,
3899 .offload_write_send_fn = vfswrap_offload_write_send,
3900 .offload_write_recv_fn = vfswrap_offload_write_recv,
3901 .fget_compression_fn = vfswrap_fget_compression,
3902 .set_compression_fn = vfswrap_set_compression,
3904 /* NT ACL operations. */
3906 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
3907 .get_nt_acl_at_fn = vfswrap_get_nt_acl_at,
3908 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
3909 .audit_file_fn = vfswrap_audit_file,
3911 /* POSIX ACL operations. */
3913 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
3914 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3915 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
3916 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3917 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3918 .sys_acl_delete_def_fd_fn = vfswrap_sys_acl_delete_def_fd,
3920 /* EA operations. */
3921 .getxattr_fn = vfswrap_getxattr,
3922 .getxattrat_send_fn = vfswrap_getxattrat_send,
3923 .getxattrat_recv_fn = vfswrap_getxattrat_recv,
3924 .fgetxattr_fn = vfswrap_fgetxattr,
3925 .flistxattr_fn = vfswrap_flistxattr,
3926 .fremovexattr_fn = vfswrap_fremovexattr,
3927 .fsetxattr_fn = vfswrap_fsetxattr,
3929 /* aio operations */
3930 .aio_force_fn = vfswrap_aio_force,
3932 /* durable handle operations */
3933 .durable_cookie_fn = vfswrap_durable_cookie,
3934 .durable_disconnect_fn = vfswrap_durable_disconnect,
3935 .durable_reconnect_fn = vfswrap_durable_reconnect,
3939 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3942 * Here we need to implement every call!
3944 * As this is the end of the vfs module chain.
3946 smb_vfs_assert_all_fns(&vfs_default_fns, DEFAULT_VFS_MODULE_NAME);
3947 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3948 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);