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"
40 #define DBGC_CLASS DBGC_VFS
42 /* Check for NULL pointer parameters in vfswrap_* functions */
44 /* We don't want to have NULL function pointers lying around. Someone
45 is sure to try and execute them. These stubs are used to prevent
48 static int vfswrap_connect(vfs_handle_struct *handle, const char *service, const char *user)
50 return 0; /* Return >= 0 for success */
53 static void vfswrap_disconnect(vfs_handle_struct *handle)
59 static uint64_t vfswrap_disk_free(vfs_handle_struct *handle,
60 const struct smb_filename *smb_fname,
65 if (sys_fsusage(smb_fname->base_name, dfree, dsize) != 0) {
73 static int vfswrap_get_quota(struct vfs_handle_struct *handle,
74 const struct smb_filename *smb_fname,
75 enum SMB_QUOTA_TYPE qtype,
79 #ifdef HAVE_SYS_QUOTAS
82 START_PROFILE(syscall_get_quota);
83 result = sys_get_quota(smb_fname->base_name, qtype, id, qt);
84 END_PROFILE(syscall_get_quota);
92 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
94 #ifdef HAVE_SYS_QUOTAS
97 START_PROFILE(syscall_set_quota);
98 result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
99 END_PROFILE(syscall_set_quota);
107 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
108 struct files_struct *fsp,
109 struct shadow_copy_data *shadow_copy_data,
113 return -1; /* Not implemented. */
116 static int vfswrap_statvfs(struct vfs_handle_struct *handle,
117 const struct smb_filename *smb_fname,
118 vfs_statvfs_struct *statbuf)
120 return sys_statvfs(smb_fname->base_name, statbuf);
123 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
124 enum timestamp_set_resolution *p_ts_res)
126 const struct loadparm_substitution *lp_sub =
127 loadparm_s3_global_substitution();
128 connection_struct *conn = handle->conn;
129 uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
130 struct smb_filename *smb_fname_cpath = NULL;
131 struct vfs_statvfs_struct statbuf;
134 smb_fname_cpath = synthetic_smb_fname(talloc_tos(), conn->connectpath,
136 if (smb_fname_cpath == NULL) {
140 ZERO_STRUCT(statbuf);
141 ret = SMB_VFS_STATVFS(conn, smb_fname_cpath, &statbuf);
143 caps = statbuf.FsCapabilities;
146 *p_ts_res = TIMESTAMP_SET_SECONDS;
148 /* Work out what timestamp resolution we can
149 * use when setting a timestamp. */
151 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
153 TALLOC_FREE(smb_fname_cpath);
157 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
158 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
159 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
160 /* If any of the normal UNIX directory timestamps
161 * have a non-zero tv_nsec component assume
162 * we might be able to set sub-second timestamps.
163 * See what filetime set primitives we have.
165 #if defined(HAVE_UTIMENSAT)
166 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
167 #elif defined(HAVE_UTIMES)
168 /* utimes allows msec timestamps to be set. */
169 *p_ts_res = TIMESTAMP_SET_MSEC;
170 #elif defined(HAVE_UTIME)
171 /* utime only allows sec timestamps to be set. */
172 *p_ts_res = TIMESTAMP_SET_SECONDS;
175 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
177 "available on share %s, directory %s\n",
178 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
179 lp_servicename(talloc_tos(), lp_sub, conn->params->service),
180 conn->connectpath ));
182 TALLOC_FREE(smb_fname_cpath);
186 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
187 struct dfs_GetDFSReferral *r)
189 struct junction_map *junction = NULL;
191 bool self_referral = false;
192 char *pathnamep = NULL;
193 char *local_dfs_path = NULL;
196 uint16_t max_referral_level = r->in.req.max_referral_level;
199 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
202 /* get the junction entry */
203 if (r->in.req.servername == NULL) {
204 return NT_STATUS_NOT_FOUND;
208 * Trim pathname sent by client so it begins with only one backslash.
209 * Two backslashes confuse some dfs clients
212 local_dfs_path = talloc_strdup(r, r->in.req.servername);
213 if (local_dfs_path == NULL) {
214 return NT_STATUS_NO_MEMORY;
216 pathnamep = local_dfs_path;
217 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
218 IS_DIRECTORY_SEP(pathnamep[1])) {
222 junction = talloc_zero(r, struct junction_map);
223 if (junction == NULL) {
224 return NT_STATUS_NO_MEMORY;
227 /* The following call can change cwd. */
228 status = get_referred_path(r,
229 handle->conn->session_info,
231 handle->conn->sconn->remote_address,
232 handle->conn->sconn->local_address,
233 !handle->conn->sconn->using_smb2,
234 junction, &consumedcnt, &self_referral);
235 if (!NT_STATUS_IS_OK(status)) {
236 struct smb_filename connectpath_fname = {
237 .base_name = handle->conn->connectpath
239 vfs_ChDir(handle->conn, &connectpath_fname);
243 struct smb_filename connectpath_fname = {
244 .base_name = handle->conn->connectpath
246 vfs_ChDir(handle->conn, &connectpath_fname);
249 if (!self_referral) {
250 pathnamep[consumedcnt] = '\0';
253 dbgtext("Path %s to alternate path(s):",
255 for (i=0; i < junction->referral_count; i++) {
257 junction->referral_list[i].alternate_path);
263 if (r->in.req.max_referral_level <= 2) {
264 max_referral_level = 2;
266 if (r->in.req.max_referral_level >= 3) {
267 max_referral_level = 3;
270 r->out.resp = talloc_zero(r, struct dfs_referral_resp);
271 if (r->out.resp == NULL) {
272 return NT_STATUS_NO_MEMORY;
275 r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
276 r->out.resp->nb_referrals = junction->referral_count;
278 r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
280 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
283 r->out.resp->referral_entries = talloc_zero_array(r,
284 struct dfs_referral_type,
285 r->out.resp->nb_referrals);
286 if (r->out.resp->referral_entries == NULL) {
287 return NT_STATUS_NO_MEMORY;
290 switch (max_referral_level) {
292 for(i=0; i < junction->referral_count; i++) {
293 struct referral *ref = &junction->referral_list[i];
294 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
295 struct dfs_referral_type *t =
296 &r->out.resp->referral_entries[i];
297 struct dfs_referral_v2 *v2 = &t->referral.v2;
300 v2->size = VERSION2_REFERRAL_SIZE;
302 v2->server_type = DFS_SERVER_ROOT;
304 v2->server_type = DFS_SERVER_NON_ROOT;
307 v2->proximity = ref->proximity;
309 v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
310 if (v2->DFS_path == NULL) {
311 return NT_STATUS_NO_MEMORY;
313 v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
314 if (v2->DFS_alt_path == NULL) {
315 return NT_STATUS_NO_MEMORY;
317 v2->netw_address = talloc_strdup(mem_ctx,
318 ref->alternate_path);
319 if (v2->netw_address == NULL) {
320 return NT_STATUS_NO_MEMORY;
326 for(i=0; i < junction->referral_count; i++) {
327 struct referral *ref = &junction->referral_list[i];
328 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
329 struct dfs_referral_type *t =
330 &r->out.resp->referral_entries[i];
331 struct dfs_referral_v3 *v3 = &t->referral.v3;
332 struct dfs_normal_referral *r1 = &v3->referrals.r1;
335 v3->size = VERSION3_REFERRAL_SIZE;
337 v3->server_type = DFS_SERVER_ROOT;
339 v3->server_type = DFS_SERVER_NON_ROOT;
343 r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
344 if (r1->DFS_path == NULL) {
345 return NT_STATUS_NO_MEMORY;
347 r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
348 if (r1->DFS_alt_path == NULL) {
349 return NT_STATUS_NO_MEMORY;
351 r1->netw_address = talloc_strdup(mem_ctx,
352 ref->alternate_path);
353 if (r1->netw_address == NULL) {
354 return NT_STATUS_NO_MEMORY;
359 DEBUG(0,("Invalid dfs referral version: %d\n",
360 max_referral_level));
361 return NT_STATUS_INVALID_LEVEL;
365 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
371 static NTSTATUS vfswrap_create_dfs_pathat(struct vfs_handle_struct *handle,
372 struct files_struct *dirfsp,
373 const struct smb_filename *smb_fname,
374 const struct referral *reflist,
375 size_t referral_count)
377 TALLOC_CTX *frame = talloc_stackframe();
378 NTSTATUS status = NT_STATUS_NO_MEMORY;
380 char *msdfs_link = NULL;
382 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
384 /* Form the msdfs_link contents */
385 msdfs_link = msdfs_link_string(frame,
388 if (msdfs_link == NULL) {
392 ret = symlinkat(msdfs_link,
394 smb_fname->base_name);
396 status = NT_STATUS_OK;
398 status = map_nt_error_from_unix(errno);
408 * Read and return the contents of a DFS redirect given a
409 * pathname. A caller can pass in NULL for ppreflist and
410 * preferral_count but still determine if this was a
411 * DFS redirect point by getting NT_STATUS_OK back
412 * without incurring the overhead of reading and parsing
413 * the referral contents.
416 static NTSTATUS vfswrap_read_dfs_pathat(struct vfs_handle_struct *handle,
418 struct files_struct *dirfsp,
419 const struct smb_filename *smb_fname,
420 struct referral **ppreflist,
421 size_t *preferral_count)
423 NTSTATUS status = NT_STATUS_NO_MEMORY;
425 char *link_target = NULL;
428 #if defined(HAVE_BROKEN_READLINK)
429 char link_target_buf[PATH_MAX];
431 char link_target_buf[7];
434 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
436 if (ppreflist == NULL && preferral_count == NULL) {
438 * We're only checking if this is a DFS
439 * redirect. We don't need to return data.
441 bufsize = sizeof(link_target_buf);
442 link_target = link_target_buf;
445 link_target = talloc_array(mem_ctx, char, bufsize);
451 referral_len = readlinkat(dirfsp->fh->fd,
452 smb_fname->base_name,
455 if (referral_len == -1) {
456 if (errno == EINVAL) {
458 * If the path isn't a link, readlinkat
459 * returns EINVAL. Allow the caller to
462 DBG_INFO("%s is not a link.\n", smb_fname->base_name);
463 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
465 status = map_nt_error_from_unix(errno);
466 DBG_ERR("Error reading "
467 "msdfs link %s: %s\n",
468 smb_fname->base_name,
473 link_target[referral_len] = '\0';
475 DBG_INFO("%s -> %s\n",
476 smb_fname->base_name,
479 if (!strnequal(link_target, "msdfs:", 6)) {
480 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
484 if (ppreflist == NULL && preferral_count == NULL) {
485 /* Early return for checking if this is a DFS link. */
489 ok = parse_msdfs_symlink(mem_ctx,
490 lp_msdfs_shuffle_referrals(SNUM(handle->conn)),
496 status = NT_STATUS_OK;
498 status = NT_STATUS_NO_MEMORY;
503 if (link_target != link_target_buf) {
504 TALLOC_FREE(link_target);
509 static NTSTATUS vfswrap_snap_check_path(struct vfs_handle_struct *handle,
511 const char *service_path,
514 return NT_STATUS_NOT_SUPPORTED;
517 static NTSTATUS vfswrap_snap_create(struct vfs_handle_struct *handle,
519 const char *base_volume,
525 return NT_STATUS_NOT_SUPPORTED;
528 static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle,
533 return NT_STATUS_NOT_SUPPORTED;
536 /* Directory operations */
538 static DIR *vfswrap_opendir(vfs_handle_struct *handle,
539 const struct smb_filename *smb_fname,
545 START_PROFILE(syscall_opendir);
546 result = opendir(smb_fname->base_name);
547 END_PROFILE(syscall_opendir);
551 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
558 START_PROFILE(syscall_fdopendir);
559 result = sys_fdopendir(fsp->fh->fd);
560 END_PROFILE(syscall_fdopendir);
565 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
567 SMB_STRUCT_STAT *sbuf)
569 struct dirent *result;
571 START_PROFILE(syscall_readdir);
572 result = readdir(dirp);
573 END_PROFILE(syscall_readdir);
575 /* Default Posix readdir() does not give us stat info.
576 * Set to invalid to indicate we didn't return this info. */
577 SET_STAT_INVALID(*sbuf);
578 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
579 if (result != NULL) {
580 /* See if we can efficiently return this. */
582 int flags = AT_SYMLINK_NOFOLLOW;
583 int ret = fstatat(dirfd(dirp),
588 * As this is an optimization,
589 * ignore it if we stat'ed a
590 * symlink. Make the caller
591 * do it again as we don't
592 * know if they wanted the link
593 * info, or its target info.
595 if ((ret == 0) && (!S_ISLNK(st.st_mode))) {
596 init_stat_ex_from_stat(sbuf,
598 lp_fake_directory_create_times(
599 SNUM(handle->conn)));
607 static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
608 const struct smb_filename *fname,
610 struct readdir_attr_data **attr_data)
612 return NT_STATUS_NOT_SUPPORTED;
615 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
617 START_PROFILE(syscall_seekdir);
618 seekdir(dirp, offset);
619 END_PROFILE(syscall_seekdir);
622 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
625 START_PROFILE(syscall_telldir);
626 result = telldir(dirp);
627 END_PROFILE(syscall_telldir);
631 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
633 START_PROFILE(syscall_rewinddir);
635 END_PROFILE(syscall_rewinddir);
638 static int vfswrap_mkdirat(vfs_handle_struct *handle,
639 struct files_struct *dirfsp,
640 const struct smb_filename *smb_fname,
644 const char *path = smb_fname->base_name;
647 START_PROFILE(syscall_mkdirat);
649 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
651 if (lp_inherit_acls(SNUM(handle->conn))
652 && parent_dirname(talloc_tos(), path, &parent, NULL)
653 && directory_has_default_acl(handle->conn, parent)) {
654 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
659 result = mkdirat(dirfsp->fh->fd, path, mode);
661 END_PROFILE(syscall_mkdirat);
665 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
669 START_PROFILE(syscall_closedir);
670 result = closedir(dirp);
671 END_PROFILE(syscall_closedir);
675 /* File operations */
677 static int vfswrap_open(vfs_handle_struct *handle,
678 struct smb_filename *smb_fname,
679 files_struct *fsp, int flags, mode_t mode)
683 START_PROFILE(syscall_open);
685 if (is_named_stream(smb_fname)) {
690 result = open(smb_fname->base_name, flags, mode);
692 END_PROFILE(syscall_open);
696 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
697 struct smb_request *req,
698 uint16_t root_dir_fid,
699 struct smb_filename *smb_fname,
700 uint32_t access_mask,
701 uint32_t share_access,
702 uint32_t create_disposition,
703 uint32_t create_options,
704 uint32_t file_attributes,
705 uint32_t oplock_request,
706 const struct smb2_lease *lease,
707 uint64_t allocation_size,
708 uint32_t private_flags,
709 struct security_descriptor *sd,
710 struct ea_list *ea_list,
711 files_struct **result,
713 const struct smb2_create_blobs *in_context_blobs,
714 struct smb2_create_blobs *out_context_blobs)
716 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
717 access_mask, share_access,
718 create_disposition, create_options,
719 file_attributes, oplock_request, lease,
720 allocation_size, private_flags,
722 pinfo, in_context_blobs, out_context_blobs);
725 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
729 START_PROFILE(syscall_close);
730 result = fd_close_posix(fsp);
731 END_PROFILE(syscall_close);
735 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
736 size_t n, off_t offset)
740 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
741 START_PROFILE_BYTES(syscall_pread, n);
742 result = sys_pread(fsp->fh->fd, data, n, offset);
743 END_PROFILE_BYTES(syscall_pread);
745 if (result == -1 && errno == ESPIPE) {
746 /* Maintain the fiction that pipes can be seeked (sought?) on. */
747 result = sys_read(fsp->fh->fd, data, n);
751 #else /* HAVE_PREAD */
754 #endif /* HAVE_PREAD */
759 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
760 size_t n, off_t offset)
764 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
765 START_PROFILE_BYTES(syscall_pwrite, n);
766 result = sys_pwrite(fsp->fh->fd, data, n, offset);
767 END_PROFILE_BYTES(syscall_pwrite);
769 if (result == -1 && errno == ESPIPE) {
770 /* Maintain the fiction that pipes can be sought on. */
771 result = sys_write(fsp->fh->fd, data, n);
774 #else /* HAVE_PWRITE */
777 #endif /* HAVE_PWRITE */
782 struct vfswrap_pread_state {
783 struct tevent_req *req;
790 struct vfs_aio_state vfs_aio_state;
791 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
794 static void vfs_pread_do(void *private_data);
795 static void vfs_pread_done(struct tevent_req *subreq);
796 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state);
798 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
800 struct tevent_context *ev,
801 struct files_struct *fsp,
803 size_t n, off_t offset)
805 struct tevent_req *req, *subreq;
806 struct vfswrap_pread_state *state;
808 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
815 state->fd = fsp->fh->fd;
818 state->offset = offset;
820 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
821 state->profile_bytes, n);
822 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
824 subreq = pthreadpool_tevent_job_send(
825 state, ev, handle->conn->sconn->pool,
826 vfs_pread_do, state);
827 if (tevent_req_nomem(subreq, req)) {
828 return tevent_req_post(req, ev);
830 tevent_req_set_callback(subreq, vfs_pread_done, state);
832 talloc_set_destructor(state, vfs_pread_state_destructor);
837 static void vfs_pread_do(void *private_data)
839 struct vfswrap_pread_state *state = talloc_get_type_abort(
840 private_data, struct vfswrap_pread_state);
841 struct timespec start_time;
842 struct timespec end_time;
844 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
846 PROFILE_TIMESTAMP(&start_time);
849 state->ret = pread(state->fd, state->buf, state->count,
851 } while ((state->ret == -1) && (errno == EINTR));
853 if (state->ret == -1) {
854 state->vfs_aio_state.error = errno;
857 PROFILE_TIMESTAMP(&end_time);
859 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
861 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
864 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state)
867 * This destructor only gets called if the request is still
868 * in flight, which is why we deny it by returning -1. We
869 * also set the req pointer to NULL so the _done function
870 * can detect the caller doesn't want the result anymore.
872 * Forcing the fsp closed by a SHUTDOWN_CLOSE can cause this.
878 static void vfs_pread_done(struct tevent_req *subreq)
880 struct vfswrap_pread_state *state = tevent_req_callback_data(
881 subreq, struct vfswrap_pread_state);
882 struct tevent_req *req = state->req;
885 ret = pthreadpool_tevent_job_recv(subreq);
887 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
888 talloc_set_destructor(state, NULL);
891 * We were shutdown closed in flight. No one
892 * wants the result, and state has been reparented
893 * to the NULL context, so just free it so we
896 DBG_NOTICE("pread request abandoned in flight\n");
902 tevent_req_error(req, ret);
906 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
907 * means the lower level pthreadpool failed to create a new
908 * thread. Fallback to sync processing in that case to allow
909 * some progress for the client.
914 tevent_req_done(req);
917 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
918 struct vfs_aio_state *vfs_aio_state)
920 struct vfswrap_pread_state *state = tevent_req_data(
921 req, struct vfswrap_pread_state);
923 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
927 *vfs_aio_state = state->vfs_aio_state;
931 struct vfswrap_pwrite_state {
932 struct tevent_req *req;
939 struct vfs_aio_state vfs_aio_state;
940 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
943 static void vfs_pwrite_do(void *private_data);
944 static void vfs_pwrite_done(struct tevent_req *subreq);
945 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state);
947 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
949 struct tevent_context *ev,
950 struct files_struct *fsp,
952 size_t n, off_t offset)
954 struct tevent_req *req, *subreq;
955 struct vfswrap_pwrite_state *state;
957 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
964 state->fd = fsp->fh->fd;
967 state->offset = offset;
969 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
970 state->profile_bytes, n);
971 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
973 subreq = pthreadpool_tevent_job_send(
974 state, ev, handle->conn->sconn->pool,
975 vfs_pwrite_do, state);
976 if (tevent_req_nomem(subreq, req)) {
977 return tevent_req_post(req, ev);
979 tevent_req_set_callback(subreq, vfs_pwrite_done, state);
981 talloc_set_destructor(state, vfs_pwrite_state_destructor);
986 static void vfs_pwrite_do(void *private_data)
988 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
989 private_data, struct vfswrap_pwrite_state);
990 struct timespec start_time;
991 struct timespec end_time;
993 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
995 PROFILE_TIMESTAMP(&start_time);
998 state->ret = pwrite(state->fd, state->buf, state->count,
1000 } while ((state->ret == -1) && (errno == EINTR));
1002 if (state->ret == -1) {
1003 state->vfs_aio_state.error = errno;
1006 PROFILE_TIMESTAMP(&end_time);
1008 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1010 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1013 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state)
1016 * This destructor only gets called if the request is still
1017 * in flight, which is why we deny it by returning -1. We
1018 * also set the req pointer to NULL so the _done function
1019 * can detect the caller doesn't want the result anymore.
1021 * Forcing the fsp closed by a SHUTDOWN_CLOSE can cause this.
1027 static void vfs_pwrite_done(struct tevent_req *subreq)
1029 struct vfswrap_pwrite_state *state = tevent_req_callback_data(
1030 subreq, struct vfswrap_pwrite_state);
1031 struct tevent_req *req = state->req;
1034 ret = pthreadpool_tevent_job_recv(subreq);
1035 TALLOC_FREE(subreq);
1036 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1037 talloc_set_destructor(state, NULL);
1040 * We were shutdown closed in flight. No one
1041 * wants the result, and state has been reparented
1042 * to the NULL context, so just free it so we
1043 * don't leak memory.
1045 DBG_NOTICE("pwrite request abandoned in flight\n");
1050 if (ret != EAGAIN) {
1051 tevent_req_error(req, ret);
1055 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1056 * means the lower level pthreadpool failed to create a new
1057 * thread. Fallback to sync processing in that case to allow
1058 * some progress for the client.
1060 vfs_pwrite_do(state);
1063 tevent_req_done(req);
1066 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
1067 struct vfs_aio_state *vfs_aio_state)
1069 struct vfswrap_pwrite_state *state = tevent_req_data(
1070 req, struct vfswrap_pwrite_state);
1072 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1076 *vfs_aio_state = state->vfs_aio_state;
1080 struct vfswrap_fsync_state {
1081 struct tevent_req *req;
1085 struct vfs_aio_state vfs_aio_state;
1086 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
1089 static void vfs_fsync_do(void *private_data);
1090 static void vfs_fsync_done(struct tevent_req *subreq);
1091 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state);
1093 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
1094 TALLOC_CTX *mem_ctx,
1095 struct tevent_context *ev,
1096 struct files_struct *fsp)
1098 struct tevent_req *req, *subreq;
1099 struct vfswrap_fsync_state *state;
1101 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
1108 state->fd = fsp->fh->fd;
1110 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_fsync, profile_p,
1111 state->profile_bytes, 0);
1112 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1114 subreq = pthreadpool_tevent_job_send(
1115 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
1116 if (tevent_req_nomem(subreq, req)) {
1117 return tevent_req_post(req, ev);
1119 tevent_req_set_callback(subreq, vfs_fsync_done, state);
1121 talloc_set_destructor(state, vfs_fsync_state_destructor);
1126 static void vfs_fsync_do(void *private_data)
1128 struct vfswrap_fsync_state *state = talloc_get_type_abort(
1129 private_data, struct vfswrap_fsync_state);
1130 struct timespec start_time;
1131 struct timespec end_time;
1133 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
1135 PROFILE_TIMESTAMP(&start_time);
1138 state->ret = fsync(state->fd);
1139 } while ((state->ret == -1) && (errno == EINTR));
1141 if (state->ret == -1) {
1142 state->vfs_aio_state.error = errno;
1145 PROFILE_TIMESTAMP(&end_time);
1147 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1149 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1152 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state)
1155 * This destructor only gets called if the request is still
1156 * in flight, which is why we deny it by returning -1. We
1157 * also set the req pointer to NULL so the _done function
1158 * can detect the caller doesn't want the result anymore.
1160 * Forcing the fsp closed by a SHUTDOWN_CLOSE can cause this.
1166 static void vfs_fsync_done(struct tevent_req *subreq)
1168 struct vfswrap_fsync_state *state = tevent_req_callback_data(
1169 subreq, struct vfswrap_fsync_state);
1170 struct tevent_req *req = state->req;
1173 ret = pthreadpool_tevent_job_recv(subreq);
1174 TALLOC_FREE(subreq);
1175 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1176 talloc_set_destructor(state, NULL);
1179 * We were shutdown closed in flight. No one
1180 * wants the result, and state has been reparented
1181 * to the NULL context, so just free it so we
1182 * don't leak memory.
1184 DBG_NOTICE("fsync request abandoned in flight\n");
1189 if (ret != EAGAIN) {
1190 tevent_req_error(req, ret);
1194 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1195 * means the lower level pthreadpool failed to create a new
1196 * thread. Fallback to sync processing in that case to allow
1197 * some progress for the client.
1199 vfs_fsync_do(state);
1202 tevent_req_done(req);
1205 static int vfswrap_fsync_recv(struct tevent_req *req,
1206 struct vfs_aio_state *vfs_aio_state)
1208 struct vfswrap_fsync_state *state = tevent_req_data(
1209 req, struct vfswrap_fsync_state);
1211 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1215 *vfs_aio_state = state->vfs_aio_state;
1219 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1223 START_PROFILE(syscall_lseek);
1225 result = lseek(fsp->fh->fd, offset, whence);
1227 * We want to maintain the fiction that we can seek
1228 * on a fifo for file system purposes. This allows
1229 * people to set up UNIX fifo's that feed data to Windows
1230 * applications. JRA.
1233 if((result == -1) && (errno == ESPIPE)) {
1238 END_PROFILE(syscall_lseek);
1242 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1243 off_t offset, size_t n)
1247 START_PROFILE_BYTES(syscall_sendfile, n);
1248 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
1249 END_PROFILE_BYTES(syscall_sendfile);
1253 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1255 files_struct *tofsp,
1261 START_PROFILE_BYTES(syscall_recvfile, n);
1262 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
1263 END_PROFILE_BYTES(syscall_recvfile);
1267 static int vfswrap_renameat(vfs_handle_struct *handle,
1268 files_struct *srcfsp,
1269 const struct smb_filename *smb_fname_src,
1270 files_struct *dstfsp,
1271 const struct smb_filename *smb_fname_dst)
1275 START_PROFILE(syscall_renameat);
1277 if (is_named_stream(smb_fname_src) || is_named_stream(smb_fname_dst)) {
1282 result = renameat(srcfsp->fh->fd,
1283 smb_fname_src->base_name,
1285 smb_fname_dst->base_name);
1288 END_PROFILE(syscall_renameat);
1292 static int vfswrap_stat(vfs_handle_struct *handle,
1293 struct smb_filename *smb_fname)
1297 START_PROFILE(syscall_stat);
1299 if (is_named_stream(smb_fname)) {
1304 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1305 lp_fake_directory_create_times(SNUM(handle->conn)));
1307 END_PROFILE(syscall_stat);
1311 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1315 START_PROFILE(syscall_fstat);
1316 result = sys_fstat(fsp->fh->fd,
1317 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1318 END_PROFILE(syscall_fstat);
1322 static int vfswrap_lstat(vfs_handle_struct *handle,
1323 struct smb_filename *smb_fname)
1327 START_PROFILE(syscall_lstat);
1329 if (is_named_stream(smb_fname)) {
1334 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1335 lp_fake_directory_create_times(SNUM(handle->conn)));
1337 END_PROFILE(syscall_lstat);
1341 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1343 enum vfs_translate_direction direction,
1344 TALLOC_CTX *mem_ctx,
1347 return NT_STATUS_NONE_MAPPED;
1351 * Implement the default fsctl operation.
1353 static bool vfswrap_logged_ioctl_message = false;
1355 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1356 struct files_struct *fsp,
1359 uint16_t req_flags, /* Needed for UNICODE ... */
1360 const uint8_t *_in_data,
1362 uint8_t **_out_data,
1363 uint32_t max_out_len,
1366 const char *in_data = (const char *)_in_data;
1367 char **out_data = (char **)_out_data;
1371 case FSCTL_SET_SPARSE:
1373 bool set_sparse = true;
1375 if (in_len >= 1 && in_data[0] == 0) {
1379 status = file_set_sparse(handle->conn, fsp, set_sparse);
1381 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1382 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1383 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1384 nt_errstr(status)));
1389 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1391 unsigned char objid[16];
1392 char *return_data = NULL;
1394 /* This should return the object-id on this file.
1395 * I think I'll make this be the inode+dev. JRA.
1398 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1399 fsp_fnum_dbg(fsp)));
1401 *out_len = MIN(max_out_len, 64);
1403 /* Hmmm, will this cause problems if less data asked for? */
1404 return_data = talloc_array(ctx, char, 64);
1405 if (return_data == NULL) {
1406 return NT_STATUS_NO_MEMORY;
1409 /* For backwards compatibility only store the dev/inode. */
1410 push_file_id_16(return_data, &fsp->file_id);
1411 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1412 push_file_id_16(return_data+32, &fsp->file_id);
1413 memset(return_data+48, 0, 16);
1414 *out_data = return_data;
1415 return NT_STATUS_OK;
1418 case FSCTL_GET_REPARSE_POINT:
1420 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1421 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1422 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1423 return NT_STATUS_NOT_A_REPARSE_POINT;
1426 case FSCTL_SET_REPARSE_POINT:
1428 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1429 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1430 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1431 return NT_STATUS_NOT_A_REPARSE_POINT;
1434 case FSCTL_GET_SHADOW_COPY_DATA:
1437 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1438 * and return their volume names. If max_data_count is 16, then it is just
1439 * asking for the number of volumes and length of the combined names.
1441 * pdata is the data allocated by our caller, but that uses
1442 * total_data_count (which is 0 in our case) rather than max_data_count.
1443 * Allocate the correct amount and return the pointer to let
1444 * it be deallocated when we return.
1446 struct shadow_copy_data *shadow_data = NULL;
1447 bool labels = False;
1448 uint32_t labels_data_count = 0;
1450 char *cur_pdata = NULL;
1452 if (max_out_len < 16) {
1453 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1455 return NT_STATUS_INVALID_PARAMETER;
1458 if (max_out_len > 16) {
1462 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1463 if (shadow_data == NULL) {
1464 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1465 return NT_STATUS_NO_MEMORY;
1469 * Call the VFS routine to actually do the work.
1471 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1474 /* broken module didn't set errno on error */
1475 status = NT_STATUS_UNSUCCESSFUL;
1477 status = map_nt_error_from_unix(errno);
1478 if (NT_STATUS_EQUAL(status,
1479 NT_STATUS_NOT_SUPPORTED)) {
1483 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1484 "connectpath %s, failed - %s.\n",
1485 fsp->conn->connectpath,
1486 nt_errstr(status)));
1487 TALLOC_FREE(shadow_data);
1491 labels_data_count = (shadow_data->num_volumes * 2 *
1492 sizeof(SHADOW_COPY_LABEL)) + 2;
1497 *out_len = 12 + labels_data_count;
1500 if (max_out_len < *out_len) {
1501 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1502 max_out_len, *out_len));
1503 TALLOC_FREE(shadow_data);
1504 return NT_STATUS_BUFFER_TOO_SMALL;
1507 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1508 if (cur_pdata == NULL) {
1509 TALLOC_FREE(shadow_data);
1510 return NT_STATUS_NO_MEMORY;
1513 *out_data = cur_pdata;
1515 /* num_volumes 4 bytes */
1516 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1519 /* num_labels 4 bytes */
1520 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1523 /* needed_data_count 4 bytes */
1524 SIVAL(cur_pdata, 8, labels_data_count);
1528 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1529 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1530 if (labels && shadow_data->labels) {
1531 for (i=0; i<shadow_data->num_volumes; i++) {
1533 status = srvstr_push(cur_pdata, req_flags,
1534 cur_pdata, shadow_data->labels[i],
1535 2 * sizeof(SHADOW_COPY_LABEL),
1536 STR_UNICODE|STR_TERMINATE, &len);
1537 if (!NT_STATUS_IS_OK(status)) {
1538 TALLOC_FREE(*out_data);
1539 TALLOC_FREE(shadow_data);
1542 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1543 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1547 TALLOC_FREE(shadow_data);
1549 return NT_STATUS_OK;
1552 case FSCTL_FIND_FILES_BY_SID:
1554 /* pretend this succeeded -
1556 * we have to send back a list with all files owned by this SID
1558 * but I have to check that --metze
1562 struct dom_sid_buf buf;
1566 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1567 fsp_fnum_dbg(fsp)));
1570 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1571 return NT_STATUS_INVALID_PARAMETER;
1574 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1576 /* unknown 4 bytes: this is not the length of the sid :-( */
1577 /*unknown = IVAL(pdata,0);*/
1579 ret = sid_parse(_in_data + 4, sid_len, &sid);
1581 return NT_STATUS_INVALID_PARAMETER;
1583 DEBUGADD(10, ("for SID: %s\n",
1584 dom_sid_str_buf(&sid, &buf)));
1586 if (!sid_to_uid(&sid, &uid)) {
1587 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1588 dom_sid_str_buf(&sid, &buf),
1589 (unsigned long)sid_len));
1593 /* we can take a look at the find source :-)
1595 * find ./ -uid $uid -name '*' is what we need here
1598 * and send 4bytes len and then NULL terminated unicode strings
1601 * but I don't know how to deal with the paged results
1602 * (maybe we can hang the result anywhere in the fsp struct)
1604 * but I don't know how to deal with the paged results
1605 * (maybe we can hang the result anywhere in the fsp struct)
1607 * we don't send all files at once
1608 * and at the next we should *not* start from the beginning,
1609 * so we have to cache the result
1614 /* this works for now... */
1615 return NT_STATUS_OK;
1618 case FSCTL_QUERY_ALLOCATED_RANGES:
1620 /* FIXME: This is just a dummy reply, telling that all of the
1621 * file is allocated. MKS cp needs that.
1622 * Adding the real allocated ranges via FIEMAP on Linux
1623 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1624 * this FSCTL correct for sparse files.
1626 uint64_t offset, length;
1627 char *out_data_tmp = NULL;
1630 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1632 return NT_STATUS_INVALID_PARAMETER;
1635 if (max_out_len < 16) {
1636 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1638 return NT_STATUS_INVALID_PARAMETER;
1641 offset = BVAL(in_data,0);
1642 length = BVAL(in_data,8);
1644 if (offset + length < offset) {
1645 /* No 64-bit integer wrap. */
1646 return NT_STATUS_INVALID_PARAMETER;
1649 /* Shouldn't this be SMB_VFS_STAT ... ? */
1650 status = vfs_stat_fsp(fsp);
1651 if (!NT_STATUS_IS_OK(status)) {
1656 out_data_tmp = talloc_array(ctx, char, *out_len);
1657 if (out_data_tmp == NULL) {
1658 DEBUG(10, ("unable to allocate memory for response\n"));
1659 return NT_STATUS_NO_MEMORY;
1662 if (offset > fsp->fsp_name->st.st_ex_size ||
1663 fsp->fsp_name->st.st_ex_size == 0 ||
1665 memset(out_data_tmp, 0, *out_len);
1667 uint64_t end = offset + length;
1668 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1669 SBVAL(out_data_tmp, 0, 0);
1670 SBVAL(out_data_tmp, 8, end);
1673 *out_data = out_data_tmp;
1675 return NT_STATUS_OK;
1678 case FSCTL_IS_VOLUME_DIRTY:
1680 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1681 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1683 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1684 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1686 return NT_STATUS_INVALID_PARAMETER;
1691 * Only print once ... unfortunately there could be lots of
1692 * different FSCTLs that are called.
1694 if (!vfswrap_logged_ioctl_message) {
1695 vfswrap_logged_ioctl_message = true;
1696 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1697 __func__, function));
1701 return NT_STATUS_NOT_SUPPORTED;
1704 static bool vfswrap_is_offline(struct connection_struct *conn,
1705 const struct smb_filename *fname);
1707 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1708 struct smb_filename *smb_fname,
1713 offline = vfswrap_is_offline(handle->conn, smb_fname);
1715 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1718 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1721 struct vfswrap_get_dos_attributes_state {
1722 struct vfs_aio_state aio_state;
1723 connection_struct *conn;
1724 TALLOC_CTX *mem_ctx;
1725 struct tevent_context *ev;
1726 files_struct *dir_fsp;
1727 struct smb_filename *smb_fname;
1732 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq);
1734 static struct tevent_req *vfswrap_get_dos_attributes_send(
1735 TALLOC_CTX *mem_ctx,
1736 struct tevent_context *ev,
1737 struct vfs_handle_struct *handle,
1738 files_struct *dir_fsp,
1739 struct smb_filename *smb_fname)
1741 struct tevent_req *req = NULL;
1742 struct tevent_req *subreq = NULL;
1743 struct vfswrap_get_dos_attributes_state *state = NULL;
1745 req = tevent_req_create(mem_ctx, &state,
1746 struct vfswrap_get_dos_attributes_state);
1751 *state = (struct vfswrap_get_dos_attributes_state) {
1752 .conn = dir_fsp->conn,
1756 .smb_fname = smb_fname,
1759 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1763 SAMBA_XATTR_DOS_ATTRIB,
1765 if (tevent_req_nomem(subreq, req)) {
1766 return tevent_req_post(req, ev);
1768 tevent_req_set_callback(subreq,
1769 vfswrap_get_dos_attributes_getxattr_done,
1775 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq)
1777 struct tevent_req *req =
1778 tevent_req_callback_data(subreq,
1780 struct vfswrap_get_dos_attributes_state *state =
1781 tevent_req_data(req,
1782 struct vfswrap_get_dos_attributes_state);
1784 DATA_BLOB blob = {0};
1786 char *tofree = NULL;
1787 char pathbuf[PATH_MAX+1];
1789 struct smb_filename smb_fname;
1793 xattr_size = SMB_VFS_GETXATTRAT_RECV(subreq,
1797 TALLOC_FREE(subreq);
1798 if (xattr_size == -1) {
1799 status = map_nt_error_from_unix(state->aio_state.error);
1801 if (state->as_root) {
1802 tevent_req_nterror(req, status);
1805 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1806 tevent_req_nterror(req, status);
1810 state->as_root = true;
1813 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1817 SAMBA_XATTR_DOS_ATTRIB,
1820 if (tevent_req_nomem(subreq, req)) {
1823 tevent_req_set_callback(subreq,
1824 vfswrap_get_dos_attributes_getxattr_done,
1829 blob.length = xattr_size;
1831 status = parse_dos_attribute_blob(state->smb_fname,
1834 if (!NT_STATUS_IS_OK(status)) {
1835 tevent_req_nterror(req, status);
1839 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
1840 state->smb_fname->base_name,
1845 if (pathlen == -1) {
1846 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1850 smb_fname = (struct smb_filename) {
1852 .st = state->smb_fname->st,
1853 .flags = state->smb_fname->flags,
1856 offline = vfswrap_is_offline(state->conn, &smb_fname);
1858 state->dosmode |= FILE_ATTRIBUTE_OFFLINE;
1860 TALLOC_FREE(tofree);
1862 tevent_req_done(req);
1866 static NTSTATUS vfswrap_get_dos_attributes_recv(struct tevent_req *req,
1867 struct vfs_aio_state *aio_state,
1870 struct vfswrap_get_dos_attributes_state *state =
1871 tevent_req_data(req,
1872 struct vfswrap_get_dos_attributes_state);
1875 if (tevent_req_is_nterror(req, &status)) {
1876 tevent_req_received(req);
1880 *aio_state = state->aio_state;
1881 *dosmode = state->dosmode;
1882 tevent_req_received(req);
1883 return NT_STATUS_OK;
1886 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1887 struct files_struct *fsp,
1892 offline = vfswrap_is_offline(handle->conn, fsp->fsp_name);
1894 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1897 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1900 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1901 const struct smb_filename *smb_fname,
1904 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1907 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1908 struct files_struct *fsp,
1911 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1914 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1916 struct vfswrap_offload_read_state {
1920 static struct tevent_req *vfswrap_offload_read_send(
1921 TALLOC_CTX *mem_ctx,
1922 struct tevent_context *ev,
1923 struct vfs_handle_struct *handle,
1924 struct files_struct *fsp,
1930 struct tevent_req *req = NULL;
1931 struct vfswrap_offload_read_state *state = NULL;
1934 req = tevent_req_create(mem_ctx, &state,
1935 struct vfswrap_offload_read_state);
1940 status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1941 &vfswrap_offload_ctx);
1942 if (tevent_req_nterror(req, status)) {
1943 return tevent_req_post(req, ev);
1946 if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1947 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1948 return tevent_req_post(req, ev);
1951 status = vfs_offload_token_create_blob(state, fsp, fsctl,
1953 if (tevent_req_nterror(req, status)) {
1954 return tevent_req_post(req, ev);
1957 status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1959 if (tevent_req_nterror(req, status)) {
1960 return tevent_req_post(req, ev);
1963 tevent_req_done(req);
1964 return tevent_req_post(req, ev);
1967 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
1968 struct vfs_handle_struct *handle,
1969 TALLOC_CTX *mem_ctx,
1972 struct vfswrap_offload_read_state *state = tevent_req_data(
1973 req, struct vfswrap_offload_read_state);
1976 if (tevent_req_is_nterror(req, &status)) {
1977 tevent_req_received(req);
1981 token->length = state->token.length;
1982 token->data = talloc_move(mem_ctx, &state->token.data);
1984 tevent_req_received(req);
1985 return NT_STATUS_OK;
1988 struct vfswrap_offload_write_state {
1990 bool read_lck_locked;
1991 bool write_lck_locked;
1993 struct tevent_context *src_ev;
1994 struct files_struct *src_fsp;
1996 struct tevent_context *dst_ev;
1997 struct files_struct *dst_fsp;
2001 size_t next_io_size;
2004 static void vfswrap_offload_write_cleanup(struct tevent_req *req,
2005 enum tevent_req_state req_state)
2007 struct vfswrap_offload_write_state *state = tevent_req_data(
2008 req, struct vfswrap_offload_write_state);
2011 if (state->dst_fsp == NULL) {
2015 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2017 state->dst_fsp = NULL;
2020 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
2022 static struct tevent_req *vfswrap_offload_write_send(
2023 struct vfs_handle_struct *handle,
2024 TALLOC_CTX *mem_ctx,
2025 struct tevent_context *ev,
2028 off_t transfer_offset,
2029 struct files_struct *dest_fsp,
2033 struct tevent_req *req;
2034 struct vfswrap_offload_write_state *state = NULL;
2035 /* off_t is signed! */
2036 off_t max_offset = INT64_MAX - to_copy;
2037 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
2038 files_struct *src_fsp = NULL;
2042 req = tevent_req_create(mem_ctx, &state,
2043 struct vfswrap_offload_write_state);
2048 *state = (struct vfswrap_offload_write_state) {
2050 .src_off = transfer_offset,
2052 .dst_fsp = dest_fsp,
2053 .dst_off = dest_off,
2055 .remaining = to_copy,
2058 tevent_req_set_cleanup_fn(req, vfswrap_offload_write_cleanup);
2061 case FSCTL_SRV_COPYCHUNK:
2062 case FSCTL_SRV_COPYCHUNK_WRITE:
2065 case FSCTL_OFFLOAD_WRITE:
2066 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
2067 return tevent_req_post(req, ev);
2069 case FSCTL_DUP_EXTENTS_TO_FILE:
2070 DBG_DEBUG("COW clones not supported by vfs_default\n");
2071 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2072 return tevent_req_post(req, ev);
2075 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2076 return tevent_req_post(req, ev);
2080 * From here on we assume a copy-chunk fsctl
2084 tevent_req_done(req);
2085 return tevent_req_post(req, ev);
2088 if (state->src_off > max_offset) {
2090 * Protect integer checks below.
2092 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2093 return tevent_req_post(req, ev);
2095 if (state->src_off < 0) {
2097 * Protect integer checks below.
2099 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2100 return tevent_req_post(req, ev);
2102 if (state->dst_off > max_offset) {
2104 * Protect integer checks below.
2106 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2107 return tevent_req_post(req, ev);
2109 if (state->dst_off < 0) {
2111 * Protect integer checks below.
2113 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2114 return tevent_req_post(req, ev);
2117 status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
2119 if (tevent_req_nterror(req, status)) {
2120 return tevent_req_post(req, ev);
2123 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
2125 status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
2126 if (!NT_STATUS_IS_OK(status)) {
2127 tevent_req_nterror(req, status);
2128 return tevent_req_post(req, ev);
2131 ok = change_to_user_and_service_by_fsp(src_fsp);
2133 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2134 return tevent_req_post(req, ev);
2137 state->src_ev = src_fsp->conn->sconn->ev_ctx;
2138 state->src_fsp = src_fsp;
2140 status = vfs_stat_fsp(src_fsp);
2141 if (tevent_req_nterror(req, status)) {
2142 return tevent_req_post(req, ev);
2145 if (src_fsp->fsp_name->st.st_ex_size < state->src_off + to_copy) {
2147 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
2148 * If the SourceOffset or SourceOffset + Length extends beyond
2149 * the end of file, the server SHOULD<240> treat this as a
2150 * STATUS_END_OF_FILE error.
2152 * <240> Section 3.3.5.15.6: Windows servers will return
2153 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
2155 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
2156 return tevent_req_post(req, ev);
2159 state->buf = talloc_array(state, uint8_t, num);
2160 if (tevent_req_nomem(state->buf, req)) {
2161 return tevent_req_post(req, ev);
2164 status = vfswrap_offload_write_loop(req);
2165 if (!NT_STATUS_IS_OK(status)) {
2166 tevent_req_nterror(req, status);
2167 return tevent_req_post(req, ev);
2173 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
2175 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
2177 struct vfswrap_offload_write_state *state = tevent_req_data(
2178 req, struct vfswrap_offload_write_state);
2179 struct tevent_req *subreq = NULL;
2180 struct lock_struct read_lck;
2184 * This is called under the context of state->src_fsp.
2187 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
2189 init_strict_lock_struct(state->src_fsp,
2190 state->src_fsp->op->global->open_persistent_id,
2192 state->next_io_size,
2196 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
2200 return NT_STATUS_FILE_LOCK_CONFLICT;
2203 subreq = SMB_VFS_PREAD_SEND(state,
2207 state->next_io_size,
2209 if (subreq == NULL) {
2210 return NT_STATUS_NO_MEMORY;
2212 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
2214 return NT_STATUS_OK;
2217 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
2219 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
2221 struct tevent_req *req = tevent_req_callback_data(
2222 subreq, struct tevent_req);
2223 struct vfswrap_offload_write_state *state = tevent_req_data(
2224 req, struct vfswrap_offload_write_state);
2225 struct vfs_aio_state aio_state;
2226 struct lock_struct write_lck;
2230 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
2231 TALLOC_FREE(subreq);
2233 DBG_ERR("read failed: %s\n", strerror(aio_state.error));
2234 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2237 if (nread != state->next_io_size) {
2238 DBG_ERR("Short read, only %zd of %zu\n",
2239 nread, state->next_io_size);
2240 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2244 state->src_off += nread;
2246 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2248 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2252 init_strict_lock_struct(state->dst_fsp,
2253 state->dst_fsp->op->global->open_persistent_id,
2255 state->next_io_size,
2259 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
2263 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
2267 subreq = SMB_VFS_PWRITE_SEND(state,
2271 state->next_io_size,
2273 if (subreq == NULL) {
2274 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2277 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
2280 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
2282 struct tevent_req *req = tevent_req_callback_data(
2283 subreq, struct tevent_req);
2284 struct vfswrap_offload_write_state *state = tevent_req_data(
2285 req, struct vfswrap_offload_write_state);
2286 struct vfs_aio_state aio_state;
2291 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
2292 TALLOC_FREE(subreq);
2293 if (nwritten == -1) {
2294 DBG_ERR("write failed: %s\n", strerror(aio_state.error));
2295 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2298 if (nwritten != state->next_io_size) {
2299 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
2300 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2304 state->dst_off += nwritten;
2306 if (state->remaining < nwritten) {
2307 /* Paranoia check */
2308 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2311 state->remaining -= nwritten;
2312 if (state->remaining == 0) {
2313 tevent_req_done(req);
2317 ok = change_to_user_and_service_by_fsp(state->src_fsp);
2319 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2323 status = vfswrap_offload_write_loop(req);
2324 if (!NT_STATUS_IS_OK(status)) {
2325 tevent_req_nterror(req, status);
2332 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
2333 struct tevent_req *req,
2336 struct vfswrap_offload_write_state *state = tevent_req_data(
2337 req, struct vfswrap_offload_write_state);
2340 if (tevent_req_is_nterror(req, &status)) {
2341 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
2343 tevent_req_received(req);
2347 *copied = state->to_copy;
2348 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
2349 tevent_req_received(req);
2351 return NT_STATUS_OK;
2354 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
2355 TALLOC_CTX *mem_ctx,
2356 struct files_struct *fsp,
2357 struct smb_filename *smb_fname,
2358 uint16_t *_compression_fmt)
2360 return NT_STATUS_INVALID_DEVICE_REQUEST;
2363 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
2364 TALLOC_CTX *mem_ctx,
2365 struct files_struct *fsp,
2366 uint16_t compression_fmt)
2368 return NT_STATUS_INVALID_DEVICE_REQUEST;
2371 /********************************************************************
2372 Given a stat buffer return the allocated size on disk, taking into
2373 account sparse files.
2374 ********************************************************************/
2375 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
2376 struct files_struct *fsp,
2377 const SMB_STRUCT_STAT *sbuf)
2381 START_PROFILE(syscall_get_alloc_size);
2383 if(S_ISDIR(sbuf->st_ex_mode)) {
2388 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2389 /* The type of st_blocksize is blkcnt_t which *MUST* be
2390 signed (according to POSIX) and can be less than 64-bits.
2391 Ensure when we're converting to 64 bits wide we don't
2393 #if defined(SIZEOF_BLKCNT_T_8)
2394 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2395 #elif defined(SIZEOF_BLKCNT_T_4)
2397 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2398 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2401 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2405 * Some file systems do not allocate a block for very
2406 * small files. But for non-empty file should report a
2410 uint64_t filesize = get_file_size_stat(sbuf);
2412 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2416 result = get_file_size_stat(sbuf);
2419 if (fsp && fsp->initial_allocation_size)
2420 result = MAX(result,fsp->initial_allocation_size);
2422 result = smb_roundup(handle->conn, result);
2425 END_PROFILE(syscall_get_alloc_size);
2429 static int vfswrap_unlinkat(vfs_handle_struct *handle,
2430 struct files_struct *dirfsp,
2431 const struct smb_filename *smb_fname,
2436 START_PROFILE(syscall_unlinkat);
2438 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2440 if (is_named_stream(smb_fname)) {
2444 result = unlinkat(dirfsp->fh->fd,
2445 smb_fname->base_name,
2449 END_PROFILE(syscall_unlinkat);
2453 static int vfswrap_chmod(vfs_handle_struct *handle,
2454 const struct smb_filename *smb_fname,
2459 START_PROFILE(syscall_chmod);
2460 result = chmod(smb_fname->base_name, mode);
2461 END_PROFILE(syscall_chmod);
2465 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2469 START_PROFILE(syscall_fchmod);
2470 #if defined(HAVE_FCHMOD)
2471 result = fchmod(fsp->fh->fd, mode);
2477 END_PROFILE(syscall_fchmod);
2481 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2486 START_PROFILE(syscall_fchown);
2487 result = fchown(fsp->fh->fd, uid, gid);
2488 END_PROFILE(syscall_fchown);
2496 static int vfswrap_lchown(vfs_handle_struct *handle,
2497 const struct smb_filename *smb_fname,
2503 START_PROFILE(syscall_lchown);
2504 result = lchown(smb_fname->base_name, uid, gid);
2505 END_PROFILE(syscall_lchown);
2509 static int vfswrap_chdir(vfs_handle_struct *handle,
2510 const struct smb_filename *smb_fname)
2514 START_PROFILE(syscall_chdir);
2515 result = chdir(smb_fname->base_name);
2516 END_PROFILE(syscall_chdir);
2520 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2524 struct smb_filename *smb_fname = NULL;
2526 START_PROFILE(syscall_getwd);
2527 result = sys_getwd();
2528 END_PROFILE(syscall_getwd);
2530 if (result == NULL) {
2533 smb_fname = synthetic_smb_fname(ctx,
2539 * sys_getwd() *always* returns malloced memory.
2540 * We must free here to avoid leaks:
2541 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2547 /*********************************************************************
2548 nsec timestamp resolution call. Convert down to whatever the underlying
2549 system will support.
2550 **********************************************************************/
2552 static int vfswrap_ntimes(vfs_handle_struct *handle,
2553 const struct smb_filename *smb_fname,
2554 struct smb_file_time *ft)
2558 START_PROFILE(syscall_ntimes);
2560 if (is_named_stream(smb_fname)) {
2566 if (is_omit_timespec(&ft->atime)) {
2567 ft->atime= smb_fname->st.st_ex_atime;
2570 if (is_omit_timespec(&ft->mtime)) {
2571 ft->mtime = smb_fname->st.st_ex_mtime;
2574 if (!is_omit_timespec(&ft->create_time)) {
2575 set_create_timespec_ea(handle->conn,
2580 if ((timespec_compare(&ft->atime,
2581 &smb_fname->st.st_ex_atime) == 0) &&
2582 (timespec_compare(&ft->mtime,
2583 &smb_fname->st.st_ex_mtime) == 0)) {
2588 #if defined(HAVE_UTIMENSAT)
2590 struct timespec ts[2];
2593 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2595 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2597 if (!((result == -1) && (errno == ENOSYS))) {
2601 #if defined(HAVE_UTIMES)
2603 struct timeval tv[2];
2604 tv[0] = convert_timespec_to_timeval(ft->atime);
2605 tv[1] = convert_timespec_to_timeval(ft->mtime);
2606 result = utimes(smb_fname->base_name, tv);
2608 result = utimes(smb_fname->base_name, NULL);
2610 if (!((result == -1) && (errno == ENOSYS))) {
2614 #if defined(HAVE_UTIME)
2616 struct utimbuf times;
2617 times.actime = convert_timespec_to_time_t(ft->atime);
2618 times.modtime = convert_timespec_to_time_t(ft->mtime);
2619 result = utime(smb_fname->base_name, ×);
2621 result = utime(smb_fname->base_name, NULL);
2623 if (!((result == -1) && (errno == ENOSYS))) {
2631 END_PROFILE(syscall_ntimes);
2635 /*********************************************************************
2636 A version of ftruncate that will write the space on disk if strict
2638 **********************************************************************/
2640 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2642 off_t space_to_write;
2643 uint64_t space_avail;
2644 uint64_t bsize,dfree,dsize;
2647 SMB_STRUCT_STAT *pst;
2649 status = vfs_stat_fsp(fsp);
2650 if (!NT_STATUS_IS_OK(status)) {
2653 pst = &fsp->fsp_name->st;
2656 if (S_ISFIFO(pst->st_ex_mode))
2660 if (pst->st_ex_size == len)
2663 /* Shrink - just ftruncate. */
2664 if (pst->st_ex_size > len)
2665 return ftruncate(fsp->fh->fd, len);
2667 space_to_write = len - pst->st_ex_size;
2669 /* for allocation try fallocate first. This can fail on some
2670 platforms e.g. when the filesystem doesn't support it and no
2671 emulation is being done by the libc (like on AIX with JFS1). In that
2672 case we do our own emulation. fallocate implementations can
2673 return ENOTSUP or EINVAL in cases like that. */
2674 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2675 if (ret == -1 && errno == ENOSPC) {
2681 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2682 "error %d. Falling back to slow manual allocation\n", errno));
2684 /* available disk space is enough or not? */
2686 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2687 /* space_avail is 1k blocks */
2688 if (space_avail == (uint64_t)-1 ||
2689 ((uint64_t)space_to_write/1024 > space_avail) ) {
2694 /* Write out the real space on disk. */
2695 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2703 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2706 SMB_STRUCT_STAT *pst;
2710 START_PROFILE(syscall_ftruncate);
2712 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2713 result = strict_allocate_ftruncate(handle, fsp, len);
2714 END_PROFILE(syscall_ftruncate);
2718 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2719 ftruncate if the system supports it. Then I discovered that
2720 you can have some filesystems that support ftruncate
2721 expansion and some that don't! On Linux fat can't do
2722 ftruncate extend but ext2 can. */
2724 result = ftruncate(fsp->fh->fd, len);
2726 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2727 extend a file with ftruncate. Provide alternate implementation
2730 /* Do an fstat to see if the file is longer than the requested
2731 size in which case the ftruncate above should have
2732 succeeded or shorter, in which case seek to len - 1 and
2733 write 1 byte of zero */
2734 status = vfs_stat_fsp(fsp);
2735 if (!NT_STATUS_IS_OK(status)) {
2739 /* We need to update the files_struct after successful ftruncate */
2744 pst = &fsp->fsp_name->st;
2747 if (S_ISFIFO(pst->st_ex_mode)) {
2753 if (pst->st_ex_size == len) {
2758 if (pst->st_ex_size > len) {
2759 /* the ftruncate should have worked */
2763 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2771 END_PROFILE(syscall_ftruncate);
2775 static int vfswrap_fallocate(vfs_handle_struct *handle,
2783 START_PROFILE(syscall_fallocate);
2785 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2787 * posix_fallocate returns 0 on success, errno on error
2788 * and doesn't set errno. Make it behave like fallocate()
2789 * which returns -1, and sets errno on failure.
2796 /* sys_fallocate handles filtering of unsupported mode flags */
2797 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2799 END_PROFILE(syscall_fallocate);
2803 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2807 START_PROFILE(syscall_fcntl_lock);
2809 if (fsp->use_ofd_locks) {
2810 op = map_process_lock_to_ofd_lock(op);
2813 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2814 END_PROFILE(syscall_fcntl_lock);
2818 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2819 uint32_t share_access, uint32_t access_mask)
2821 START_PROFILE(syscall_kernel_flock);
2822 kernel_flock(fsp->fh->fd, share_access, access_mask);
2823 END_PROFILE(syscall_kernel_flock);
2827 static int vfswrap_fcntl(vfs_handle_struct *handle, files_struct *fsp, int cmd,
2831 va_list dup_cmd_arg;
2835 START_PROFILE(syscall_fcntl);
2837 va_copy(dup_cmd_arg, cmd_arg);
2843 #if defined(HAVE_OFD_LOCKS)
2848 #if defined(HAVE_F_OWNER_EX)
2852 #if defined(HAVE_RW_HINTS)
2855 case F_GET_FILE_RW_HINT:
2856 case F_SET_FILE_RW_HINT:
2858 argp = va_arg(dup_cmd_arg, void *);
2859 result = sys_fcntl_ptr(fsp->fh->fd, cmd, argp);
2862 val = va_arg(dup_cmd_arg, int);
2863 result = sys_fcntl_int(fsp->fh->fd, cmd, val);
2866 va_end(dup_cmd_arg);
2868 END_PROFILE(syscall_fcntl);
2872 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2877 START_PROFILE(syscall_fcntl_getlock);
2879 if (fsp->use_ofd_locks) {
2880 op = map_process_lock_to_ofd_lock(op);
2883 result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2884 END_PROFILE(syscall_fcntl_getlock);
2888 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2893 START_PROFILE(syscall_linux_setlease);
2895 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2896 result = linux_setlease(fsp->fh->fd, leasetype);
2900 END_PROFILE(syscall_linux_setlease);
2904 static int vfswrap_symlinkat(vfs_handle_struct *handle,
2905 const char *link_target,
2906 struct files_struct *dirfsp,
2907 const struct smb_filename *new_smb_fname)
2911 START_PROFILE(syscall_symlinkat);
2913 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2915 result = symlinkat(link_target,
2917 new_smb_fname->base_name);
2918 END_PROFILE(syscall_symlinkat);
2922 static int vfswrap_readlinkat(vfs_handle_struct *handle,
2923 files_struct *dirfsp,
2924 const struct smb_filename *smb_fname,
2930 START_PROFILE(syscall_readlinkat);
2932 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2934 result = readlinkat(dirfsp->fh->fd,
2935 smb_fname->base_name,
2939 END_PROFILE(syscall_readlinkat);
2943 static int vfswrap_linkat(vfs_handle_struct *handle,
2944 files_struct *srcfsp,
2945 const struct smb_filename *old_smb_fname,
2946 files_struct *dstfsp,
2947 const struct smb_filename *new_smb_fname,
2952 START_PROFILE(syscall_linkat);
2954 SMB_ASSERT(srcfsp == srcfsp->conn->cwd_fsp);
2955 SMB_ASSERT(dstfsp == dstfsp->conn->cwd_fsp);
2957 result = linkat(srcfsp->fh->fd,
2958 old_smb_fname->base_name,
2960 new_smb_fname->base_name,
2963 END_PROFILE(syscall_linkat);
2967 static int vfswrap_mknodat(vfs_handle_struct *handle,
2968 files_struct *dirfsp,
2969 const struct smb_filename *smb_fname,
2975 START_PROFILE(syscall_mknodat);
2977 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2979 result = sys_mknodat(dirfsp->fh->fd,
2980 smb_fname->base_name,
2984 END_PROFILE(syscall_mknodat);
2988 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2990 const struct smb_filename *smb_fname)
2993 struct smb_filename *result_fname = NULL;
2995 START_PROFILE(syscall_realpath);
2996 result = sys_realpath(smb_fname->base_name);
2997 END_PROFILE(syscall_realpath);
2999 result_fname = synthetic_smb_fname(ctx, result, NULL, NULL, 0);
3002 return result_fname;
3005 static int vfswrap_chflags(vfs_handle_struct *handle,
3006 const struct smb_filename *smb_fname,
3010 return chflags(smb_fname->base_name, flags);
3017 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
3018 const SMB_STRUCT_STAT *sbuf)
3022 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
3026 key.devid = sbuf->st_ex_dev;
3027 key.inode = sbuf->st_ex_ino;
3028 /* key.extid is unused by default. */
3033 static uint64_t vfswrap_fs_file_id(struct vfs_handle_struct *handle,
3034 const SMB_STRUCT_STAT *psbuf)
3038 if (!(psbuf->st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)) {
3039 return psbuf->st_ex_file_id;
3042 if (handle->conn->base_share_dev == psbuf->st_ex_dev) {
3043 return (uint64_t)psbuf->st_ex_ino;
3047 file_id = ((psbuf->st_ex_ino) & UINT32_MAX);
3050 file_id |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32;
3055 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
3056 struct files_struct *fsp,
3057 const struct smb_filename *smb_fname,
3058 TALLOC_CTX *mem_ctx,
3059 unsigned int *pnum_streams,
3060 struct stream_struct **pstreams)
3062 SMB_STRUCT_STAT sbuf;
3063 struct stream_struct *tmp_streams = NULL;
3066 if ((fsp != NULL) && (fsp->is_directory)) {
3068 * No default streams on directories
3073 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
3074 ret = SMB_VFS_FSTAT(fsp, &sbuf);
3077 struct smb_filename smb_fname_cp;
3079 ZERO_STRUCT(smb_fname_cp);
3080 smb_fname_cp.base_name = discard_const_p(char,
3081 smb_fname->base_name);
3082 smb_fname_cp.flags = smb_fname->flags;
3084 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
3085 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
3087 ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
3089 sbuf = smb_fname_cp.st;
3093 return map_nt_error_from_unix(errno);
3096 if (S_ISDIR(sbuf.st_ex_mode)) {
3100 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
3101 (*pnum_streams) + 1);
3102 if (tmp_streams == NULL) {
3103 return NT_STATUS_NO_MEMORY;
3105 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
3106 if (tmp_streams[*pnum_streams].name == NULL) {
3107 return NT_STATUS_NO_MEMORY;
3109 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
3110 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
3113 *pstreams = tmp_streams;
3115 return NT_STATUS_OK;
3118 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
3121 TALLOC_CTX *mem_ctx,
3125 * Don't fall back to get_real_filename so callers can differentiate
3126 * between a full directory scan and an actual case-insensitive stat.
3132 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
3133 const struct smb_filename *smb_fname)
3135 return handle->conn->connectpath;
3138 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
3139 struct byte_range_lock *br_lck,
3140 struct lock_struct *plock)
3142 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3144 /* Note: blr is not used in the default implementation. */
3145 return brl_lock_windows_default(br_lck, plock);
3148 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
3149 struct byte_range_lock *br_lck,
3150 const struct lock_struct *plock)
3152 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3154 return brl_unlock_windows_default(br_lck, plock);
3157 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
3159 struct lock_struct *plock)
3161 SMB_ASSERT(plock->lock_type == READ_LOCK ||
3162 plock->lock_type == WRITE_LOCK);
3164 return strict_lock_check_default(fsp, plock);
3167 /* NT ACL operations. */
3169 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
3171 uint32_t security_info,
3172 TALLOC_CTX *mem_ctx,
3173 struct security_descriptor **ppdesc)
3177 START_PROFILE(fget_nt_acl);
3178 result = posix_fget_nt_acl(fsp, security_info,
3180 END_PROFILE(fget_nt_acl);
3184 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
3185 const struct smb_filename *smb_fname,
3186 uint32_t security_info,
3187 TALLOC_CTX *mem_ctx,
3188 struct security_descriptor **ppdesc)
3192 START_PROFILE(get_nt_acl);
3193 result = posix_get_nt_acl(handle->conn,
3198 END_PROFILE(get_nt_acl);
3202 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
3206 START_PROFILE(fset_nt_acl);
3207 result = set_nt_acl(fsp, security_info_sent, psd);
3208 END_PROFILE(fset_nt_acl);
3212 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
3213 struct smb_filename *file,
3214 struct security_acl *sacl,
3215 uint32_t access_requested,
3216 uint32_t access_denied)
3218 return NT_STATUS_OK; /* Nothing to do here ... */
3221 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
3222 const struct smb_filename *smb_fname,
3223 SMB_ACL_TYPE_T type,
3224 TALLOC_CTX *mem_ctx)
3226 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
3229 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
3231 TALLOC_CTX *mem_ctx)
3233 return sys_acl_get_fd(handle, fsp, mem_ctx);
3236 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
3237 const struct smb_filename *smb_fname,
3238 SMB_ACL_TYPE_T acltype,
3241 return sys_acl_set_file(handle, smb_fname, acltype, theacl);
3244 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
3246 return sys_acl_set_fd(handle, fsp, theacl);
3249 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
3250 const struct smb_filename *smb_fname)
3252 return sys_acl_delete_def_file(handle, smb_fname);
3255 /****************************************************************
3256 Extended attribute operations.
3257 *****************************************************************/
3259 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
3260 const struct smb_filename *smb_fname,
3265 return getxattr(smb_fname->base_name, name, value, size);
3268 struct vfswrap_getxattrat_state {
3269 struct tevent_context *ev;
3270 files_struct *dir_fsp;
3271 const struct smb_filename *smb_fname;
3272 struct tevent_req *req;
3275 * The following variables are talloced off "state" which is protected
3276 * by a destructor and thus are guaranteed to be safe to be used in the
3277 * job function in the worker thread.
3280 const char *xattr_name;
3281 uint8_t *xattr_value;
3282 struct security_unix_token *token;
3285 struct vfs_aio_state vfs_aio_state;
3286 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
3289 static int vfswrap_getxattrat_state_destructor(
3290 struct vfswrap_getxattrat_state *state)
3293 * This destructor only gets called if the request is still
3294 * in flight, which is why we deny it by returning -1. We
3295 * also set the req pointer to NULL so the _done function
3296 * can detect the caller doesn't want the result anymore.
3298 * Forcing the fsp closed by a SHUTDOWN_CLOSE can cause this.
3304 static void vfswrap_getxattrat_do_sync(struct tevent_req *req);
3305 static void vfswrap_getxattrat_do_async(void *private_data);
3306 static void vfswrap_getxattrat_done(struct tevent_req *subreq);
3308 static struct tevent_req *vfswrap_getxattrat_send(
3309 TALLOC_CTX *mem_ctx,
3310 struct tevent_context *ev,
3311 struct vfs_handle_struct *handle,
3312 files_struct *dir_fsp,
3313 const struct smb_filename *smb_fname,
3314 const char *xattr_name,
3317 struct tevent_req *req = NULL;
3318 struct tevent_req *subreq = NULL;
3319 struct vfswrap_getxattrat_state *state = NULL;
3320 size_t max_threads = 0;
3321 bool have_per_thread_cwd = false;
3322 bool have_per_thread_creds = false;
3323 bool do_async = false;
3325 req = tevent_req_create(mem_ctx, &state,
3326 struct vfswrap_getxattrat_state);
3330 *state = (struct vfswrap_getxattrat_state) {
3333 .smb_fname = smb_fname,
3337 max_threads = pthreadpool_tevent_max_threads(dir_fsp->conn->sconn->pool);
3338 if (max_threads >= 1) {
3340 * We need a non sync threadpool!
3342 have_per_thread_cwd = per_thread_cwd_supported();
3344 #ifdef HAVE_LINUX_THREAD_CREDENTIALS
3345 have_per_thread_creds = true;
3347 if (have_per_thread_cwd && have_per_thread_creds) {
3351 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat, profile_p,
3352 state->profile_bytes, 0);
3354 if (dir_fsp->fh->fd == -1) {
3355 DBG_ERR("Need a valid directory fd\n");
3356 tevent_req_error(req, EINVAL);
3357 return tevent_req_post(req, ev);
3360 if (alloc_hint > 0) {
3361 state->xattr_value = talloc_zero_array(state,
3364 if (tevent_req_nomem(state->xattr_value, req)) {
3365 return tevent_req_post(req, ev);
3370 vfswrap_getxattrat_do_sync(req);
3371 return tevent_req_post(req, ev);
3375 * Now allocate all parameters from a memory context that won't go away
3376 * no matter what. These paremeters will get used in threads and we
3377 * can't reliably cancel threads, so all buffers passed to the threads
3378 * must not be freed before all referencing threads terminate.
3381 state->name = talloc_strdup(state, smb_fname->base_name);
3382 if (tevent_req_nomem(state->name, req)) {
3383 return tevent_req_post(req, ev);
3386 state->xattr_name = talloc_strdup(state, xattr_name);
3387 if (tevent_req_nomem(state->xattr_name, req)) {
3388 return tevent_req_post(req, ev);
3392 * This is a hot codepath so at first glance one might think we should
3393 * somehow optimize away the token allocation and do a
3394 * talloc_reference() or similar black magic instead. But due to the
3395 * talloc_stackframe pool per SMB2 request this should be a simple copy
3396 * without a malloc in most cases.
3398 if (geteuid() == sec_initial_uid()) {
3399 state->token = root_unix_token(state);
3401 state->token = copy_unix_token(
3403 dir_fsp->conn->session_info->unix_token);
3405 if (tevent_req_nomem(state->token, req)) {
3406 return tevent_req_post(req, ev);
3409 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3411 subreq = pthreadpool_tevent_job_send(
3414 dir_fsp->conn->sconn->pool,
3415 vfswrap_getxattrat_do_async,
3417 if (tevent_req_nomem(subreq, req)) {
3418 return tevent_req_post(req, ev);
3420 tevent_req_set_callback(subreq, vfswrap_getxattrat_done, state);
3422 talloc_set_destructor(state, vfswrap_getxattrat_state_destructor);
3427 static void vfswrap_getxattrat_do_sync(struct tevent_req *req)
3429 struct vfswrap_getxattrat_state *state = tevent_req_data(
3430 req, struct vfswrap_getxattrat_state);
3432 char *tofree = NULL;
3433 char pathbuf[PATH_MAX+1];
3437 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
3438 state->smb_fname->base_name,
3443 if (pathlen == -1) {
3444 tevent_req_error(req, ENOMEM);
3448 state->xattr_size = getxattr(path,
3451 talloc_array_length(state->xattr_value));
3453 TALLOC_FREE(tofree);
3454 if (state->xattr_size == -1) {
3455 tevent_req_error(req, err);
3459 tevent_req_done(req);
3463 static void vfswrap_getxattrat_do_async(void *private_data)
3465 struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3466 private_data, struct vfswrap_getxattrat_state);
3467 struct timespec start_time;
3468 struct timespec end_time;
3471 PROFILE_TIMESTAMP(&start_time);
3472 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
3475 * Here we simulate a getxattrat()
3476 * call using fchdir();getxattr()
3479 per_thread_cwd_activate();
3481 /* Become the correct credential on this thread. */
3482 ret = set_thread_credentials(state->token->uid,
3484 (size_t)state->token->ngroups,
3485 state->token->groups);
3487 state->xattr_size = -1;
3488 state->vfs_aio_state.error = errno;
3492 ret = fchdir(state->dir_fsp->fh->fd);
3494 state->xattr_size = -1;
3495 state->vfs_aio_state.error = errno;
3499 state->xattr_size = getxattr(state->name,
3502 talloc_array_length(state->xattr_value));
3503 if (state->xattr_size == -1) {
3504 state->vfs_aio_state.error = errno;
3508 PROFILE_TIMESTAMP(&end_time);
3509 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
3510 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3513 static void vfswrap_getxattrat_done(struct tevent_req *subreq)
3515 struct vfswrap_getxattrat_state *state = tevent_req_callback_data(
3516 subreq, struct vfswrap_getxattrat_state);
3517 struct tevent_req *req = state->req;
3522 * Make sure we run as the user again
3524 ok = change_to_user_and_service_by_fsp(state->dir_fsp);
3527 ret = pthreadpool_tevent_job_recv(subreq);
3528 TALLOC_FREE(subreq);
3529 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
3530 talloc_set_destructor(state, NULL);
3533 * We were shutdown closed in flight. No one wants the result,
3534 * and state has been reparented to the NULL context, so just
3535 * free it so we don't leak memory.
3537 DBG_NOTICE("getxattr request abandoned in flight\n");
3542 if (ret != EAGAIN) {
3543 tevent_req_error(req, ret);
3547 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
3548 * means the lower level pthreadpool failed to create a new
3549 * thread. Fallback to sync processing in that case to allow
3550 * some progress for the client.
3552 vfswrap_getxattrat_do_sync(req);
3556 if (state->xattr_size == -1) {
3557 tevent_req_error(req, state->vfs_aio_state.error);
3561 if (state->xattr_value == NULL) {
3563 * The caller only wanted the size.
3565 tevent_req_done(req);
3570 * shrink the buffer to the returned size.
3571 * (can't fail). It means NULL if size is 0.
3573 state->xattr_value = talloc_realloc(state,
3578 tevent_req_done(req);
3581 static ssize_t vfswrap_getxattrat_recv(struct tevent_req *req,
3582 struct vfs_aio_state *aio_state,
3583 TALLOC_CTX *mem_ctx,
3584 uint8_t **xattr_value)
3586 struct vfswrap_getxattrat_state *state = tevent_req_data(
3587 req, struct vfswrap_getxattrat_state);
3590 if (tevent_req_is_unix_error(req, &aio_state->error)) {
3591 tevent_req_received(req);
3595 *aio_state = state->vfs_aio_state;
3596 xattr_size = state->xattr_size;
3597 if (xattr_value != NULL) {
3598 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
3601 tevent_req_received(req);
3605 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
3607 return fgetxattr(fsp->fh->fd, name, value, size);
3610 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
3611 const struct smb_filename *smb_fname,
3615 return listxattr(smb_fname->base_name, list, size);
3618 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
3620 return flistxattr(fsp->fh->fd, list, size);
3623 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
3624 const struct smb_filename *smb_fname,
3627 return removexattr(smb_fname->base_name, name);
3630 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
3632 return fremovexattr(fsp->fh->fd, name);
3635 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
3636 const struct smb_filename *smb_fname,
3642 return setxattr(smb_fname->base_name, name, value, size, flags);
3645 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
3647 return fsetxattr(fsp->fh->fd, name, value, size, flags);
3650 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
3655 static bool vfswrap_is_offline(struct connection_struct *conn,
3656 const struct smb_filename *fname)
3660 bool offline = false;
3662 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
3666 if (!lp_dmapi_support(SNUM(conn)) || !dmapi_have_session()) {
3667 #if defined(ENOTSUP)
3673 status = get_full_smb_filename(talloc_tos(), fname, &path);
3674 if (!NT_STATUS_IS_OK(status)) {
3675 errno = map_errno_from_nt_status(status);
3679 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
3686 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
3687 struct files_struct *fsp,
3688 TALLOC_CTX *mem_ctx,
3691 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
3694 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
3695 struct files_struct *fsp,
3696 const DATA_BLOB old_cookie,
3697 TALLOC_CTX *mem_ctx,
3698 DATA_BLOB *new_cookie)
3700 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
3704 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
3705 struct smb_request *smb1req,
3706 struct smbXsrv_open *op,
3707 const DATA_BLOB old_cookie,
3708 TALLOC_CTX *mem_ctx,
3709 struct files_struct **fsp,
3710 DATA_BLOB *new_cookie)
3712 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
3713 old_cookie, mem_ctx,
3717 static struct vfs_fn_pointers vfs_default_fns = {
3718 /* Disk operations */
3720 .connect_fn = vfswrap_connect,
3721 .disconnect_fn = vfswrap_disconnect,
3722 .disk_free_fn = vfswrap_disk_free,
3723 .get_quota_fn = vfswrap_get_quota,
3724 .set_quota_fn = vfswrap_set_quota,
3725 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3726 .statvfs_fn = vfswrap_statvfs,
3727 .fs_capabilities_fn = vfswrap_fs_capabilities,
3728 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3729 .create_dfs_pathat_fn = vfswrap_create_dfs_pathat,
3730 .read_dfs_pathat_fn = vfswrap_read_dfs_pathat,
3731 .snap_check_path_fn = vfswrap_snap_check_path,
3732 .snap_create_fn = vfswrap_snap_create,
3733 .snap_delete_fn = vfswrap_snap_delete,
3735 /* Directory operations */
3737 .opendir_fn = vfswrap_opendir,
3738 .fdopendir_fn = vfswrap_fdopendir,
3739 .readdir_fn = vfswrap_readdir,
3740 .readdir_attr_fn = vfswrap_readdir_attr,
3741 .seekdir_fn = vfswrap_seekdir,
3742 .telldir_fn = vfswrap_telldir,
3743 .rewind_dir_fn = vfswrap_rewinddir,
3744 .mkdirat_fn = vfswrap_mkdirat,
3745 .closedir_fn = vfswrap_closedir,
3747 /* File operations */
3749 .open_fn = vfswrap_open,
3750 .create_file_fn = vfswrap_create_file,
3751 .close_fn = vfswrap_close,
3752 .pread_fn = vfswrap_pread,
3753 .pread_send_fn = vfswrap_pread_send,
3754 .pread_recv_fn = vfswrap_pread_recv,
3755 .pwrite_fn = vfswrap_pwrite,
3756 .pwrite_send_fn = vfswrap_pwrite_send,
3757 .pwrite_recv_fn = vfswrap_pwrite_recv,
3758 .lseek_fn = vfswrap_lseek,
3759 .sendfile_fn = vfswrap_sendfile,
3760 .recvfile_fn = vfswrap_recvfile,
3761 .renameat_fn = vfswrap_renameat,
3762 .fsync_send_fn = vfswrap_fsync_send,
3763 .fsync_recv_fn = vfswrap_fsync_recv,
3764 .stat_fn = vfswrap_stat,
3765 .fstat_fn = vfswrap_fstat,
3766 .lstat_fn = vfswrap_lstat,
3767 .get_alloc_size_fn = vfswrap_get_alloc_size,
3768 .unlinkat_fn = vfswrap_unlinkat,
3769 .chmod_fn = vfswrap_chmod,
3770 .fchmod_fn = vfswrap_fchmod,
3771 .fchown_fn = vfswrap_fchown,
3772 .lchown_fn = vfswrap_lchown,
3773 .chdir_fn = vfswrap_chdir,
3774 .getwd_fn = vfswrap_getwd,
3775 .ntimes_fn = vfswrap_ntimes,
3776 .ftruncate_fn = vfswrap_ftruncate,
3777 .fallocate_fn = vfswrap_fallocate,
3778 .lock_fn = vfswrap_lock,
3779 .kernel_flock_fn = vfswrap_kernel_flock,
3780 .fcntl_fn = vfswrap_fcntl,
3781 .linux_setlease_fn = vfswrap_linux_setlease,
3782 .getlock_fn = vfswrap_getlock,
3783 .symlinkat_fn = vfswrap_symlinkat,
3784 .readlinkat_fn = vfswrap_readlinkat,
3785 .linkat_fn = vfswrap_linkat,
3786 .mknodat_fn = vfswrap_mknodat,
3787 .realpath_fn = vfswrap_realpath,
3788 .chflags_fn = vfswrap_chflags,
3789 .file_id_create_fn = vfswrap_file_id_create,
3790 .fs_file_id_fn = vfswrap_fs_file_id,
3791 .streaminfo_fn = vfswrap_streaminfo,
3792 .get_real_filename_fn = vfswrap_get_real_filename,
3793 .connectpath_fn = vfswrap_connectpath,
3794 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
3795 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3796 .strict_lock_check_fn = vfswrap_strict_lock_check,
3797 .translate_name_fn = vfswrap_translate_name,
3798 .fsctl_fn = vfswrap_fsctl,
3799 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
3800 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
3801 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
3802 .get_dos_attributes_send_fn = vfswrap_get_dos_attributes_send,
3803 .get_dos_attributes_recv_fn = vfswrap_get_dos_attributes_recv,
3804 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
3805 .offload_read_send_fn = vfswrap_offload_read_send,
3806 .offload_read_recv_fn = vfswrap_offload_read_recv,
3807 .offload_write_send_fn = vfswrap_offload_write_send,
3808 .offload_write_recv_fn = vfswrap_offload_write_recv,
3809 .get_compression_fn = vfswrap_get_compression,
3810 .set_compression_fn = vfswrap_set_compression,
3812 /* NT ACL operations. */
3814 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
3815 .get_nt_acl_fn = vfswrap_get_nt_acl,
3816 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
3817 .audit_file_fn = vfswrap_audit_file,
3819 /* POSIX ACL operations. */
3821 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
3822 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3823 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
3824 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3825 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
3826 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3827 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
3829 /* EA operations. */
3830 .getxattr_fn = vfswrap_getxattr,
3831 .getxattrat_send_fn = vfswrap_getxattrat_send,
3832 .getxattrat_recv_fn = vfswrap_getxattrat_recv,
3833 .fgetxattr_fn = vfswrap_fgetxattr,
3834 .listxattr_fn = vfswrap_listxattr,
3835 .flistxattr_fn = vfswrap_flistxattr,
3836 .removexattr_fn = vfswrap_removexattr,
3837 .fremovexattr_fn = vfswrap_fremovexattr,
3838 .setxattr_fn = vfswrap_setxattr,
3839 .fsetxattr_fn = vfswrap_fsetxattr,
3841 /* aio operations */
3842 .aio_force_fn = vfswrap_aio_force,
3844 /* durable handle operations */
3845 .durable_cookie_fn = vfswrap_durable_cookie,
3846 .durable_disconnect_fn = vfswrap_durable_disconnect,
3847 .durable_reconnect_fn = vfswrap_durable_reconnect,
3851 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3854 * Here we need to implement every call!
3856 * As this is the end of the vfs module chain.
3858 smb_vfs_assert_all_fns(&vfs_default_fns, DEFAULT_VFS_MODULE_NAME);
3859 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3860 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);