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_readdir_attr(struct vfs_handle_struct *handle,
635 const struct smb_filename *fname,
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 * Implement the default fsctl operation.
1331 static bool vfswrap_logged_ioctl_message = false;
1333 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1334 struct files_struct *fsp,
1337 uint16_t req_flags, /* Needed for UNICODE ... */
1338 const uint8_t *_in_data,
1340 uint8_t **_out_data,
1341 uint32_t max_out_len,
1344 const char *in_data = (const char *)_in_data;
1345 char **out_data = (char **)_out_data;
1349 case FSCTL_SET_SPARSE:
1351 bool set_sparse = true;
1353 if (in_len >= 1 && in_data[0] == 0) {
1357 status = file_set_sparse(handle->conn, fsp, set_sparse);
1359 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1360 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1361 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1362 nt_errstr(status)));
1367 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1369 unsigned char objid[16];
1370 char *return_data = NULL;
1372 /* This should return the object-id on this file.
1373 * I think I'll make this be the inode+dev. JRA.
1376 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1377 fsp_fnum_dbg(fsp)));
1379 *out_len = MIN(max_out_len, 64);
1381 /* Hmmm, will this cause problems if less data asked for? */
1382 return_data = talloc_array(ctx, char, 64);
1383 if (return_data == NULL) {
1384 return NT_STATUS_NO_MEMORY;
1387 /* For backwards compatibility only store the dev/inode. */
1388 push_file_id_16(return_data, &fsp->file_id);
1389 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1390 push_file_id_16(return_data+32, &fsp->file_id);
1391 memset(return_data+48, 0, 16);
1392 *out_data = return_data;
1393 return NT_STATUS_OK;
1396 case FSCTL_GET_REPARSE_POINT:
1398 status = fsctl_get_reparse_point(
1399 fsp, ctx, out_data, max_out_len, out_len);
1403 case FSCTL_SET_REPARSE_POINT:
1405 status = fsctl_set_reparse_point(fsp, ctx, _in_data, in_len);
1409 case FSCTL_DELETE_REPARSE_POINT:
1411 status = fsctl_del_reparse_point(fsp, ctx, _in_data, in_len);
1415 case FSCTL_GET_SHADOW_COPY_DATA:
1418 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1419 * and return their volume names. If max_data_count is 16, then it is just
1420 * asking for the number of volumes and length of the combined names.
1422 * pdata is the data allocated by our caller, but that uses
1423 * total_data_count (which is 0 in our case) rather than max_data_count.
1424 * Allocate the correct amount and return the pointer to let
1425 * it be deallocated when we return.
1427 struct shadow_copy_data *shadow_data = NULL;
1428 bool labels = False;
1429 uint32_t labels_data_count = 0;
1431 char *cur_pdata = NULL;
1433 if (max_out_len < 16) {
1434 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1436 return NT_STATUS_INVALID_PARAMETER;
1439 if (max_out_len > 16) {
1443 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1444 if (shadow_data == NULL) {
1445 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1446 return NT_STATUS_NO_MEMORY;
1450 * Call the VFS routine to actually do the work.
1452 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1455 /* broken module didn't set errno on error */
1456 status = NT_STATUS_UNSUCCESSFUL;
1458 status = map_nt_error_from_unix(errno);
1459 if (NT_STATUS_EQUAL(status,
1460 NT_STATUS_NOT_SUPPORTED)) {
1464 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1465 "connectpath %s, failed - %s.\n",
1466 fsp->conn->connectpath,
1467 nt_errstr(status)));
1468 TALLOC_FREE(shadow_data);
1472 labels_data_count = (shadow_data->num_volumes * 2 *
1473 sizeof(SHADOW_COPY_LABEL)) + 2;
1478 *out_len = 12 + labels_data_count;
1481 if (max_out_len < *out_len) {
1482 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1483 max_out_len, *out_len));
1484 TALLOC_FREE(shadow_data);
1485 return NT_STATUS_BUFFER_TOO_SMALL;
1488 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1489 if (cur_pdata == NULL) {
1490 TALLOC_FREE(shadow_data);
1491 return NT_STATUS_NO_MEMORY;
1494 *out_data = cur_pdata;
1496 /* num_volumes 4 bytes */
1497 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1500 /* num_labels 4 bytes */
1501 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1504 /* needed_data_count 4 bytes */
1505 SIVAL(cur_pdata, 8, labels_data_count);
1509 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1510 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1511 if (labels && shadow_data->labels) {
1512 for (i=0; i<shadow_data->num_volumes; i++) {
1514 status = srvstr_push(cur_pdata, req_flags,
1515 cur_pdata, shadow_data->labels[i],
1516 2 * sizeof(SHADOW_COPY_LABEL),
1517 STR_UNICODE|STR_TERMINATE, &len);
1518 if (!NT_STATUS_IS_OK(status)) {
1519 TALLOC_FREE(*out_data);
1520 TALLOC_FREE(shadow_data);
1523 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1524 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1528 TALLOC_FREE(shadow_data);
1530 return NT_STATUS_OK;
1533 case FSCTL_FIND_FILES_BY_SID:
1535 /* pretend this succeeded -
1537 * we have to send back a list with all files owned by this SID
1539 * but I have to check that --metze
1543 struct dom_sid_buf buf;
1547 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1548 fsp_fnum_dbg(fsp)));
1551 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1552 return NT_STATUS_INVALID_PARAMETER;
1555 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1557 /* unknown 4 bytes: this is not the length of the sid :-( */
1558 /*unknown = IVAL(pdata,0);*/
1560 ret = sid_parse(_in_data + 4, sid_len, &sid);
1562 return NT_STATUS_INVALID_PARAMETER;
1564 DEBUGADD(10, ("for SID: %s\n",
1565 dom_sid_str_buf(&sid, &buf)));
1567 if (!sid_to_uid(&sid, &uid)) {
1568 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1569 dom_sid_str_buf(&sid, &buf),
1570 (unsigned long)sid_len));
1574 /* we can take a look at the find source :-)
1576 * find ./ -uid $uid -name '*' is what we need here
1579 * and send 4bytes len and then NULL terminated unicode strings
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 * but I don't know how to deal with the paged results
1586 * (maybe we can hang the result anywhere in the fsp struct)
1588 * we don't send all files at once
1589 * and at the next we should *not* start from the beginning,
1590 * so we have to cache the result
1595 /* this works for now... */
1596 return NT_STATUS_OK;
1599 case FSCTL_QUERY_ALLOCATED_RANGES:
1601 /* FIXME: This is just a dummy reply, telling that all of the
1602 * file is allocated. MKS cp needs that.
1603 * Adding the real allocated ranges via FIEMAP on Linux
1604 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1605 * this FSCTL correct for sparse files.
1607 uint64_t offset, length;
1608 char *out_data_tmp = NULL;
1611 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1613 return NT_STATUS_INVALID_PARAMETER;
1616 if (max_out_len < 16) {
1617 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1619 return NT_STATUS_INVALID_PARAMETER;
1622 offset = BVAL(in_data,0);
1623 length = BVAL(in_data,8);
1625 if (offset + length < offset) {
1626 /* No 64-bit integer wrap. */
1627 return NT_STATUS_INVALID_PARAMETER;
1630 /* Shouldn't this be SMB_VFS_STAT ... ? */
1631 status = vfs_stat_fsp(fsp);
1632 if (!NT_STATUS_IS_OK(status)) {
1637 out_data_tmp = talloc_array(ctx, char, *out_len);
1638 if (out_data_tmp == NULL) {
1639 DEBUG(10, ("unable to allocate memory for response\n"));
1640 return NT_STATUS_NO_MEMORY;
1643 if (offset > fsp->fsp_name->st.st_ex_size ||
1644 fsp->fsp_name->st.st_ex_size == 0 ||
1646 memset(out_data_tmp, 0, *out_len);
1648 uint64_t end = offset + length;
1649 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1650 SBVAL(out_data_tmp, 0, 0);
1651 SBVAL(out_data_tmp, 8, end);
1654 *out_data = out_data_tmp;
1656 return NT_STATUS_OK;
1659 case FSCTL_IS_VOLUME_DIRTY:
1661 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1662 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1664 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1665 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1667 return NT_STATUS_INVALID_PARAMETER;
1672 * Only print once ... unfortunately there could be lots of
1673 * different FSCTLs that are called.
1675 if (!vfswrap_logged_ioctl_message) {
1676 vfswrap_logged_ioctl_message = true;
1677 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1678 __func__, function));
1682 return NT_STATUS_NOT_SUPPORTED;
1685 static bool vfswrap_is_offline(struct connection_struct *conn,
1686 const struct smb_filename *fname);
1688 struct vfswrap_get_dos_attributes_state {
1689 struct vfs_aio_state aio_state;
1690 connection_struct *conn;
1691 TALLOC_CTX *mem_ctx;
1692 struct tevent_context *ev;
1693 files_struct *dir_fsp;
1694 struct smb_filename *smb_fname;
1699 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq);
1701 static struct tevent_req *vfswrap_get_dos_attributes_send(
1702 TALLOC_CTX *mem_ctx,
1703 struct tevent_context *ev,
1704 struct vfs_handle_struct *handle,
1705 files_struct *dir_fsp,
1706 struct smb_filename *smb_fname)
1708 struct tevent_req *req = NULL;
1709 struct tevent_req *subreq = NULL;
1710 struct vfswrap_get_dos_attributes_state *state = NULL;
1712 req = tevent_req_create(mem_ctx, &state,
1713 struct vfswrap_get_dos_attributes_state);
1718 *state = (struct vfswrap_get_dos_attributes_state) {
1719 .conn = dir_fsp->conn,
1723 .smb_fname = smb_fname,
1726 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1730 SAMBA_XATTR_DOS_ATTRIB,
1732 if (tevent_req_nomem(subreq, req)) {
1733 return tevent_req_post(req, ev);
1735 tevent_req_set_callback(subreq,
1736 vfswrap_get_dos_attributes_getxattr_done,
1742 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq)
1744 struct tevent_req *req =
1745 tevent_req_callback_data(subreq,
1747 struct vfswrap_get_dos_attributes_state *state =
1748 tevent_req_data(req,
1749 struct vfswrap_get_dos_attributes_state);
1751 DATA_BLOB blob = {0};
1753 char *tofree = NULL;
1754 char pathbuf[PATH_MAX+1];
1756 struct smb_filename smb_fname;
1760 xattr_size = SMB_VFS_GETXATTRAT_RECV(subreq,
1764 TALLOC_FREE(subreq);
1765 if (xattr_size == -1) {
1766 status = map_nt_error_from_unix(state->aio_state.error);
1768 if (state->as_root) {
1769 tevent_req_nterror(req, status);
1772 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1773 tevent_req_nterror(req, status);
1777 state->as_root = true;
1780 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1784 SAMBA_XATTR_DOS_ATTRIB,
1787 if (tevent_req_nomem(subreq, req)) {
1790 tevent_req_set_callback(subreq,
1791 vfswrap_get_dos_attributes_getxattr_done,
1796 blob.length = xattr_size;
1798 status = parse_dos_attribute_blob(state->smb_fname,
1801 if (!NT_STATUS_IS_OK(status)) {
1802 tevent_req_nterror(req, status);
1806 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
1807 state->smb_fname->base_name,
1812 if (pathlen == -1) {
1813 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1817 smb_fname = (struct smb_filename) {
1819 .st = state->smb_fname->st,
1820 .flags = state->smb_fname->flags,
1821 .twrp = state->smb_fname->twrp,
1824 offline = vfswrap_is_offline(state->conn, &smb_fname);
1826 state->dosmode |= FILE_ATTRIBUTE_OFFLINE;
1828 TALLOC_FREE(tofree);
1830 tevent_req_done(req);
1834 static NTSTATUS vfswrap_get_dos_attributes_recv(struct tevent_req *req,
1835 struct vfs_aio_state *aio_state,
1838 struct vfswrap_get_dos_attributes_state *state =
1839 tevent_req_data(req,
1840 struct vfswrap_get_dos_attributes_state);
1843 if (tevent_req_is_nterror(req, &status)) {
1844 tevent_req_received(req);
1848 *aio_state = state->aio_state;
1849 *dosmode = state->dosmode;
1850 tevent_req_received(req);
1851 return NT_STATUS_OK;
1854 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1855 struct files_struct *fsp,
1860 offline = vfswrap_is_offline(handle->conn, fsp->fsp_name);
1862 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1865 return fget_ea_dos_attribute(fsp, dosmode);
1868 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1869 struct files_struct *fsp,
1872 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1875 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1877 struct vfswrap_offload_read_state {
1881 static struct tevent_req *vfswrap_offload_read_send(
1882 TALLOC_CTX *mem_ctx,
1883 struct tevent_context *ev,
1884 struct vfs_handle_struct *handle,
1885 struct files_struct *fsp,
1891 struct tevent_req *req = NULL;
1892 struct vfswrap_offload_read_state *state = NULL;
1895 req = tevent_req_create(mem_ctx, &state,
1896 struct vfswrap_offload_read_state);
1901 status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1902 &vfswrap_offload_ctx);
1903 if (tevent_req_nterror(req, status)) {
1904 return tevent_req_post(req, ev);
1907 if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1908 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1909 return tevent_req_post(req, ev);
1912 status = vfs_offload_token_create_blob(state, fsp, fsctl,
1914 if (tevent_req_nterror(req, status)) {
1915 return tevent_req_post(req, ev);
1918 status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1920 if (tevent_req_nterror(req, status)) {
1921 return tevent_req_post(req, ev);
1924 tevent_req_done(req);
1925 return tevent_req_post(req, ev);
1928 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
1929 struct vfs_handle_struct *handle,
1930 TALLOC_CTX *mem_ctx,
1933 struct vfswrap_offload_read_state *state = tevent_req_data(
1934 req, struct vfswrap_offload_read_state);
1937 if (tevent_req_is_nterror(req, &status)) {
1938 tevent_req_received(req);
1942 token->length = state->token.length;
1943 token->data = talloc_move(mem_ctx, &state->token.data);
1945 tevent_req_received(req);
1946 return NT_STATUS_OK;
1949 struct vfswrap_offload_write_state {
1951 bool read_lck_locked;
1952 bool write_lck_locked;
1954 struct tevent_context *src_ev;
1955 struct files_struct *src_fsp;
1957 struct tevent_context *dst_ev;
1958 struct files_struct *dst_fsp;
1962 size_t next_io_size;
1965 static void vfswrap_offload_write_cleanup(struct tevent_req *req,
1966 enum tevent_req_state req_state)
1968 struct vfswrap_offload_write_state *state = tevent_req_data(
1969 req, struct vfswrap_offload_write_state);
1972 if (state->dst_fsp == NULL) {
1976 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
1978 state->dst_fsp = NULL;
1981 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
1983 static struct tevent_req *vfswrap_offload_write_send(
1984 struct vfs_handle_struct *handle,
1985 TALLOC_CTX *mem_ctx,
1986 struct tevent_context *ev,
1989 off_t transfer_offset,
1990 struct files_struct *dest_fsp,
1994 struct tevent_req *req;
1995 struct vfswrap_offload_write_state *state = NULL;
1996 /* off_t is signed! */
1997 off_t max_offset = INT64_MAX - to_copy;
1998 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
1999 files_struct *src_fsp = NULL;
2003 req = tevent_req_create(mem_ctx, &state,
2004 struct vfswrap_offload_write_state);
2009 *state = (struct vfswrap_offload_write_state) {
2011 .src_off = transfer_offset,
2013 .dst_fsp = dest_fsp,
2014 .dst_off = dest_off,
2016 .remaining = to_copy,
2019 tevent_req_set_cleanup_fn(req, vfswrap_offload_write_cleanup);
2022 case FSCTL_SRV_COPYCHUNK:
2023 case FSCTL_SRV_COPYCHUNK_WRITE:
2026 case FSCTL_OFFLOAD_WRITE:
2027 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
2028 return tevent_req_post(req, ev);
2030 case FSCTL_DUP_EXTENTS_TO_FILE:
2031 DBG_DEBUG("COW clones not supported by vfs_default\n");
2032 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2033 return tevent_req_post(req, ev);
2036 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2037 return tevent_req_post(req, ev);
2041 * From here on we assume a copy-chunk fsctl
2045 tevent_req_done(req);
2046 return tevent_req_post(req, ev);
2049 if (state->src_off > max_offset) {
2051 * Protect integer checks below.
2053 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2054 return tevent_req_post(req, ev);
2056 if (state->src_off < 0) {
2058 * Protect integer checks below.
2060 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2061 return tevent_req_post(req, ev);
2063 if (state->dst_off > max_offset) {
2065 * Protect integer checks below.
2067 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2068 return tevent_req_post(req, ev);
2070 if (state->dst_off < 0) {
2072 * Protect integer checks below.
2074 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2075 return tevent_req_post(req, ev);
2078 status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
2080 if (tevent_req_nterror(req, status)) {
2081 return tevent_req_post(req, ev);
2084 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
2086 status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
2087 if (!NT_STATUS_IS_OK(status)) {
2088 tevent_req_nterror(req, status);
2089 return tevent_req_post(req, ev);
2092 ok = change_to_user_and_service_by_fsp(src_fsp);
2094 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2095 return tevent_req_post(req, ev);
2098 state->src_ev = src_fsp->conn->sconn->ev_ctx;
2099 state->src_fsp = src_fsp;
2101 status = vfs_stat_fsp(src_fsp);
2102 if (tevent_req_nterror(req, status)) {
2103 return tevent_req_post(req, ev);
2106 if (src_fsp->fsp_name->st.st_ex_size < state->src_off + to_copy) {
2108 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
2109 * If the SourceOffset or SourceOffset + Length extends beyond
2110 * the end of file, the server SHOULD<240> treat this as a
2111 * STATUS_END_OF_FILE error.
2113 * <240> Section 3.3.5.15.6: Windows servers will return
2114 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
2116 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
2117 return tevent_req_post(req, ev);
2120 state->buf = talloc_array(state, uint8_t, num);
2121 if (tevent_req_nomem(state->buf, req)) {
2122 return tevent_req_post(req, ev);
2125 status = vfswrap_offload_write_loop(req);
2126 if (!NT_STATUS_IS_OK(status)) {
2127 tevent_req_nterror(req, status);
2128 return tevent_req_post(req, ev);
2134 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
2136 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
2138 struct vfswrap_offload_write_state *state = tevent_req_data(
2139 req, struct vfswrap_offload_write_state);
2140 struct tevent_req *subreq = NULL;
2141 struct lock_struct read_lck;
2145 * This is called under the context of state->src_fsp.
2148 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
2150 init_strict_lock_struct(state->src_fsp,
2151 state->src_fsp->op->global->open_persistent_id,
2153 state->next_io_size,
2157 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
2161 return NT_STATUS_FILE_LOCK_CONFLICT;
2164 subreq = SMB_VFS_PREAD_SEND(state,
2168 state->next_io_size,
2170 if (subreq == NULL) {
2171 return NT_STATUS_NO_MEMORY;
2173 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
2175 return NT_STATUS_OK;
2178 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
2180 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
2182 struct tevent_req *req = tevent_req_callback_data(
2183 subreq, struct tevent_req);
2184 struct vfswrap_offload_write_state *state = tevent_req_data(
2185 req, struct vfswrap_offload_write_state);
2186 struct vfs_aio_state aio_state;
2187 struct lock_struct write_lck;
2191 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
2192 TALLOC_FREE(subreq);
2194 DBG_ERR("read failed: %s\n", strerror(aio_state.error));
2195 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2198 if (nread != state->next_io_size) {
2199 DBG_ERR("Short read, only %zd of %zu\n",
2200 nread, state->next_io_size);
2201 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2205 state->src_off += nread;
2207 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2209 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2213 init_strict_lock_struct(state->dst_fsp,
2214 state->dst_fsp->op->global->open_persistent_id,
2216 state->next_io_size,
2220 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
2224 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
2228 subreq = SMB_VFS_PWRITE_SEND(state,
2232 state->next_io_size,
2234 if (subreq == NULL) {
2235 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2238 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
2241 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
2243 struct tevent_req *req = tevent_req_callback_data(
2244 subreq, struct tevent_req);
2245 struct vfswrap_offload_write_state *state = tevent_req_data(
2246 req, struct vfswrap_offload_write_state);
2247 struct vfs_aio_state aio_state;
2252 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
2253 TALLOC_FREE(subreq);
2254 if (nwritten == -1) {
2255 DBG_ERR("write failed: %s\n", strerror(aio_state.error));
2256 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2259 if (nwritten != state->next_io_size) {
2260 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
2261 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2265 state->dst_off += nwritten;
2267 if (state->remaining < nwritten) {
2268 /* Paranoia check */
2269 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2272 state->remaining -= nwritten;
2273 if (state->remaining == 0) {
2274 tevent_req_done(req);
2278 ok = change_to_user_and_service_by_fsp(state->src_fsp);
2280 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2284 status = vfswrap_offload_write_loop(req);
2285 if (!NT_STATUS_IS_OK(status)) {
2286 tevent_req_nterror(req, status);
2293 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
2294 struct tevent_req *req,
2297 struct vfswrap_offload_write_state *state = tevent_req_data(
2298 req, struct vfswrap_offload_write_state);
2301 if (tevent_req_is_nterror(req, &status)) {
2302 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
2304 tevent_req_received(req);
2308 *copied = state->to_copy;
2309 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
2310 tevent_req_received(req);
2312 return NT_STATUS_OK;
2315 static NTSTATUS vfswrap_fget_compression(struct vfs_handle_struct *handle,
2316 TALLOC_CTX *mem_ctx,
2317 struct files_struct *fsp,
2318 uint16_t *_compression_fmt)
2320 return NT_STATUS_INVALID_DEVICE_REQUEST;
2323 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
2324 TALLOC_CTX *mem_ctx,
2325 struct files_struct *fsp,
2326 uint16_t compression_fmt)
2328 return NT_STATUS_INVALID_DEVICE_REQUEST;
2331 /********************************************************************
2332 Given a stat buffer return the allocated size on disk, taking into
2333 account sparse files.
2334 ********************************************************************/
2335 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
2336 struct files_struct *fsp,
2337 const SMB_STRUCT_STAT *sbuf)
2341 START_PROFILE(syscall_get_alloc_size);
2343 if(S_ISDIR(sbuf->st_ex_mode)) {
2348 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2349 /* The type of st_blocksize is blkcnt_t which *MUST* be
2350 signed (according to POSIX) and can be less than 64-bits.
2351 Ensure when we're converting to 64 bits wide we don't
2353 #if defined(SIZEOF_BLKCNT_T_8)
2354 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2355 #elif defined(SIZEOF_BLKCNT_T_4)
2357 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2358 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2361 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2365 * Some file systems do not allocate a block for very
2366 * small files. But for non-empty file should report a
2370 uint64_t filesize = get_file_size_stat(sbuf);
2372 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2376 result = get_file_size_stat(sbuf);
2379 if (fsp && fsp->initial_allocation_size)
2380 result = MAX(result,fsp->initial_allocation_size);
2382 result = smb_roundup(handle->conn, result);
2385 END_PROFILE(syscall_get_alloc_size);
2389 static int vfswrap_unlinkat(vfs_handle_struct *handle,
2390 struct files_struct *dirfsp,
2391 const struct smb_filename *smb_fname,
2396 START_PROFILE(syscall_unlinkat);
2398 if (is_named_stream(smb_fname)) {
2402 result = unlinkat(fsp_get_pathref_fd(dirfsp),
2403 smb_fname->base_name,
2407 END_PROFILE(syscall_unlinkat);
2411 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2415 START_PROFILE(syscall_fchmod);
2417 if (!fsp->fsp_flags.is_pathref) {
2418 result = fchmod(fsp_get_io_fd(fsp), mode);
2419 END_PROFILE(syscall_fchmod);
2423 if (fsp->fsp_flags.have_proc_fds) {
2424 int fd = fsp_get_pathref_fd(fsp);
2425 const char *p = NULL;
2428 p = sys_proc_fd_path(fd, buf, sizeof(buf));
2430 result = chmod(p, mode);
2434 END_PROFILE(syscall_fchmod);
2439 * This is no longer a handle based call.
2441 result = chmod(fsp->fsp_name->base_name, mode);
2443 END_PROFILE(syscall_fchmod);
2447 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2452 START_PROFILE(syscall_fchown);
2453 result = fchown(fsp_get_io_fd(fsp), uid, gid);
2454 END_PROFILE(syscall_fchown);
2462 static int vfswrap_lchown(vfs_handle_struct *handle,
2463 const struct smb_filename *smb_fname,
2469 START_PROFILE(syscall_lchown);
2470 result = lchown(smb_fname->base_name, uid, gid);
2471 END_PROFILE(syscall_lchown);
2475 static int vfswrap_chdir(vfs_handle_struct *handle,
2476 const struct smb_filename *smb_fname)
2480 START_PROFILE(syscall_chdir);
2481 result = chdir(smb_fname->base_name);
2482 END_PROFILE(syscall_chdir);
2486 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2490 struct smb_filename *smb_fname = NULL;
2492 START_PROFILE(syscall_getwd);
2493 result = sys_getwd();
2494 END_PROFILE(syscall_getwd);
2496 if (result == NULL) {
2499 smb_fname = synthetic_smb_fname(ctx,
2506 * sys_getwd() *always* returns malloced memory.
2507 * We must free here to avoid leaks:
2508 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2514 /*********************************************************************
2515 nsec timestamp resolution call. Convert down to whatever the underlying
2516 system will support.
2517 **********************************************************************/
2519 static int vfswrap_fntimes(vfs_handle_struct *handle,
2521 struct smb_file_time *ft)
2524 struct timespec ts[2];
2525 struct timespec *times = NULL;
2527 START_PROFILE(syscall_fntimes);
2529 if (is_named_stream(fsp->fsp_name)) {
2535 if (is_omit_timespec(&ft->atime)) {
2536 ft->atime = fsp->fsp_name->st.st_ex_atime;
2539 if (is_omit_timespec(&ft->mtime)) {
2540 ft->mtime = fsp->fsp_name->st.st_ex_mtime;
2543 if (!is_omit_timespec(&ft->create_time)) {
2544 set_create_timespec_ea(handle->conn,
2549 if ((timespec_compare(&ft->atime,
2550 &fsp->fsp_name->st.st_ex_atime) == 0) &&
2551 (timespec_compare(&ft->mtime,
2552 &fsp->fsp_name->st.st_ex_mtime) == 0)) {
2564 if (!fsp->fsp_flags.is_pathref) {
2565 result = futimens(fsp_get_io_fd(fsp), times);
2569 if (fsp->fsp_flags.have_proc_fds) {
2570 int fd = fsp_get_pathref_fd(fsp);
2571 const char *p = NULL;
2574 p = sys_proc_fd_path(fd, buf, sizeof(buf));
2577 * The dirfd argument of utimensat is ignored when
2578 * pathname is an absolute path
2580 result = utimensat(AT_FDCWD, p, times, 0);
2589 * The fd is a pathref (opened with O_PATH) and there isn't fd to
2590 * path translation mechanism. Fallback to path based call.
2592 result = utimensat(AT_FDCWD, fsp->fsp_name->base_name, times, 0);
2595 END_PROFILE(syscall_fntimes);
2601 /*********************************************************************
2602 A version of ftruncate that will write the space on disk if strict
2604 **********************************************************************/
2606 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2608 off_t space_to_write;
2609 uint64_t space_avail;
2610 uint64_t bsize,dfree,dsize;
2613 SMB_STRUCT_STAT *pst;
2616 ok = vfs_valid_pwrite_range(len, 0);
2622 status = vfs_stat_fsp(fsp);
2623 if (!NT_STATUS_IS_OK(status)) {
2626 pst = &fsp->fsp_name->st;
2629 if (S_ISFIFO(pst->st_ex_mode))
2633 if (pst->st_ex_size == len)
2636 /* Shrink - just ftruncate. */
2637 if (pst->st_ex_size > len)
2638 return ftruncate(fsp_get_io_fd(fsp), len);
2640 space_to_write = len - pst->st_ex_size;
2642 /* for allocation try fallocate first. This can fail on some
2643 platforms e.g. when the filesystem doesn't support it and no
2644 emulation is being done by the libc (like on AIX with JFS1). In that
2645 case we do our own emulation. fallocate implementations can
2646 return ENOTSUP or EINVAL in cases like that. */
2647 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2648 if (ret == -1 && errno == ENOSPC) {
2654 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2655 "error %d. Falling back to slow manual allocation\n", errno));
2657 /* available disk space is enough or not? */
2659 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2660 /* space_avail is 1k blocks */
2661 if (space_avail == (uint64_t)-1 ||
2662 ((uint64_t)space_to_write/1024 > space_avail) ) {
2667 /* Write out the real space on disk. */
2668 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2676 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2679 SMB_STRUCT_STAT *pst;
2683 START_PROFILE(syscall_ftruncate);
2685 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->fsp_flags.is_sparse) {
2686 result = strict_allocate_ftruncate(handle, fsp, len);
2687 END_PROFILE(syscall_ftruncate);
2691 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2692 ftruncate if the system supports it. Then I discovered that
2693 you can have some filesystems that support ftruncate
2694 expansion and some that don't! On Linux fat can't do
2695 ftruncate extend but ext2 can. */
2697 result = ftruncate(fsp_get_io_fd(fsp), len);
2699 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2700 extend a file with ftruncate. Provide alternate implementation
2703 /* Do an fstat to see if the file is longer than the requested
2704 size in which case the ftruncate above should have
2705 succeeded or shorter, in which case seek to len - 1 and
2706 write 1 byte of zero */
2707 status = vfs_stat_fsp(fsp);
2708 if (!NT_STATUS_IS_OK(status)) {
2712 /* We need to update the files_struct after successful ftruncate */
2717 pst = &fsp->fsp_name->st;
2720 if (S_ISFIFO(pst->st_ex_mode)) {
2726 if (pst->st_ex_size == len) {
2731 if (pst->st_ex_size > len) {
2732 /* the ftruncate should have worked */
2736 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2744 END_PROFILE(syscall_ftruncate);
2748 static int vfswrap_fallocate(vfs_handle_struct *handle,
2756 START_PROFILE(syscall_fallocate);
2758 result = sys_posix_fallocate(fsp_get_io_fd(fsp), offset, len);
2760 * posix_fallocate returns 0 on success, errno on error
2761 * and doesn't set errno. Make it behave like fallocate()
2762 * which returns -1, and sets errno on failure.
2769 /* sys_fallocate handles filtering of unsupported mode flags */
2770 result = sys_fallocate(fsp_get_io_fd(fsp), mode, offset, len);
2772 END_PROFILE(syscall_fallocate);
2776 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2780 START_PROFILE(syscall_fcntl_lock);
2782 if (fsp->fsp_flags.use_ofd_locks) {
2783 op = map_process_lock_to_ofd_lock(op);
2786 result = fcntl_lock(fsp_get_io_fd(fsp), op, offset, count, type);
2787 END_PROFILE(syscall_fcntl_lock);
2791 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2792 uint32_t share_access, uint32_t access_mask)
2794 START_PROFILE(syscall_kernel_flock);
2795 kernel_flock(fsp_get_io_fd(fsp), share_access, access_mask);
2796 END_PROFILE(syscall_kernel_flock);
2800 static int vfswrap_fcntl(vfs_handle_struct *handle, files_struct *fsp, int cmd,
2804 va_list dup_cmd_arg;
2808 START_PROFILE(syscall_fcntl);
2810 va_copy(dup_cmd_arg, cmd_arg);
2816 #if defined(HAVE_OFD_LOCKS)
2821 #if defined(HAVE_F_OWNER_EX)
2825 #if defined(HAVE_RW_HINTS)
2828 case F_GET_FILE_RW_HINT:
2829 case F_SET_FILE_RW_HINT:
2831 argp = va_arg(dup_cmd_arg, void *);
2832 result = sys_fcntl_ptr(fsp_get_io_fd(fsp), cmd, argp);
2835 val = va_arg(dup_cmd_arg, int);
2836 result = sys_fcntl_int(fsp_get_io_fd(fsp), cmd, val);
2839 va_end(dup_cmd_arg);
2841 END_PROFILE(syscall_fcntl);
2845 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2850 START_PROFILE(syscall_fcntl_getlock);
2852 if (fsp->fsp_flags.use_ofd_locks) {
2853 op = map_process_lock_to_ofd_lock(op);
2856 result = fcntl_getlock(fsp_get_io_fd(fsp), op, poffset, pcount, ptype, ppid);
2857 END_PROFILE(syscall_fcntl_getlock);
2861 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2866 START_PROFILE(syscall_linux_setlease);
2868 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2869 result = linux_setlease(fsp_get_io_fd(fsp), leasetype);
2873 END_PROFILE(syscall_linux_setlease);
2877 static int vfswrap_symlinkat(vfs_handle_struct *handle,
2878 const struct smb_filename *link_target,
2879 struct files_struct *dirfsp,
2880 const struct smb_filename *new_smb_fname)
2884 START_PROFILE(syscall_symlinkat);
2886 result = symlinkat(link_target->base_name,
2887 fsp_get_pathref_fd(dirfsp),
2888 new_smb_fname->base_name);
2889 END_PROFILE(syscall_symlinkat);
2893 static int vfswrap_readlinkat(vfs_handle_struct *handle,
2894 const struct files_struct *dirfsp,
2895 const struct smb_filename *smb_fname,
2901 START_PROFILE(syscall_readlinkat);
2903 result = readlinkat(fsp_get_pathref_fd(dirfsp),
2904 smb_fname->base_name,
2908 END_PROFILE(syscall_readlinkat);
2912 static int vfswrap_linkat(vfs_handle_struct *handle,
2913 files_struct *srcfsp,
2914 const struct smb_filename *old_smb_fname,
2915 files_struct *dstfsp,
2916 const struct smb_filename *new_smb_fname,
2921 START_PROFILE(syscall_linkat);
2923 result = linkat(fsp_get_pathref_fd(srcfsp),
2924 old_smb_fname->base_name,
2925 fsp_get_pathref_fd(dstfsp),
2926 new_smb_fname->base_name,
2929 END_PROFILE(syscall_linkat);
2933 static int vfswrap_mknodat(vfs_handle_struct *handle,
2934 files_struct *dirfsp,
2935 const struct smb_filename *smb_fname,
2941 START_PROFILE(syscall_mknodat);
2943 result = sys_mknodat(fsp_get_pathref_fd(dirfsp),
2944 smb_fname->base_name,
2948 END_PROFILE(syscall_mknodat);
2952 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2954 const struct smb_filename *smb_fname)
2957 struct smb_filename *result_fname = NULL;
2959 START_PROFILE(syscall_realpath);
2960 result = sys_realpath(smb_fname->base_name);
2961 END_PROFILE(syscall_realpath);
2963 result_fname = synthetic_smb_fname(ctx,
2971 return result_fname;
2974 static int vfswrap_chflags(vfs_handle_struct *handle,
2975 const struct smb_filename *smb_fname,
2979 return chflags(smb_fname->base_name, flags);
2986 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2987 const SMB_STRUCT_STAT *sbuf)
2991 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2995 key.devid = sbuf->st_ex_dev;
2996 key.inode = sbuf->st_ex_ino;
2997 /* key.extid is unused by default. */
3002 static uint64_t vfswrap_fs_file_id(struct vfs_handle_struct *handle,
3003 const SMB_STRUCT_STAT *psbuf)
3007 if (!(psbuf->st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)) {
3008 return psbuf->st_ex_file_id;
3011 if (handle->conn->base_share_dev == psbuf->st_ex_dev) {
3012 return (uint64_t)psbuf->st_ex_ino;
3016 file_id = ((psbuf->st_ex_ino) & UINT32_MAX);
3019 file_id |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32;
3024 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
3025 struct files_struct *fsp,
3026 const struct smb_filename *smb_fname,
3027 TALLOC_CTX *mem_ctx,
3028 unsigned int *pnum_streams,
3029 struct stream_struct **pstreams)
3031 SMB_STRUCT_STAT sbuf;
3032 struct stream_struct *tmp_streams = NULL;
3035 if ((fsp != NULL) && (fsp->fsp_flags.is_directory)) {
3037 * No default streams on directories
3042 if ((fsp != NULL) && (fsp_get_pathref_fd(fsp) != -1)) {
3043 ret = SMB_VFS_FSTAT(fsp, &sbuf);
3046 struct smb_filename *smb_fname_cp = NULL;
3048 smb_fname_cp = cp_smb_filename_nostream(talloc_tos(), smb_fname);
3049 if (smb_fname_cp == NULL) {
3050 return NT_STATUS_NO_MEMORY;
3053 ret = vfs_stat(handle->conn, smb_fname_cp);
3054 sbuf = smb_fname_cp->st;
3055 TALLOC_FREE(smb_fname_cp);
3059 return map_nt_error_from_unix(errno);
3062 if (S_ISDIR(sbuf.st_ex_mode)) {
3066 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
3067 (*pnum_streams) + 1);
3068 if (tmp_streams == NULL) {
3069 return NT_STATUS_NO_MEMORY;
3071 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
3072 if (tmp_streams[*pnum_streams].name == NULL) {
3073 return NT_STATUS_NO_MEMORY;
3075 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
3076 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
3079 *pstreams = tmp_streams;
3081 return NT_STATUS_OK;
3084 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
3085 const struct smb_filename *path,
3087 TALLOC_CTX *mem_ctx,
3091 * Don't fall back to get_real_filename so callers can differentiate
3092 * between a full directory scan and an actual case-insensitive stat.
3098 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
3099 const struct smb_filename *smb_fname)
3101 return handle->conn->connectpath;
3104 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
3105 struct byte_range_lock *br_lck,
3106 struct lock_struct *plock)
3108 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3110 /* Note: blr is not used in the default implementation. */
3111 return brl_lock_windows_default(br_lck, plock);
3114 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
3115 struct byte_range_lock *br_lck,
3116 const struct lock_struct *plock)
3118 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3120 return brl_unlock_windows_default(br_lck, plock);
3123 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
3125 struct lock_struct *plock)
3127 SMB_ASSERT(plock->lock_type == READ_LOCK ||
3128 plock->lock_type == WRITE_LOCK);
3130 return strict_lock_check_default(fsp, plock);
3133 /* NT ACL operations. */
3135 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
3137 uint32_t security_info,
3138 TALLOC_CTX *mem_ctx,
3139 struct security_descriptor **ppdesc)
3143 START_PROFILE(fget_nt_acl);
3144 result = posix_fget_nt_acl(fsp, security_info,
3146 END_PROFILE(fget_nt_acl);
3150 static NTSTATUS vfswrap_get_nt_acl_at(vfs_handle_struct *handle,
3151 struct files_struct *dirfsp,
3152 const struct smb_filename *smb_fname,
3153 uint32_t security_info,
3154 TALLOC_CTX *mem_ctx,
3155 struct security_descriptor **ppdesc)
3159 START_PROFILE(get_nt_acl_at);
3161 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
3163 result = posix_get_nt_acl(handle->conn,
3168 END_PROFILE(get_nt_acl_at);
3172 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
3176 START_PROFILE(fset_nt_acl);
3177 result = set_nt_acl(fsp, security_info_sent, psd);
3178 END_PROFILE(fset_nt_acl);
3182 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
3183 struct smb_filename *file,
3184 struct security_acl *sacl,
3185 uint32_t access_requested,
3186 uint32_t access_denied)
3188 return NT_STATUS_OK; /* Nothing to do here ... */
3191 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
3192 const struct smb_filename *smb_fname,
3193 SMB_ACL_TYPE_T type,
3194 TALLOC_CTX *mem_ctx)
3196 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
3199 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
3201 TALLOC_CTX *mem_ctx)
3203 return sys_acl_get_fd(handle, fsp, mem_ctx);
3206 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle,
3208 SMB_ACL_TYPE_T type,
3211 if (!fsp->fsp_flags.is_pathref &&
3212 type == SMB_ACL_TYPE_ACCESS)
3214 return sys_acl_set_fd(handle, fsp, theacl);
3217 if (fsp->fsp_flags.have_proc_fds) {
3218 int fd = fsp_get_pathref_fd(fsp);
3219 struct smb_filename smb_fname;
3220 const char *p = NULL;
3223 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3228 smb_fname = (struct smb_filename) {
3232 return sys_acl_set_file(handle,
3239 * This is no longer a handle based call.
3241 return sys_acl_set_file(handle,
3247 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
3248 const struct smb_filename *smb_fname)
3250 return sys_acl_delete_def_file(handle, smb_fname);
3253 /****************************************************************
3254 Extended attribute operations.
3255 *****************************************************************/
3257 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
3258 const struct smb_filename *smb_fname,
3263 return getxattr(smb_fname->base_name, name, value, size);
3266 struct vfswrap_getxattrat_state {
3267 struct tevent_context *ev;
3268 files_struct *dir_fsp;
3269 const struct smb_filename *smb_fname;
3272 * The following variables are talloced off "state" which is protected
3273 * by a destructor and thus are guaranteed to be safe to be used in the
3274 * job function in the worker thread.
3277 const char *xattr_name;
3278 uint8_t *xattr_value;
3279 struct security_unix_token *token;
3282 struct vfs_aio_state vfs_aio_state;
3283 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
3286 static int vfswrap_getxattrat_state_destructor(
3287 struct vfswrap_getxattrat_state *state)
3292 static void vfswrap_getxattrat_do_sync(struct tevent_req *req);
3293 static void vfswrap_getxattrat_do_async(void *private_data);
3294 static void vfswrap_getxattrat_done(struct tevent_req *subreq);
3296 static struct tevent_req *vfswrap_getxattrat_send(
3297 TALLOC_CTX *mem_ctx,
3298 struct tevent_context *ev,
3299 struct vfs_handle_struct *handle,
3300 files_struct *dir_fsp,
3301 const struct smb_filename *smb_fname,
3302 const char *xattr_name,
3305 struct tevent_req *req = NULL;
3306 struct tevent_req *subreq = NULL;
3307 struct vfswrap_getxattrat_state *state = NULL;
3308 size_t max_threads = 0;
3309 bool have_per_thread_cwd = false;
3310 bool have_per_thread_creds = false;
3311 bool do_async = false;
3313 req = tevent_req_create(mem_ctx, &state,
3314 struct vfswrap_getxattrat_state);
3318 *state = (struct vfswrap_getxattrat_state) {
3321 .smb_fname = smb_fname,
3324 max_threads = pthreadpool_tevent_max_threads(dir_fsp->conn->sconn->pool);
3325 if (max_threads >= 1) {
3327 * We need a non sync threadpool!
3329 have_per_thread_cwd = per_thread_cwd_supported();
3331 #ifdef HAVE_LINUX_THREAD_CREDENTIALS
3332 have_per_thread_creds = true;
3334 if (have_per_thread_cwd && have_per_thread_creds) {
3338 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat, profile_p,
3339 state->profile_bytes, 0);
3341 if (fsp_get_pathref_fd(dir_fsp) == -1) {
3342 DBG_ERR("Need a valid directory fd\n");
3343 tevent_req_error(req, EINVAL);
3344 return tevent_req_post(req, ev);
3347 if (alloc_hint > 0) {
3348 state->xattr_value = talloc_zero_array(state,
3351 if (tevent_req_nomem(state->xattr_value, req)) {
3352 return tevent_req_post(req, ev);
3357 vfswrap_getxattrat_do_sync(req);
3358 return tevent_req_post(req, ev);
3362 * Now allocate all parameters from a memory context that won't go away
3363 * no matter what. These paremeters will get used in threads and we
3364 * can't reliably cancel threads, so all buffers passed to the threads
3365 * must not be freed before all referencing threads terminate.
3368 state->name = talloc_strdup(state, smb_fname->base_name);
3369 if (tevent_req_nomem(state->name, req)) {
3370 return tevent_req_post(req, ev);
3373 state->xattr_name = talloc_strdup(state, xattr_name);
3374 if (tevent_req_nomem(state->xattr_name, req)) {
3375 return tevent_req_post(req, ev);
3379 * This is a hot codepath so at first glance one might think we should
3380 * somehow optimize away the token allocation and do a
3381 * talloc_reference() or similar black magic instead. But due to the
3382 * talloc_stackframe pool per SMB2 request this should be a simple copy
3383 * without a malloc in most cases.
3385 if (geteuid() == sec_initial_uid()) {
3386 state->token = root_unix_token(state);
3388 state->token = copy_unix_token(
3390 dir_fsp->conn->session_info->unix_token);
3392 if (tevent_req_nomem(state->token, req)) {
3393 return tevent_req_post(req, ev);
3396 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3398 subreq = pthreadpool_tevent_job_send(
3401 dir_fsp->conn->sconn->pool,
3402 vfswrap_getxattrat_do_async,
3404 if (tevent_req_nomem(subreq, req)) {
3405 return tevent_req_post(req, ev);
3407 tevent_req_set_callback(subreq, vfswrap_getxattrat_done, req);
3409 talloc_set_destructor(state, vfswrap_getxattrat_state_destructor);
3414 static void vfswrap_getxattrat_do_sync(struct tevent_req *req)
3416 struct vfswrap_getxattrat_state *state = tevent_req_data(
3417 req, struct vfswrap_getxattrat_state);
3419 char *tofree = NULL;
3420 char pathbuf[PATH_MAX+1];
3424 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
3425 state->smb_fname->base_name,
3430 if (pathlen == -1) {
3431 tevent_req_error(req, ENOMEM);
3435 state->xattr_size = getxattr(path,
3438 talloc_array_length(state->xattr_value));
3440 TALLOC_FREE(tofree);
3441 if (state->xattr_size == -1) {
3442 tevent_req_error(req, err);
3446 tevent_req_done(req);
3450 static void vfswrap_getxattrat_do_async(void *private_data)
3452 struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3453 private_data, struct vfswrap_getxattrat_state);
3454 struct timespec start_time;
3455 struct timespec end_time;
3458 PROFILE_TIMESTAMP(&start_time);
3459 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
3462 * Here we simulate a getxattrat()
3463 * call using fchdir();getxattr()
3466 per_thread_cwd_activate();
3468 /* Become the correct credential on this thread. */
3469 ret = set_thread_credentials(state->token->uid,
3471 (size_t)state->token->ngroups,
3472 state->token->groups);
3474 state->xattr_size = -1;
3475 state->vfs_aio_state.error = errno;
3479 ret = fchdir(fsp_get_pathref_fd(state->dir_fsp));
3481 state->xattr_size = -1;
3482 state->vfs_aio_state.error = errno;
3486 state->xattr_size = getxattr(state->name,
3489 talloc_array_length(state->xattr_value));
3490 if (state->xattr_size == -1) {
3491 state->vfs_aio_state.error = errno;
3495 PROFILE_TIMESTAMP(&end_time);
3496 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
3497 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3500 static void vfswrap_getxattrat_done(struct tevent_req *subreq)
3502 struct tevent_req *req = tevent_req_callback_data(
3503 subreq, struct tevent_req);
3504 struct vfswrap_getxattrat_state *state = tevent_req_data(
3505 req, struct vfswrap_getxattrat_state);
3510 * Make sure we run as the user again
3512 ok = change_to_user_and_service_by_fsp(state->dir_fsp);
3515 ret = pthreadpool_tevent_job_recv(subreq);
3516 TALLOC_FREE(subreq);
3517 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
3518 talloc_set_destructor(state, NULL);
3520 if (ret != EAGAIN) {
3521 tevent_req_error(req, ret);
3525 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
3526 * means the lower level pthreadpool failed to create a new
3527 * thread. Fallback to sync processing in that case to allow
3528 * some progress for the client.
3530 vfswrap_getxattrat_do_sync(req);
3534 if (state->xattr_size == -1) {
3535 tevent_req_error(req, state->vfs_aio_state.error);
3539 if (state->xattr_value == NULL) {
3541 * The caller only wanted the size.
3543 tevent_req_done(req);
3548 * shrink the buffer to the returned size.
3549 * (can't fail). It means NULL if size is 0.
3551 state->xattr_value = talloc_realloc(state,
3556 tevent_req_done(req);
3559 static ssize_t vfswrap_getxattrat_recv(struct tevent_req *req,
3560 struct vfs_aio_state *aio_state,
3561 TALLOC_CTX *mem_ctx,
3562 uint8_t **xattr_value)
3564 struct vfswrap_getxattrat_state *state = tevent_req_data(
3565 req, struct vfswrap_getxattrat_state);
3568 if (tevent_req_is_unix_error(req, &aio_state->error)) {
3569 tevent_req_received(req);
3573 *aio_state = state->vfs_aio_state;
3574 xattr_size = state->xattr_size;
3575 if (xattr_value != NULL) {
3576 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
3579 tevent_req_received(req);
3583 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle,
3584 struct files_struct *fsp,
3589 int fd = fsp_get_pathref_fd(fsp);
3591 if (!fsp->fsp_flags.is_pathref) {
3592 return fgetxattr(fd, name, value, size);
3595 if (fsp->fsp_flags.have_proc_fds) {
3596 const char *p = NULL;
3599 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3604 return getxattr(p, name, value, size);
3608 * This is no longer a handle based call.
3610 return getxattr(fsp->fsp_name->base_name, name, value, size);
3613 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
3615 int fd = fsp_get_pathref_fd(fsp);
3617 if (!fsp->fsp_flags.is_pathref) {
3618 return flistxattr(fd, list, size);
3621 if (fsp->fsp_flags.have_proc_fds) {
3622 const char *p = NULL;
3625 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3630 return listxattr(p, list, size);
3634 * This is no longer a handle based call.
3636 return listxattr(fsp->fsp_name->base_name, list, size);
3639 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
3641 int fd = fsp_get_pathref_fd(fsp);
3643 if (!fsp->fsp_flags.is_pathref) {
3644 return fremovexattr(fd, name);
3647 if (fsp->fsp_flags.have_proc_fds) {
3648 const char *p = NULL;
3651 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3656 return removexattr(p, name);
3660 * This is no longer a handle based call.
3662 return removexattr(fsp->fsp_name->base_name, name);
3665 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
3667 int fd = fsp_get_pathref_fd(fsp);
3669 if (!fsp->fsp_flags.is_pathref) {
3670 return fsetxattr(fd, name, value, size, flags);
3673 if (fsp->fsp_flags.have_proc_fds) {
3674 const char *p = NULL;
3677 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3682 return setxattr(p, name, value, size, flags);
3686 * This is no longer a handle based call.
3688 return setxattr(fsp->fsp_name->base_name, name, value, size, flags);
3691 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
3696 static bool vfswrap_is_offline(struct connection_struct *conn,
3697 const struct smb_filename *fname)
3701 bool offline = false;
3703 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
3707 if (!lp_dmapi_support(SNUM(conn)) || !dmapi_have_session()) {
3708 #if defined(ENOTSUP)
3714 status = get_full_smb_filename(talloc_tos(), fname, &path);
3715 if (!NT_STATUS_IS_OK(status)) {
3716 errno = map_errno_from_nt_status(status);
3720 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
3727 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
3728 struct files_struct *fsp,
3729 TALLOC_CTX *mem_ctx,
3732 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
3735 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
3736 struct files_struct *fsp,
3737 const DATA_BLOB old_cookie,
3738 TALLOC_CTX *mem_ctx,
3739 DATA_BLOB *new_cookie)
3741 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
3745 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
3746 struct smb_request *smb1req,
3747 struct smbXsrv_open *op,
3748 const DATA_BLOB old_cookie,
3749 TALLOC_CTX *mem_ctx,
3750 struct files_struct **fsp,
3751 DATA_BLOB *new_cookie)
3753 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
3754 old_cookie, mem_ctx,
3758 static struct vfs_fn_pointers vfs_default_fns = {
3759 /* Disk operations */
3761 .connect_fn = vfswrap_connect,
3762 .disconnect_fn = vfswrap_disconnect,
3763 .disk_free_fn = vfswrap_disk_free,
3764 .get_quota_fn = vfswrap_get_quota,
3765 .set_quota_fn = vfswrap_set_quota,
3766 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3767 .statvfs_fn = vfswrap_statvfs,
3768 .fs_capabilities_fn = vfswrap_fs_capabilities,
3769 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3770 .create_dfs_pathat_fn = vfswrap_create_dfs_pathat,
3771 .read_dfs_pathat_fn = vfswrap_read_dfs_pathat,
3772 .snap_check_path_fn = vfswrap_snap_check_path,
3773 .snap_create_fn = vfswrap_snap_create,
3774 .snap_delete_fn = vfswrap_snap_delete,
3776 /* Directory operations */
3778 .fdopendir_fn = vfswrap_fdopendir,
3779 .readdir_fn = vfswrap_readdir,
3780 .readdir_attr_fn = vfswrap_readdir_attr,
3781 .seekdir_fn = vfswrap_seekdir,
3782 .telldir_fn = vfswrap_telldir,
3783 .rewind_dir_fn = vfswrap_rewinddir,
3784 .mkdirat_fn = vfswrap_mkdirat,
3785 .closedir_fn = vfswrap_closedir,
3787 /* File operations */
3789 .openat_fn = vfswrap_openat,
3790 .create_file_fn = vfswrap_create_file,
3791 .close_fn = vfswrap_close,
3792 .pread_fn = vfswrap_pread,
3793 .pread_send_fn = vfswrap_pread_send,
3794 .pread_recv_fn = vfswrap_pread_recv,
3795 .pwrite_fn = vfswrap_pwrite,
3796 .pwrite_send_fn = vfswrap_pwrite_send,
3797 .pwrite_recv_fn = vfswrap_pwrite_recv,
3798 .lseek_fn = vfswrap_lseek,
3799 .sendfile_fn = vfswrap_sendfile,
3800 .recvfile_fn = vfswrap_recvfile,
3801 .renameat_fn = vfswrap_renameat,
3802 .fsync_send_fn = vfswrap_fsync_send,
3803 .fsync_recv_fn = vfswrap_fsync_recv,
3804 .stat_fn = vfswrap_stat,
3805 .fstat_fn = vfswrap_fstat,
3806 .lstat_fn = vfswrap_lstat,
3807 .get_alloc_size_fn = vfswrap_get_alloc_size,
3808 .unlinkat_fn = vfswrap_unlinkat,
3809 .fchmod_fn = vfswrap_fchmod,
3810 .fchown_fn = vfswrap_fchown,
3811 .lchown_fn = vfswrap_lchown,
3812 .chdir_fn = vfswrap_chdir,
3813 .getwd_fn = vfswrap_getwd,
3814 .fntimes_fn = vfswrap_fntimes,
3815 .ftruncate_fn = vfswrap_ftruncate,
3816 .fallocate_fn = vfswrap_fallocate,
3817 .lock_fn = vfswrap_lock,
3818 .kernel_flock_fn = vfswrap_kernel_flock,
3819 .fcntl_fn = vfswrap_fcntl,
3820 .linux_setlease_fn = vfswrap_linux_setlease,
3821 .getlock_fn = vfswrap_getlock,
3822 .symlinkat_fn = vfswrap_symlinkat,
3823 .readlinkat_fn = vfswrap_readlinkat,
3824 .linkat_fn = vfswrap_linkat,
3825 .mknodat_fn = vfswrap_mknodat,
3826 .realpath_fn = vfswrap_realpath,
3827 .chflags_fn = vfswrap_chflags,
3828 .file_id_create_fn = vfswrap_file_id_create,
3829 .fs_file_id_fn = vfswrap_fs_file_id,
3830 .streaminfo_fn = vfswrap_streaminfo,
3831 .get_real_filename_fn = vfswrap_get_real_filename,
3832 .connectpath_fn = vfswrap_connectpath,
3833 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
3834 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3835 .strict_lock_check_fn = vfswrap_strict_lock_check,
3836 .translate_name_fn = vfswrap_translate_name,
3837 .fsctl_fn = vfswrap_fsctl,
3838 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
3839 .get_dos_attributes_send_fn = vfswrap_get_dos_attributes_send,
3840 .get_dos_attributes_recv_fn = vfswrap_get_dos_attributes_recv,
3841 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
3842 .offload_read_send_fn = vfswrap_offload_read_send,
3843 .offload_read_recv_fn = vfswrap_offload_read_recv,
3844 .offload_write_send_fn = vfswrap_offload_write_send,
3845 .offload_write_recv_fn = vfswrap_offload_write_recv,
3846 .fget_compression_fn = vfswrap_fget_compression,
3847 .set_compression_fn = vfswrap_set_compression,
3849 /* NT ACL operations. */
3851 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
3852 .get_nt_acl_at_fn = vfswrap_get_nt_acl_at,
3853 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
3854 .audit_file_fn = vfswrap_audit_file,
3856 /* POSIX ACL operations. */
3858 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
3859 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3860 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
3861 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3862 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3863 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
3865 /* EA operations. */
3866 .getxattr_fn = vfswrap_getxattr,
3867 .getxattrat_send_fn = vfswrap_getxattrat_send,
3868 .getxattrat_recv_fn = vfswrap_getxattrat_recv,
3869 .fgetxattr_fn = vfswrap_fgetxattr,
3870 .flistxattr_fn = vfswrap_flistxattr,
3871 .fremovexattr_fn = vfswrap_fremovexattr,
3872 .fsetxattr_fn = vfswrap_fsetxattr,
3874 /* aio operations */
3875 .aio_force_fn = vfswrap_aio_force,
3877 /* durable handle operations */
3878 .durable_cookie_fn = vfswrap_durable_cookie,
3879 .durable_disconnect_fn = vfswrap_durable_disconnect,
3880 .durable_reconnect_fn = vfswrap_durable_reconnect,
3884 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3887 * Here we need to implement every call!
3889 * As this is the end of the vfs module chain.
3891 smb_vfs_assert_all_fns(&vfs_default_fns, DEFAULT_VFS_MODULE_NAME);
3892 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3893 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);