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 {
938 struct vfs_aio_state vfs_aio_state;
939 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
942 static void vfs_pwrite_do(void *private_data);
943 static void vfs_pwrite_done(struct tevent_req *subreq);
944 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state);
946 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
948 struct tevent_context *ev,
949 struct files_struct *fsp,
951 size_t n, off_t offset)
953 struct tevent_req *req, *subreq;
954 struct vfswrap_pwrite_state *state;
956 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
962 state->fd = fsp->fh->fd;
965 state->offset = offset;
967 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
968 state->profile_bytes, n);
969 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
971 subreq = pthreadpool_tevent_job_send(
972 state, ev, handle->conn->sconn->pool,
973 vfs_pwrite_do, state);
974 if (tevent_req_nomem(subreq, req)) {
975 return tevent_req_post(req, ev);
977 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
979 talloc_set_destructor(state, vfs_pwrite_state_destructor);
984 static void vfs_pwrite_do(void *private_data)
986 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
987 private_data, struct vfswrap_pwrite_state);
988 struct timespec start_time;
989 struct timespec end_time;
991 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
993 PROFILE_TIMESTAMP(&start_time);
996 state->ret = pwrite(state->fd, state->buf, state->count,
998 } while ((state->ret == -1) && (errno == EINTR));
1000 if (state->ret == -1) {
1001 state->vfs_aio_state.error = errno;
1004 PROFILE_TIMESTAMP(&end_time);
1006 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1008 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1011 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state)
1016 static void vfs_pwrite_done(struct tevent_req *subreq)
1018 struct tevent_req *req = tevent_req_callback_data(
1019 subreq, struct tevent_req);
1020 struct vfswrap_pwrite_state *state = tevent_req_data(
1021 req, struct vfswrap_pwrite_state);
1024 ret = pthreadpool_tevent_job_recv(subreq);
1025 TALLOC_FREE(subreq);
1026 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1027 talloc_set_destructor(state, NULL);
1029 if (ret != EAGAIN) {
1030 tevent_req_error(req, ret);
1034 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1035 * means the lower level pthreadpool failed to create a new
1036 * thread. Fallback to sync processing in that case to allow
1037 * some progress for the client.
1039 vfs_pwrite_do(state);
1042 tevent_req_done(req);
1045 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
1046 struct vfs_aio_state *vfs_aio_state)
1048 struct vfswrap_pwrite_state *state = tevent_req_data(
1049 req, struct vfswrap_pwrite_state);
1051 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1055 *vfs_aio_state = state->vfs_aio_state;
1059 struct vfswrap_fsync_state {
1063 struct vfs_aio_state vfs_aio_state;
1064 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
1067 static void vfs_fsync_do(void *private_data);
1068 static void vfs_fsync_done(struct tevent_req *subreq);
1069 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state);
1071 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
1072 TALLOC_CTX *mem_ctx,
1073 struct tevent_context *ev,
1074 struct files_struct *fsp)
1076 struct tevent_req *req, *subreq;
1077 struct vfswrap_fsync_state *state;
1079 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
1085 state->fd = fsp->fh->fd;
1087 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_fsync, profile_p,
1088 state->profile_bytes, 0);
1089 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1091 subreq = pthreadpool_tevent_job_send(
1092 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
1093 if (tevent_req_nomem(subreq, req)) {
1094 return tevent_req_post(req, ev);
1096 tevent_req_set_callback(subreq, vfs_fsync_done, req);
1098 talloc_set_destructor(state, vfs_fsync_state_destructor);
1103 static void vfs_fsync_do(void *private_data)
1105 struct vfswrap_fsync_state *state = talloc_get_type_abort(
1106 private_data, struct vfswrap_fsync_state);
1107 struct timespec start_time;
1108 struct timespec end_time;
1110 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
1112 PROFILE_TIMESTAMP(&start_time);
1115 state->ret = fsync(state->fd);
1116 } while ((state->ret == -1) && (errno == EINTR));
1118 if (state->ret == -1) {
1119 state->vfs_aio_state.error = errno;
1122 PROFILE_TIMESTAMP(&end_time);
1124 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1126 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1129 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state)
1134 static void vfs_fsync_done(struct tevent_req *subreq)
1136 struct tevent_req *req = tevent_req_callback_data(
1137 subreq, struct tevent_req);
1138 struct vfswrap_fsync_state *state = tevent_req_data(
1139 req, struct vfswrap_fsync_state);
1142 ret = pthreadpool_tevent_job_recv(subreq);
1143 TALLOC_FREE(subreq);
1144 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1145 talloc_set_destructor(state, NULL);
1147 if (ret != EAGAIN) {
1148 tevent_req_error(req, ret);
1152 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1153 * means the lower level pthreadpool failed to create a new
1154 * thread. Fallback to sync processing in that case to allow
1155 * some progress for the client.
1157 vfs_fsync_do(state);
1160 tevent_req_done(req);
1163 static int vfswrap_fsync_recv(struct tevent_req *req,
1164 struct vfs_aio_state *vfs_aio_state)
1166 struct vfswrap_fsync_state *state = tevent_req_data(
1167 req, struct vfswrap_fsync_state);
1169 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1173 *vfs_aio_state = state->vfs_aio_state;
1177 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1181 START_PROFILE(syscall_lseek);
1183 result = lseek(fsp->fh->fd, offset, whence);
1185 * We want to maintain the fiction that we can seek
1186 * on a fifo for file system purposes. This allows
1187 * people to set up UNIX fifo's that feed data to Windows
1188 * applications. JRA.
1191 if((result == -1) && (errno == ESPIPE)) {
1196 END_PROFILE(syscall_lseek);
1200 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1201 off_t offset, size_t n)
1205 START_PROFILE_BYTES(syscall_sendfile, n);
1206 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
1207 END_PROFILE_BYTES(syscall_sendfile);
1211 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1213 files_struct *tofsp,
1219 START_PROFILE_BYTES(syscall_recvfile, n);
1220 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
1221 END_PROFILE_BYTES(syscall_recvfile);
1225 static int vfswrap_renameat(vfs_handle_struct *handle,
1226 files_struct *srcfsp,
1227 const struct smb_filename *smb_fname_src,
1228 files_struct *dstfsp,
1229 const struct smb_filename *smb_fname_dst)
1233 START_PROFILE(syscall_renameat);
1235 if (is_named_stream(smb_fname_src) || is_named_stream(smb_fname_dst)) {
1240 result = renameat(srcfsp->fh->fd,
1241 smb_fname_src->base_name,
1243 smb_fname_dst->base_name);
1246 END_PROFILE(syscall_renameat);
1250 static int vfswrap_stat(vfs_handle_struct *handle,
1251 struct smb_filename *smb_fname)
1255 START_PROFILE(syscall_stat);
1257 if (is_named_stream(smb_fname)) {
1262 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1263 lp_fake_directory_create_times(SNUM(handle->conn)));
1265 END_PROFILE(syscall_stat);
1269 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1273 START_PROFILE(syscall_fstat);
1274 result = sys_fstat(fsp->fh->fd,
1275 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1276 END_PROFILE(syscall_fstat);
1280 static int vfswrap_lstat(vfs_handle_struct *handle,
1281 struct smb_filename *smb_fname)
1285 START_PROFILE(syscall_lstat);
1287 if (is_named_stream(smb_fname)) {
1292 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1293 lp_fake_directory_create_times(SNUM(handle->conn)));
1295 END_PROFILE(syscall_lstat);
1299 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1301 enum vfs_translate_direction direction,
1302 TALLOC_CTX *mem_ctx,
1305 return NT_STATUS_NONE_MAPPED;
1309 * Implement the default fsctl operation.
1311 static bool vfswrap_logged_ioctl_message = false;
1313 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1314 struct files_struct *fsp,
1317 uint16_t req_flags, /* Needed for UNICODE ... */
1318 const uint8_t *_in_data,
1320 uint8_t **_out_data,
1321 uint32_t max_out_len,
1324 const char *in_data = (const char *)_in_data;
1325 char **out_data = (char **)_out_data;
1329 case FSCTL_SET_SPARSE:
1331 bool set_sparse = true;
1333 if (in_len >= 1 && in_data[0] == 0) {
1337 status = file_set_sparse(handle->conn, fsp, set_sparse);
1339 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1340 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1341 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1342 nt_errstr(status)));
1347 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1349 unsigned char objid[16];
1350 char *return_data = NULL;
1352 /* This should return the object-id on this file.
1353 * I think I'll make this be the inode+dev. JRA.
1356 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1357 fsp_fnum_dbg(fsp)));
1359 *out_len = MIN(max_out_len, 64);
1361 /* Hmmm, will this cause problems if less data asked for? */
1362 return_data = talloc_array(ctx, char, 64);
1363 if (return_data == NULL) {
1364 return NT_STATUS_NO_MEMORY;
1367 /* For backwards compatibility only store the dev/inode. */
1368 push_file_id_16(return_data, &fsp->file_id);
1369 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1370 push_file_id_16(return_data+32, &fsp->file_id);
1371 memset(return_data+48, 0, 16);
1372 *out_data = return_data;
1373 return NT_STATUS_OK;
1376 case FSCTL_GET_REPARSE_POINT:
1378 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1379 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1380 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1381 return NT_STATUS_NOT_A_REPARSE_POINT;
1384 case FSCTL_SET_REPARSE_POINT:
1386 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1387 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1388 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1389 return NT_STATUS_NOT_A_REPARSE_POINT;
1392 case FSCTL_GET_SHADOW_COPY_DATA:
1395 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1396 * and return their volume names. If max_data_count is 16, then it is just
1397 * asking for the number of volumes and length of the combined names.
1399 * pdata is the data allocated by our caller, but that uses
1400 * total_data_count (which is 0 in our case) rather than max_data_count.
1401 * Allocate the correct amount and return the pointer to let
1402 * it be deallocated when we return.
1404 struct shadow_copy_data *shadow_data = NULL;
1405 bool labels = False;
1406 uint32_t labels_data_count = 0;
1408 char *cur_pdata = NULL;
1410 if (max_out_len < 16) {
1411 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1413 return NT_STATUS_INVALID_PARAMETER;
1416 if (max_out_len > 16) {
1420 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1421 if (shadow_data == NULL) {
1422 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1423 return NT_STATUS_NO_MEMORY;
1427 * Call the VFS routine to actually do the work.
1429 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1432 /* broken module didn't set errno on error */
1433 status = NT_STATUS_UNSUCCESSFUL;
1435 status = map_nt_error_from_unix(errno);
1436 if (NT_STATUS_EQUAL(status,
1437 NT_STATUS_NOT_SUPPORTED)) {
1441 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1442 "connectpath %s, failed - %s.\n",
1443 fsp->conn->connectpath,
1444 nt_errstr(status)));
1445 TALLOC_FREE(shadow_data);
1449 labels_data_count = (shadow_data->num_volumes * 2 *
1450 sizeof(SHADOW_COPY_LABEL)) + 2;
1455 *out_len = 12 + labels_data_count;
1458 if (max_out_len < *out_len) {
1459 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1460 max_out_len, *out_len));
1461 TALLOC_FREE(shadow_data);
1462 return NT_STATUS_BUFFER_TOO_SMALL;
1465 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1466 if (cur_pdata == NULL) {
1467 TALLOC_FREE(shadow_data);
1468 return NT_STATUS_NO_MEMORY;
1471 *out_data = cur_pdata;
1473 /* num_volumes 4 bytes */
1474 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1477 /* num_labels 4 bytes */
1478 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1481 /* needed_data_count 4 bytes */
1482 SIVAL(cur_pdata, 8, labels_data_count);
1486 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1487 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1488 if (labels && shadow_data->labels) {
1489 for (i=0; i<shadow_data->num_volumes; i++) {
1491 status = srvstr_push(cur_pdata, req_flags,
1492 cur_pdata, shadow_data->labels[i],
1493 2 * sizeof(SHADOW_COPY_LABEL),
1494 STR_UNICODE|STR_TERMINATE, &len);
1495 if (!NT_STATUS_IS_OK(status)) {
1496 TALLOC_FREE(*out_data);
1497 TALLOC_FREE(shadow_data);
1500 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1501 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1505 TALLOC_FREE(shadow_data);
1507 return NT_STATUS_OK;
1510 case FSCTL_FIND_FILES_BY_SID:
1512 /* pretend this succeeded -
1514 * we have to send back a list with all files owned by this SID
1516 * but I have to check that --metze
1520 struct dom_sid_buf buf;
1524 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1525 fsp_fnum_dbg(fsp)));
1528 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1529 return NT_STATUS_INVALID_PARAMETER;
1532 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1534 /* unknown 4 bytes: this is not the length of the sid :-( */
1535 /*unknown = IVAL(pdata,0);*/
1537 ret = sid_parse(_in_data + 4, sid_len, &sid);
1539 return NT_STATUS_INVALID_PARAMETER;
1541 DEBUGADD(10, ("for SID: %s\n",
1542 dom_sid_str_buf(&sid, &buf)));
1544 if (!sid_to_uid(&sid, &uid)) {
1545 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1546 dom_sid_str_buf(&sid, &buf),
1547 (unsigned long)sid_len));
1551 /* we can take a look at the find source :-)
1553 * find ./ -uid $uid -name '*' is what we need here
1556 * and send 4bytes len and then NULL terminated unicode strings
1559 * but I don't know how to deal with the paged results
1560 * (maybe we can hang the result anywhere in the fsp struct)
1562 * but I don't know how to deal with the paged results
1563 * (maybe we can hang the result anywhere in the fsp struct)
1565 * we don't send all files at once
1566 * and at the next we should *not* start from the beginning,
1567 * so we have to cache the result
1572 /* this works for now... */
1573 return NT_STATUS_OK;
1576 case FSCTL_QUERY_ALLOCATED_RANGES:
1578 /* FIXME: This is just a dummy reply, telling that all of the
1579 * file is allocated. MKS cp needs that.
1580 * Adding the real allocated ranges via FIEMAP on Linux
1581 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1582 * this FSCTL correct for sparse files.
1584 uint64_t offset, length;
1585 char *out_data_tmp = NULL;
1588 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1590 return NT_STATUS_INVALID_PARAMETER;
1593 if (max_out_len < 16) {
1594 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1596 return NT_STATUS_INVALID_PARAMETER;
1599 offset = BVAL(in_data,0);
1600 length = BVAL(in_data,8);
1602 if (offset + length < offset) {
1603 /* No 64-bit integer wrap. */
1604 return NT_STATUS_INVALID_PARAMETER;
1607 /* Shouldn't this be SMB_VFS_STAT ... ? */
1608 status = vfs_stat_fsp(fsp);
1609 if (!NT_STATUS_IS_OK(status)) {
1614 out_data_tmp = talloc_array(ctx, char, *out_len);
1615 if (out_data_tmp == NULL) {
1616 DEBUG(10, ("unable to allocate memory for response\n"));
1617 return NT_STATUS_NO_MEMORY;
1620 if (offset > fsp->fsp_name->st.st_ex_size ||
1621 fsp->fsp_name->st.st_ex_size == 0 ||
1623 memset(out_data_tmp, 0, *out_len);
1625 uint64_t end = offset + length;
1626 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1627 SBVAL(out_data_tmp, 0, 0);
1628 SBVAL(out_data_tmp, 8, end);
1631 *out_data = out_data_tmp;
1633 return NT_STATUS_OK;
1636 case FSCTL_IS_VOLUME_DIRTY:
1638 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1639 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1641 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1642 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1644 return NT_STATUS_INVALID_PARAMETER;
1649 * Only print once ... unfortunately there could be lots of
1650 * different FSCTLs that are called.
1652 if (!vfswrap_logged_ioctl_message) {
1653 vfswrap_logged_ioctl_message = true;
1654 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1655 __func__, function));
1659 return NT_STATUS_NOT_SUPPORTED;
1662 static bool vfswrap_is_offline(struct connection_struct *conn,
1663 const struct smb_filename *fname);
1665 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1666 struct smb_filename *smb_fname,
1671 offline = vfswrap_is_offline(handle->conn, smb_fname);
1673 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1676 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1679 struct vfswrap_get_dos_attributes_state {
1680 struct vfs_aio_state aio_state;
1681 connection_struct *conn;
1682 TALLOC_CTX *mem_ctx;
1683 struct tevent_context *ev;
1684 files_struct *dir_fsp;
1685 struct smb_filename *smb_fname;
1690 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq);
1692 static struct tevent_req *vfswrap_get_dos_attributes_send(
1693 TALLOC_CTX *mem_ctx,
1694 struct tevent_context *ev,
1695 struct vfs_handle_struct *handle,
1696 files_struct *dir_fsp,
1697 struct smb_filename *smb_fname)
1699 struct tevent_req *req = NULL;
1700 struct tevent_req *subreq = NULL;
1701 struct vfswrap_get_dos_attributes_state *state = NULL;
1703 req = tevent_req_create(mem_ctx, &state,
1704 struct vfswrap_get_dos_attributes_state);
1709 *state = (struct vfswrap_get_dos_attributes_state) {
1710 .conn = dir_fsp->conn,
1714 .smb_fname = smb_fname,
1717 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1721 SAMBA_XATTR_DOS_ATTRIB,
1723 if (tevent_req_nomem(subreq, req)) {
1724 return tevent_req_post(req, ev);
1726 tevent_req_set_callback(subreq,
1727 vfswrap_get_dos_attributes_getxattr_done,
1733 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq)
1735 struct tevent_req *req =
1736 tevent_req_callback_data(subreq,
1738 struct vfswrap_get_dos_attributes_state *state =
1739 tevent_req_data(req,
1740 struct vfswrap_get_dos_attributes_state);
1742 DATA_BLOB blob = {0};
1744 char *tofree = NULL;
1745 char pathbuf[PATH_MAX+1];
1747 struct smb_filename smb_fname;
1751 xattr_size = SMB_VFS_GETXATTRAT_RECV(subreq,
1755 TALLOC_FREE(subreq);
1756 if (xattr_size == -1) {
1757 status = map_nt_error_from_unix(state->aio_state.error);
1759 if (state->as_root) {
1760 tevent_req_nterror(req, status);
1763 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1764 tevent_req_nterror(req, status);
1768 state->as_root = true;
1771 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1775 SAMBA_XATTR_DOS_ATTRIB,
1778 if (tevent_req_nomem(subreq, req)) {
1781 tevent_req_set_callback(subreq,
1782 vfswrap_get_dos_attributes_getxattr_done,
1787 blob.length = xattr_size;
1789 status = parse_dos_attribute_blob(state->smb_fname,
1792 if (!NT_STATUS_IS_OK(status)) {
1793 tevent_req_nterror(req, status);
1797 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
1798 state->smb_fname->base_name,
1803 if (pathlen == -1) {
1804 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1808 smb_fname = (struct smb_filename) {
1810 .st = state->smb_fname->st,
1811 .flags = state->smb_fname->flags,
1814 offline = vfswrap_is_offline(state->conn, &smb_fname);
1816 state->dosmode |= FILE_ATTRIBUTE_OFFLINE;
1818 TALLOC_FREE(tofree);
1820 tevent_req_done(req);
1824 static NTSTATUS vfswrap_get_dos_attributes_recv(struct tevent_req *req,
1825 struct vfs_aio_state *aio_state,
1828 struct vfswrap_get_dos_attributes_state *state =
1829 tevent_req_data(req,
1830 struct vfswrap_get_dos_attributes_state);
1833 if (tevent_req_is_nterror(req, &status)) {
1834 tevent_req_received(req);
1838 *aio_state = state->aio_state;
1839 *dosmode = state->dosmode;
1840 tevent_req_received(req);
1841 return NT_STATUS_OK;
1844 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1845 struct files_struct *fsp,
1850 offline = vfswrap_is_offline(handle->conn, fsp->fsp_name);
1852 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1855 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1858 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1859 const struct smb_filename *smb_fname,
1862 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1865 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1866 struct files_struct *fsp,
1869 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1872 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1874 struct vfswrap_offload_read_state {
1878 static struct tevent_req *vfswrap_offload_read_send(
1879 TALLOC_CTX *mem_ctx,
1880 struct tevent_context *ev,
1881 struct vfs_handle_struct *handle,
1882 struct files_struct *fsp,
1888 struct tevent_req *req = NULL;
1889 struct vfswrap_offload_read_state *state = NULL;
1892 req = tevent_req_create(mem_ctx, &state,
1893 struct vfswrap_offload_read_state);
1898 status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1899 &vfswrap_offload_ctx);
1900 if (tevent_req_nterror(req, status)) {
1901 return tevent_req_post(req, ev);
1904 if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1905 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1906 return tevent_req_post(req, ev);
1909 status = vfs_offload_token_create_blob(state, fsp, fsctl,
1911 if (tevent_req_nterror(req, status)) {
1912 return tevent_req_post(req, ev);
1915 status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1917 if (tevent_req_nterror(req, status)) {
1918 return tevent_req_post(req, ev);
1921 tevent_req_done(req);
1922 return tevent_req_post(req, ev);
1925 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
1926 struct vfs_handle_struct *handle,
1927 TALLOC_CTX *mem_ctx,
1930 struct vfswrap_offload_read_state *state = tevent_req_data(
1931 req, struct vfswrap_offload_read_state);
1934 if (tevent_req_is_nterror(req, &status)) {
1935 tevent_req_received(req);
1939 token->length = state->token.length;
1940 token->data = talloc_move(mem_ctx, &state->token.data);
1942 tevent_req_received(req);
1943 return NT_STATUS_OK;
1946 struct vfswrap_offload_write_state {
1948 bool read_lck_locked;
1949 bool write_lck_locked;
1951 struct tevent_context *src_ev;
1952 struct files_struct *src_fsp;
1954 struct tevent_context *dst_ev;
1955 struct files_struct *dst_fsp;
1959 size_t next_io_size;
1962 static void vfswrap_offload_write_cleanup(struct tevent_req *req,
1963 enum tevent_req_state req_state)
1965 struct vfswrap_offload_write_state *state = tevent_req_data(
1966 req, struct vfswrap_offload_write_state);
1969 if (state->dst_fsp == NULL) {
1973 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
1975 state->dst_fsp = NULL;
1978 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
1980 static struct tevent_req *vfswrap_offload_write_send(
1981 struct vfs_handle_struct *handle,
1982 TALLOC_CTX *mem_ctx,
1983 struct tevent_context *ev,
1986 off_t transfer_offset,
1987 struct files_struct *dest_fsp,
1991 struct tevent_req *req;
1992 struct vfswrap_offload_write_state *state = NULL;
1993 /* off_t is signed! */
1994 off_t max_offset = INT64_MAX - to_copy;
1995 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
1996 files_struct *src_fsp = NULL;
2000 req = tevent_req_create(mem_ctx, &state,
2001 struct vfswrap_offload_write_state);
2006 *state = (struct vfswrap_offload_write_state) {
2008 .src_off = transfer_offset,
2010 .dst_fsp = dest_fsp,
2011 .dst_off = dest_off,
2013 .remaining = to_copy,
2016 tevent_req_set_cleanup_fn(req, vfswrap_offload_write_cleanup);
2019 case FSCTL_SRV_COPYCHUNK:
2020 case FSCTL_SRV_COPYCHUNK_WRITE:
2023 case FSCTL_OFFLOAD_WRITE:
2024 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
2025 return tevent_req_post(req, ev);
2027 case FSCTL_DUP_EXTENTS_TO_FILE:
2028 DBG_DEBUG("COW clones not supported by vfs_default\n");
2029 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2030 return tevent_req_post(req, ev);
2033 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2034 return tevent_req_post(req, ev);
2038 * From here on we assume a copy-chunk fsctl
2042 tevent_req_done(req);
2043 return tevent_req_post(req, ev);
2046 if (state->src_off > max_offset) {
2048 * Protect integer checks below.
2050 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2051 return tevent_req_post(req, ev);
2053 if (state->src_off < 0) {
2055 * Protect integer checks below.
2057 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2058 return tevent_req_post(req, ev);
2060 if (state->dst_off > max_offset) {
2062 * Protect integer checks below.
2064 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2065 return tevent_req_post(req, ev);
2067 if (state->dst_off < 0) {
2069 * Protect integer checks below.
2071 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2072 return tevent_req_post(req, ev);
2075 status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
2077 if (tevent_req_nterror(req, status)) {
2078 return tevent_req_post(req, ev);
2081 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
2083 status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
2084 if (!NT_STATUS_IS_OK(status)) {
2085 tevent_req_nterror(req, status);
2086 return tevent_req_post(req, ev);
2089 ok = change_to_user_and_service_by_fsp(src_fsp);
2091 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2092 return tevent_req_post(req, ev);
2095 state->src_ev = src_fsp->conn->sconn->ev_ctx;
2096 state->src_fsp = src_fsp;
2098 status = vfs_stat_fsp(src_fsp);
2099 if (tevent_req_nterror(req, status)) {
2100 return tevent_req_post(req, ev);
2103 if (src_fsp->fsp_name->st.st_ex_size < state->src_off + to_copy) {
2105 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
2106 * If the SourceOffset or SourceOffset + Length extends beyond
2107 * the end of file, the server SHOULD<240> treat this as a
2108 * STATUS_END_OF_FILE error.
2110 * <240> Section 3.3.5.15.6: Windows servers will return
2111 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
2113 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
2114 return tevent_req_post(req, ev);
2117 state->buf = talloc_array(state, uint8_t, num);
2118 if (tevent_req_nomem(state->buf, req)) {
2119 return tevent_req_post(req, ev);
2122 status = vfswrap_offload_write_loop(req);
2123 if (!NT_STATUS_IS_OK(status)) {
2124 tevent_req_nterror(req, status);
2125 return tevent_req_post(req, ev);
2131 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
2133 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
2135 struct vfswrap_offload_write_state *state = tevent_req_data(
2136 req, struct vfswrap_offload_write_state);
2137 struct tevent_req *subreq = NULL;
2138 struct lock_struct read_lck;
2142 * This is called under the context of state->src_fsp.
2145 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
2147 init_strict_lock_struct(state->src_fsp,
2148 state->src_fsp->op->global->open_persistent_id,
2150 state->next_io_size,
2154 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
2158 return NT_STATUS_FILE_LOCK_CONFLICT;
2161 subreq = SMB_VFS_PREAD_SEND(state,
2165 state->next_io_size,
2167 if (subreq == NULL) {
2168 return NT_STATUS_NO_MEMORY;
2170 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
2172 return NT_STATUS_OK;
2175 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
2177 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
2179 struct tevent_req *req = tevent_req_callback_data(
2180 subreq, struct tevent_req);
2181 struct vfswrap_offload_write_state *state = tevent_req_data(
2182 req, struct vfswrap_offload_write_state);
2183 struct vfs_aio_state aio_state;
2184 struct lock_struct write_lck;
2188 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
2189 TALLOC_FREE(subreq);
2191 DBG_ERR("read failed: %s\n", strerror(aio_state.error));
2192 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2195 if (nread != state->next_io_size) {
2196 DBG_ERR("Short read, only %zd of %zu\n",
2197 nread, state->next_io_size);
2198 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2202 state->src_off += nread;
2204 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2206 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2210 init_strict_lock_struct(state->dst_fsp,
2211 state->dst_fsp->op->global->open_persistent_id,
2213 state->next_io_size,
2217 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
2221 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
2225 subreq = SMB_VFS_PWRITE_SEND(state,
2229 state->next_io_size,
2231 if (subreq == NULL) {
2232 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2235 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
2238 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
2240 struct tevent_req *req = tevent_req_callback_data(
2241 subreq, struct tevent_req);
2242 struct vfswrap_offload_write_state *state = tevent_req_data(
2243 req, struct vfswrap_offload_write_state);
2244 struct vfs_aio_state aio_state;
2249 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
2250 TALLOC_FREE(subreq);
2251 if (nwritten == -1) {
2252 DBG_ERR("write failed: %s\n", strerror(aio_state.error));
2253 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2256 if (nwritten != state->next_io_size) {
2257 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
2258 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2262 state->dst_off += nwritten;
2264 if (state->remaining < nwritten) {
2265 /* Paranoia check */
2266 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2269 state->remaining -= nwritten;
2270 if (state->remaining == 0) {
2271 tevent_req_done(req);
2275 ok = change_to_user_and_service_by_fsp(state->src_fsp);
2277 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2281 status = vfswrap_offload_write_loop(req);
2282 if (!NT_STATUS_IS_OK(status)) {
2283 tevent_req_nterror(req, status);
2290 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
2291 struct tevent_req *req,
2294 struct vfswrap_offload_write_state *state = tevent_req_data(
2295 req, struct vfswrap_offload_write_state);
2298 if (tevent_req_is_nterror(req, &status)) {
2299 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
2301 tevent_req_received(req);
2305 *copied = state->to_copy;
2306 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
2307 tevent_req_received(req);
2309 return NT_STATUS_OK;
2312 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
2313 TALLOC_CTX *mem_ctx,
2314 struct files_struct *fsp,
2315 struct smb_filename *smb_fname,
2316 uint16_t *_compression_fmt)
2318 return NT_STATUS_INVALID_DEVICE_REQUEST;
2321 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
2322 TALLOC_CTX *mem_ctx,
2323 struct files_struct *fsp,
2324 uint16_t compression_fmt)
2326 return NT_STATUS_INVALID_DEVICE_REQUEST;
2329 /********************************************************************
2330 Given a stat buffer return the allocated size on disk, taking into
2331 account sparse files.
2332 ********************************************************************/
2333 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
2334 struct files_struct *fsp,
2335 const SMB_STRUCT_STAT *sbuf)
2339 START_PROFILE(syscall_get_alloc_size);
2341 if(S_ISDIR(sbuf->st_ex_mode)) {
2346 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2347 /* The type of st_blocksize is blkcnt_t which *MUST* be
2348 signed (according to POSIX) and can be less than 64-bits.
2349 Ensure when we're converting to 64 bits wide we don't
2351 #if defined(SIZEOF_BLKCNT_T_8)
2352 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2353 #elif defined(SIZEOF_BLKCNT_T_4)
2355 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2356 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2359 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2363 * Some file systems do not allocate a block for very
2364 * small files. But for non-empty file should report a
2368 uint64_t filesize = get_file_size_stat(sbuf);
2370 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2374 result = get_file_size_stat(sbuf);
2377 if (fsp && fsp->initial_allocation_size)
2378 result = MAX(result,fsp->initial_allocation_size);
2380 result = smb_roundup(handle->conn, result);
2383 END_PROFILE(syscall_get_alloc_size);
2387 static int vfswrap_unlinkat(vfs_handle_struct *handle,
2388 struct files_struct *dirfsp,
2389 const struct smb_filename *smb_fname,
2394 START_PROFILE(syscall_unlinkat);
2396 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2398 if (is_named_stream(smb_fname)) {
2402 result = unlinkat(dirfsp->fh->fd,
2403 smb_fname->base_name,
2407 END_PROFILE(syscall_unlinkat);
2411 static int vfswrap_chmod(vfs_handle_struct *handle,
2412 const struct smb_filename *smb_fname,
2417 START_PROFILE(syscall_chmod);
2418 result = chmod(smb_fname->base_name, mode);
2419 END_PROFILE(syscall_chmod);
2423 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2427 START_PROFILE(syscall_fchmod);
2428 #if defined(HAVE_FCHMOD)
2429 result = fchmod(fsp->fh->fd, mode);
2435 END_PROFILE(syscall_fchmod);
2439 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2444 START_PROFILE(syscall_fchown);
2445 result = fchown(fsp->fh->fd, uid, gid);
2446 END_PROFILE(syscall_fchown);
2454 static int vfswrap_lchown(vfs_handle_struct *handle,
2455 const struct smb_filename *smb_fname,
2461 START_PROFILE(syscall_lchown);
2462 result = lchown(smb_fname->base_name, uid, gid);
2463 END_PROFILE(syscall_lchown);
2467 static int vfswrap_chdir(vfs_handle_struct *handle,
2468 const struct smb_filename *smb_fname)
2472 START_PROFILE(syscall_chdir);
2473 result = chdir(smb_fname->base_name);
2474 END_PROFILE(syscall_chdir);
2478 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2482 struct smb_filename *smb_fname = NULL;
2484 START_PROFILE(syscall_getwd);
2485 result = sys_getwd();
2486 END_PROFILE(syscall_getwd);
2488 if (result == NULL) {
2491 smb_fname = synthetic_smb_fname(ctx,
2497 * sys_getwd() *always* returns malloced memory.
2498 * We must free here to avoid leaks:
2499 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2505 /*********************************************************************
2506 nsec timestamp resolution call. Convert down to whatever the underlying
2507 system will support.
2508 **********************************************************************/
2510 static int vfswrap_ntimes(vfs_handle_struct *handle,
2511 const struct smb_filename *smb_fname,
2512 struct smb_file_time *ft)
2516 START_PROFILE(syscall_ntimes);
2518 if (is_named_stream(smb_fname)) {
2524 if (is_omit_timespec(&ft->atime)) {
2525 ft->atime= smb_fname->st.st_ex_atime;
2528 if (is_omit_timespec(&ft->mtime)) {
2529 ft->mtime = smb_fname->st.st_ex_mtime;
2532 if (!is_omit_timespec(&ft->create_time)) {
2533 set_create_timespec_ea(handle->conn,
2538 if ((timespec_compare(&ft->atime,
2539 &smb_fname->st.st_ex_atime) == 0) &&
2540 (timespec_compare(&ft->mtime,
2541 &smb_fname->st.st_ex_mtime) == 0)) {
2546 #if defined(HAVE_UTIMENSAT)
2548 struct timespec ts[2];
2551 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2553 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2555 if (!((result == -1) && (errno == ENOSYS))) {
2559 #if defined(HAVE_UTIMES)
2561 struct timeval tv[2];
2562 tv[0] = convert_timespec_to_timeval(ft->atime);
2563 tv[1] = convert_timespec_to_timeval(ft->mtime);
2564 result = utimes(smb_fname->base_name, tv);
2566 result = utimes(smb_fname->base_name, NULL);
2568 if (!((result == -1) && (errno == ENOSYS))) {
2572 #if defined(HAVE_UTIME)
2574 struct utimbuf times;
2575 times.actime = convert_timespec_to_time_t(ft->atime);
2576 times.modtime = convert_timespec_to_time_t(ft->mtime);
2577 result = utime(smb_fname->base_name, ×);
2579 result = utime(smb_fname->base_name, NULL);
2581 if (!((result == -1) && (errno == ENOSYS))) {
2589 END_PROFILE(syscall_ntimes);
2593 /*********************************************************************
2594 A version of ftruncate that will write the space on disk if strict
2596 **********************************************************************/
2598 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2600 off_t space_to_write;
2601 uint64_t space_avail;
2602 uint64_t bsize,dfree,dsize;
2605 SMB_STRUCT_STAT *pst;
2607 status = vfs_stat_fsp(fsp);
2608 if (!NT_STATUS_IS_OK(status)) {
2611 pst = &fsp->fsp_name->st;
2614 if (S_ISFIFO(pst->st_ex_mode))
2618 if (pst->st_ex_size == len)
2621 /* Shrink - just ftruncate. */
2622 if (pst->st_ex_size > len)
2623 return ftruncate(fsp->fh->fd, len);
2625 space_to_write = len - pst->st_ex_size;
2627 /* for allocation try fallocate first. This can fail on some
2628 platforms e.g. when the filesystem doesn't support it and no
2629 emulation is being done by the libc (like on AIX with JFS1). In that
2630 case we do our own emulation. fallocate implementations can
2631 return ENOTSUP or EINVAL in cases like that. */
2632 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2633 if (ret == -1 && errno == ENOSPC) {
2639 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2640 "error %d. Falling back to slow manual allocation\n", errno));
2642 /* available disk space is enough or not? */
2644 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2645 /* space_avail is 1k blocks */
2646 if (space_avail == (uint64_t)-1 ||
2647 ((uint64_t)space_to_write/1024 > space_avail) ) {
2652 /* Write out the real space on disk. */
2653 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2661 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2664 SMB_STRUCT_STAT *pst;
2668 START_PROFILE(syscall_ftruncate);
2670 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2671 result = strict_allocate_ftruncate(handle, fsp, len);
2672 END_PROFILE(syscall_ftruncate);
2676 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2677 ftruncate if the system supports it. Then I discovered that
2678 you can have some filesystems that support ftruncate
2679 expansion and some that don't! On Linux fat can't do
2680 ftruncate extend but ext2 can. */
2682 result = ftruncate(fsp->fh->fd, len);
2684 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2685 extend a file with ftruncate. Provide alternate implementation
2688 /* Do an fstat to see if the file is longer than the requested
2689 size in which case the ftruncate above should have
2690 succeeded or shorter, in which case seek to len - 1 and
2691 write 1 byte of zero */
2692 status = vfs_stat_fsp(fsp);
2693 if (!NT_STATUS_IS_OK(status)) {
2697 /* We need to update the files_struct after successful ftruncate */
2702 pst = &fsp->fsp_name->st;
2705 if (S_ISFIFO(pst->st_ex_mode)) {
2711 if (pst->st_ex_size == len) {
2716 if (pst->st_ex_size > len) {
2717 /* the ftruncate should have worked */
2721 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2729 END_PROFILE(syscall_ftruncate);
2733 static int vfswrap_fallocate(vfs_handle_struct *handle,
2741 START_PROFILE(syscall_fallocate);
2743 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2745 * posix_fallocate returns 0 on success, errno on error
2746 * and doesn't set errno. Make it behave like fallocate()
2747 * which returns -1, and sets errno on failure.
2754 /* sys_fallocate handles filtering of unsupported mode flags */
2755 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2757 END_PROFILE(syscall_fallocate);
2761 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2765 START_PROFILE(syscall_fcntl_lock);
2767 if (fsp->use_ofd_locks) {
2768 op = map_process_lock_to_ofd_lock(op);
2771 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2772 END_PROFILE(syscall_fcntl_lock);
2776 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2777 uint32_t share_access, uint32_t access_mask)
2779 START_PROFILE(syscall_kernel_flock);
2780 kernel_flock(fsp->fh->fd, share_access, access_mask);
2781 END_PROFILE(syscall_kernel_flock);
2785 static int vfswrap_fcntl(vfs_handle_struct *handle, files_struct *fsp, int cmd,
2789 va_list dup_cmd_arg;
2793 START_PROFILE(syscall_fcntl);
2795 va_copy(dup_cmd_arg, cmd_arg);
2801 #if defined(HAVE_OFD_LOCKS)
2806 #if defined(HAVE_F_OWNER_EX)
2810 #if defined(HAVE_RW_HINTS)
2813 case F_GET_FILE_RW_HINT:
2814 case F_SET_FILE_RW_HINT:
2816 argp = va_arg(dup_cmd_arg, void *);
2817 result = sys_fcntl_ptr(fsp->fh->fd, cmd, argp);
2820 val = va_arg(dup_cmd_arg, int);
2821 result = sys_fcntl_int(fsp->fh->fd, cmd, val);
2824 va_end(dup_cmd_arg);
2826 END_PROFILE(syscall_fcntl);
2830 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2835 START_PROFILE(syscall_fcntl_getlock);
2837 if (fsp->use_ofd_locks) {
2838 op = map_process_lock_to_ofd_lock(op);
2841 result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2842 END_PROFILE(syscall_fcntl_getlock);
2846 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2851 START_PROFILE(syscall_linux_setlease);
2853 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2854 result = linux_setlease(fsp->fh->fd, leasetype);
2858 END_PROFILE(syscall_linux_setlease);
2862 static int vfswrap_symlinkat(vfs_handle_struct *handle,
2863 const char *link_target,
2864 struct files_struct *dirfsp,
2865 const struct smb_filename *new_smb_fname)
2869 START_PROFILE(syscall_symlinkat);
2871 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2873 result = symlinkat(link_target,
2875 new_smb_fname->base_name);
2876 END_PROFILE(syscall_symlinkat);
2880 static int vfswrap_readlinkat(vfs_handle_struct *handle,
2881 files_struct *dirfsp,
2882 const struct smb_filename *smb_fname,
2888 START_PROFILE(syscall_readlinkat);
2890 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2892 result = readlinkat(dirfsp->fh->fd,
2893 smb_fname->base_name,
2897 END_PROFILE(syscall_readlinkat);
2901 static int vfswrap_linkat(vfs_handle_struct *handle,
2902 files_struct *srcfsp,
2903 const struct smb_filename *old_smb_fname,
2904 files_struct *dstfsp,
2905 const struct smb_filename *new_smb_fname,
2910 START_PROFILE(syscall_linkat);
2912 SMB_ASSERT(srcfsp == srcfsp->conn->cwd_fsp);
2913 SMB_ASSERT(dstfsp == dstfsp->conn->cwd_fsp);
2915 result = linkat(srcfsp->fh->fd,
2916 old_smb_fname->base_name,
2918 new_smb_fname->base_name,
2921 END_PROFILE(syscall_linkat);
2925 static int vfswrap_mknodat(vfs_handle_struct *handle,
2926 files_struct *dirfsp,
2927 const struct smb_filename *smb_fname,
2933 START_PROFILE(syscall_mknodat);
2935 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2937 result = sys_mknodat(dirfsp->fh->fd,
2938 smb_fname->base_name,
2942 END_PROFILE(syscall_mknodat);
2946 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2948 const struct smb_filename *smb_fname)
2951 struct smb_filename *result_fname = NULL;
2953 START_PROFILE(syscall_realpath);
2954 result = sys_realpath(smb_fname->base_name);
2955 END_PROFILE(syscall_realpath);
2957 result_fname = synthetic_smb_fname(ctx, result, NULL, NULL, 0);
2960 return result_fname;
2963 static int vfswrap_chflags(vfs_handle_struct *handle,
2964 const struct smb_filename *smb_fname,
2968 return chflags(smb_fname->base_name, flags);
2975 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2976 const SMB_STRUCT_STAT *sbuf)
2980 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2984 key.devid = sbuf->st_ex_dev;
2985 key.inode = sbuf->st_ex_ino;
2986 /* key.extid is unused by default. */
2991 static uint64_t vfswrap_fs_file_id(struct vfs_handle_struct *handle,
2992 const SMB_STRUCT_STAT *psbuf)
2996 if (!(psbuf->st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)) {
2997 return psbuf->st_ex_file_id;
3000 if (handle->conn->base_share_dev == psbuf->st_ex_dev) {
3001 return (uint64_t)psbuf->st_ex_ino;
3005 file_id = ((psbuf->st_ex_ino) & UINT32_MAX);
3008 file_id |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32;
3013 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
3014 struct files_struct *fsp,
3015 const struct smb_filename *smb_fname,
3016 TALLOC_CTX *mem_ctx,
3017 unsigned int *pnum_streams,
3018 struct stream_struct **pstreams)
3020 SMB_STRUCT_STAT sbuf;
3021 struct stream_struct *tmp_streams = NULL;
3024 if ((fsp != NULL) && (fsp->is_directory)) {
3026 * No default streams on directories
3031 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
3032 ret = SMB_VFS_FSTAT(fsp, &sbuf);
3035 struct smb_filename smb_fname_cp;
3037 ZERO_STRUCT(smb_fname_cp);
3038 smb_fname_cp.base_name = discard_const_p(char,
3039 smb_fname->base_name);
3040 smb_fname_cp.flags = smb_fname->flags;
3042 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
3043 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
3045 ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
3047 sbuf = smb_fname_cp.st;
3051 return map_nt_error_from_unix(errno);
3054 if (S_ISDIR(sbuf.st_ex_mode)) {
3058 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
3059 (*pnum_streams) + 1);
3060 if (tmp_streams == NULL) {
3061 return NT_STATUS_NO_MEMORY;
3063 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
3064 if (tmp_streams[*pnum_streams].name == NULL) {
3065 return NT_STATUS_NO_MEMORY;
3067 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
3068 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
3071 *pstreams = tmp_streams;
3073 return NT_STATUS_OK;
3076 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
3079 TALLOC_CTX *mem_ctx,
3083 * Don't fall back to get_real_filename so callers can differentiate
3084 * between a full directory scan and an actual case-insensitive stat.
3090 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
3091 const struct smb_filename *smb_fname)
3093 return handle->conn->connectpath;
3096 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
3097 struct byte_range_lock *br_lck,
3098 struct lock_struct *plock)
3100 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3102 /* Note: blr is not used in the default implementation. */
3103 return brl_lock_windows_default(br_lck, plock);
3106 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
3107 struct byte_range_lock *br_lck,
3108 const struct lock_struct *plock)
3110 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3112 return brl_unlock_windows_default(br_lck, plock);
3115 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
3117 struct lock_struct *plock)
3119 SMB_ASSERT(plock->lock_type == READ_LOCK ||
3120 plock->lock_type == WRITE_LOCK);
3122 return strict_lock_check_default(fsp, plock);
3125 /* NT ACL operations. */
3127 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
3129 uint32_t security_info,
3130 TALLOC_CTX *mem_ctx,
3131 struct security_descriptor **ppdesc)
3135 START_PROFILE(fget_nt_acl);
3136 result = posix_fget_nt_acl(fsp, security_info,
3138 END_PROFILE(fget_nt_acl);
3142 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
3143 const struct smb_filename *smb_fname,
3144 uint32_t security_info,
3145 TALLOC_CTX *mem_ctx,
3146 struct security_descriptor **ppdesc)
3150 START_PROFILE(get_nt_acl);
3151 result = posix_get_nt_acl(handle->conn,
3156 END_PROFILE(get_nt_acl);
3160 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
3164 START_PROFILE(fset_nt_acl);
3165 result = set_nt_acl(fsp, security_info_sent, psd);
3166 END_PROFILE(fset_nt_acl);
3170 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
3171 struct smb_filename *file,
3172 struct security_acl *sacl,
3173 uint32_t access_requested,
3174 uint32_t access_denied)
3176 return NT_STATUS_OK; /* Nothing to do here ... */
3179 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
3180 const struct smb_filename *smb_fname,
3181 SMB_ACL_TYPE_T type,
3182 TALLOC_CTX *mem_ctx)
3184 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
3187 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
3189 TALLOC_CTX *mem_ctx)
3191 return sys_acl_get_fd(handle, fsp, mem_ctx);
3194 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
3195 const struct smb_filename *smb_fname,
3196 SMB_ACL_TYPE_T acltype,
3199 return sys_acl_set_file(handle, smb_fname, acltype, theacl);
3202 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
3204 return sys_acl_set_fd(handle, fsp, theacl);
3207 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
3208 const struct smb_filename *smb_fname)
3210 return sys_acl_delete_def_file(handle, smb_fname);
3213 /****************************************************************
3214 Extended attribute operations.
3215 *****************************************************************/
3217 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
3218 const struct smb_filename *smb_fname,
3223 return getxattr(smb_fname->base_name, name, value, size);
3226 struct vfswrap_getxattrat_state {
3227 struct tevent_context *ev;
3228 files_struct *dir_fsp;
3229 const struct smb_filename *smb_fname;
3230 struct tevent_req *req;
3233 * The following variables are talloced off "state" which is protected
3234 * by a destructor and thus are guaranteed to be safe to be used in the
3235 * job function in the worker thread.
3238 const char *xattr_name;
3239 uint8_t *xattr_value;
3240 struct security_unix_token *token;
3243 struct vfs_aio_state vfs_aio_state;
3244 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
3247 static int vfswrap_getxattrat_state_destructor(
3248 struct vfswrap_getxattrat_state *state)
3253 static void vfswrap_getxattrat_do_sync(struct tevent_req *req);
3254 static void vfswrap_getxattrat_do_async(void *private_data);
3255 static void vfswrap_getxattrat_done(struct tevent_req *subreq);
3257 static struct tevent_req *vfswrap_getxattrat_send(
3258 TALLOC_CTX *mem_ctx,
3259 struct tevent_context *ev,
3260 struct vfs_handle_struct *handle,
3261 files_struct *dir_fsp,
3262 const struct smb_filename *smb_fname,
3263 const char *xattr_name,
3266 struct tevent_req *req = NULL;
3267 struct tevent_req *subreq = NULL;
3268 struct vfswrap_getxattrat_state *state = NULL;
3269 size_t max_threads = 0;
3270 bool have_per_thread_cwd = false;
3271 bool have_per_thread_creds = false;
3272 bool do_async = false;
3274 req = tevent_req_create(mem_ctx, &state,
3275 struct vfswrap_getxattrat_state);
3279 *state = (struct vfswrap_getxattrat_state) {
3282 .smb_fname = smb_fname,
3286 max_threads = pthreadpool_tevent_max_threads(dir_fsp->conn->sconn->pool);
3287 if (max_threads >= 1) {
3289 * We need a non sync threadpool!
3291 have_per_thread_cwd = per_thread_cwd_supported();
3293 #ifdef HAVE_LINUX_THREAD_CREDENTIALS
3294 have_per_thread_creds = true;
3296 if (have_per_thread_cwd && have_per_thread_creds) {
3300 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat, profile_p,
3301 state->profile_bytes, 0);
3303 if (dir_fsp->fh->fd == -1) {
3304 DBG_ERR("Need a valid directory fd\n");
3305 tevent_req_error(req, EINVAL);
3306 return tevent_req_post(req, ev);
3309 if (alloc_hint > 0) {
3310 state->xattr_value = talloc_zero_array(state,
3313 if (tevent_req_nomem(state->xattr_value, req)) {
3314 return tevent_req_post(req, ev);
3319 vfswrap_getxattrat_do_sync(req);
3320 return tevent_req_post(req, ev);
3324 * Now allocate all parameters from a memory context that won't go away
3325 * no matter what. These paremeters will get used in threads and we
3326 * can't reliably cancel threads, so all buffers passed to the threads
3327 * must not be freed before all referencing threads terminate.
3330 state->name = talloc_strdup(state, smb_fname->base_name);
3331 if (tevent_req_nomem(state->name, req)) {
3332 return tevent_req_post(req, ev);
3335 state->xattr_name = talloc_strdup(state, xattr_name);
3336 if (tevent_req_nomem(state->xattr_name, req)) {
3337 return tevent_req_post(req, ev);
3341 * This is a hot codepath so at first glance one might think we should
3342 * somehow optimize away the token allocation and do a
3343 * talloc_reference() or similar black magic instead. But due to the
3344 * talloc_stackframe pool per SMB2 request this should be a simple copy
3345 * without a malloc in most cases.
3347 if (geteuid() == sec_initial_uid()) {
3348 state->token = root_unix_token(state);
3350 state->token = copy_unix_token(
3352 dir_fsp->conn->session_info->unix_token);
3354 if (tevent_req_nomem(state->token, req)) {
3355 return tevent_req_post(req, ev);
3358 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3360 subreq = pthreadpool_tevent_job_send(
3363 dir_fsp->conn->sconn->pool,
3364 vfswrap_getxattrat_do_async,
3366 if (tevent_req_nomem(subreq, req)) {
3367 return tevent_req_post(req, ev);
3369 tevent_req_set_callback(subreq, vfswrap_getxattrat_done, req);
3371 talloc_set_destructor(state, vfswrap_getxattrat_state_destructor);
3376 static void vfswrap_getxattrat_do_sync(struct tevent_req *req)
3378 struct vfswrap_getxattrat_state *state = tevent_req_data(
3379 req, struct vfswrap_getxattrat_state);
3381 char *tofree = NULL;
3382 char pathbuf[PATH_MAX+1];
3386 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
3387 state->smb_fname->base_name,
3392 if (pathlen == -1) {
3393 tevent_req_error(req, ENOMEM);
3397 state->xattr_size = getxattr(path,
3400 talloc_array_length(state->xattr_value));
3402 TALLOC_FREE(tofree);
3403 if (state->xattr_size == -1) {
3404 tevent_req_error(req, err);
3408 tevent_req_done(req);
3412 static void vfswrap_getxattrat_do_async(void *private_data)
3414 struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3415 private_data, struct vfswrap_getxattrat_state);
3416 struct timespec start_time;
3417 struct timespec end_time;
3420 PROFILE_TIMESTAMP(&start_time);
3421 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
3424 * Here we simulate a getxattrat()
3425 * call using fchdir();getxattr()
3428 per_thread_cwd_activate();
3430 /* Become the correct credential on this thread. */
3431 ret = set_thread_credentials(state->token->uid,
3433 (size_t)state->token->ngroups,
3434 state->token->groups);
3436 state->xattr_size = -1;
3437 state->vfs_aio_state.error = errno;
3441 ret = fchdir(state->dir_fsp->fh->fd);
3443 state->xattr_size = -1;
3444 state->vfs_aio_state.error = errno;
3448 state->xattr_size = getxattr(state->name,
3451 talloc_array_length(state->xattr_value));
3452 if (state->xattr_size == -1) {
3453 state->vfs_aio_state.error = errno;
3457 PROFILE_TIMESTAMP(&end_time);
3458 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
3459 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3462 static void vfswrap_getxattrat_done(struct tevent_req *subreq)
3464 struct tevent_req *req = tevent_req_callback_data(
3465 subreq, struct tevent_req);
3466 struct vfswrap_getxattrat_state *state = tevent_req_data(
3467 req, struct vfswrap_getxattrat_state);
3472 * Make sure we run as the user again
3474 ok = change_to_user_and_service_by_fsp(state->dir_fsp);
3477 ret = pthreadpool_tevent_job_recv(subreq);
3478 TALLOC_FREE(subreq);
3479 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
3480 talloc_set_destructor(state, NULL);
3482 if (ret != EAGAIN) {
3483 tevent_req_error(req, ret);
3487 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
3488 * means the lower level pthreadpool failed to create a new
3489 * thread. Fallback to sync processing in that case to allow
3490 * some progress for the client.
3492 vfswrap_getxattrat_do_sync(req);
3496 if (state->xattr_size == -1) {
3497 tevent_req_error(req, state->vfs_aio_state.error);
3501 if (state->xattr_value == NULL) {
3503 * The caller only wanted the size.
3505 tevent_req_done(req);
3510 * shrink the buffer to the returned size.
3511 * (can't fail). It means NULL if size is 0.
3513 state->xattr_value = talloc_realloc(state,
3518 tevent_req_done(req);
3521 static ssize_t vfswrap_getxattrat_recv(struct tevent_req *req,
3522 struct vfs_aio_state *aio_state,
3523 TALLOC_CTX *mem_ctx,
3524 uint8_t **xattr_value)
3526 struct vfswrap_getxattrat_state *state = tevent_req_data(
3527 req, struct vfswrap_getxattrat_state);
3530 if (tevent_req_is_unix_error(req, &aio_state->error)) {
3531 tevent_req_received(req);
3535 *aio_state = state->vfs_aio_state;
3536 xattr_size = state->xattr_size;
3537 if (xattr_value != NULL) {
3538 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
3541 tevent_req_received(req);
3545 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
3547 return fgetxattr(fsp->fh->fd, name, value, size);
3550 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
3551 const struct smb_filename *smb_fname,
3555 return listxattr(smb_fname->base_name, list, size);
3558 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
3560 return flistxattr(fsp->fh->fd, list, size);
3563 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
3564 const struct smb_filename *smb_fname,
3567 return removexattr(smb_fname->base_name, name);
3570 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
3572 return fremovexattr(fsp->fh->fd, name);
3575 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
3576 const struct smb_filename *smb_fname,
3582 return setxattr(smb_fname->base_name, name, value, size, flags);
3585 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
3587 return fsetxattr(fsp->fh->fd, name, value, size, flags);
3590 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
3595 static bool vfswrap_is_offline(struct connection_struct *conn,
3596 const struct smb_filename *fname)
3600 bool offline = false;
3602 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
3606 if (!lp_dmapi_support(SNUM(conn)) || !dmapi_have_session()) {
3607 #if defined(ENOTSUP)
3613 status = get_full_smb_filename(talloc_tos(), fname, &path);
3614 if (!NT_STATUS_IS_OK(status)) {
3615 errno = map_errno_from_nt_status(status);
3619 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
3626 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
3627 struct files_struct *fsp,
3628 TALLOC_CTX *mem_ctx,
3631 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
3634 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
3635 struct files_struct *fsp,
3636 const DATA_BLOB old_cookie,
3637 TALLOC_CTX *mem_ctx,
3638 DATA_BLOB *new_cookie)
3640 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
3644 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
3645 struct smb_request *smb1req,
3646 struct smbXsrv_open *op,
3647 const DATA_BLOB old_cookie,
3648 TALLOC_CTX *mem_ctx,
3649 struct files_struct **fsp,
3650 DATA_BLOB *new_cookie)
3652 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
3653 old_cookie, mem_ctx,
3657 static struct vfs_fn_pointers vfs_default_fns = {
3658 /* Disk operations */
3660 .connect_fn = vfswrap_connect,
3661 .disconnect_fn = vfswrap_disconnect,
3662 .disk_free_fn = vfswrap_disk_free,
3663 .get_quota_fn = vfswrap_get_quota,
3664 .set_quota_fn = vfswrap_set_quota,
3665 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3666 .statvfs_fn = vfswrap_statvfs,
3667 .fs_capabilities_fn = vfswrap_fs_capabilities,
3668 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3669 .create_dfs_pathat_fn = vfswrap_create_dfs_pathat,
3670 .read_dfs_pathat_fn = vfswrap_read_dfs_pathat,
3671 .snap_check_path_fn = vfswrap_snap_check_path,
3672 .snap_create_fn = vfswrap_snap_create,
3673 .snap_delete_fn = vfswrap_snap_delete,
3675 /* Directory operations */
3677 .opendir_fn = vfswrap_opendir,
3678 .fdopendir_fn = vfswrap_fdopendir,
3679 .readdir_fn = vfswrap_readdir,
3680 .readdir_attr_fn = vfswrap_readdir_attr,
3681 .seekdir_fn = vfswrap_seekdir,
3682 .telldir_fn = vfswrap_telldir,
3683 .rewind_dir_fn = vfswrap_rewinddir,
3684 .mkdirat_fn = vfswrap_mkdirat,
3685 .closedir_fn = vfswrap_closedir,
3687 /* File operations */
3689 .open_fn = vfswrap_open,
3690 .create_file_fn = vfswrap_create_file,
3691 .close_fn = vfswrap_close,
3692 .pread_fn = vfswrap_pread,
3693 .pread_send_fn = vfswrap_pread_send,
3694 .pread_recv_fn = vfswrap_pread_recv,
3695 .pwrite_fn = vfswrap_pwrite,
3696 .pwrite_send_fn = vfswrap_pwrite_send,
3697 .pwrite_recv_fn = vfswrap_pwrite_recv,
3698 .lseek_fn = vfswrap_lseek,
3699 .sendfile_fn = vfswrap_sendfile,
3700 .recvfile_fn = vfswrap_recvfile,
3701 .renameat_fn = vfswrap_renameat,
3702 .fsync_send_fn = vfswrap_fsync_send,
3703 .fsync_recv_fn = vfswrap_fsync_recv,
3704 .stat_fn = vfswrap_stat,
3705 .fstat_fn = vfswrap_fstat,
3706 .lstat_fn = vfswrap_lstat,
3707 .get_alloc_size_fn = vfswrap_get_alloc_size,
3708 .unlinkat_fn = vfswrap_unlinkat,
3709 .chmod_fn = vfswrap_chmod,
3710 .fchmod_fn = vfswrap_fchmod,
3711 .fchown_fn = vfswrap_fchown,
3712 .lchown_fn = vfswrap_lchown,
3713 .chdir_fn = vfswrap_chdir,
3714 .getwd_fn = vfswrap_getwd,
3715 .ntimes_fn = vfswrap_ntimes,
3716 .ftruncate_fn = vfswrap_ftruncate,
3717 .fallocate_fn = vfswrap_fallocate,
3718 .lock_fn = vfswrap_lock,
3719 .kernel_flock_fn = vfswrap_kernel_flock,
3720 .fcntl_fn = vfswrap_fcntl,
3721 .linux_setlease_fn = vfswrap_linux_setlease,
3722 .getlock_fn = vfswrap_getlock,
3723 .symlinkat_fn = vfswrap_symlinkat,
3724 .readlinkat_fn = vfswrap_readlinkat,
3725 .linkat_fn = vfswrap_linkat,
3726 .mknodat_fn = vfswrap_mknodat,
3727 .realpath_fn = vfswrap_realpath,
3728 .chflags_fn = vfswrap_chflags,
3729 .file_id_create_fn = vfswrap_file_id_create,
3730 .fs_file_id_fn = vfswrap_fs_file_id,
3731 .streaminfo_fn = vfswrap_streaminfo,
3732 .get_real_filename_fn = vfswrap_get_real_filename,
3733 .connectpath_fn = vfswrap_connectpath,
3734 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
3735 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3736 .strict_lock_check_fn = vfswrap_strict_lock_check,
3737 .translate_name_fn = vfswrap_translate_name,
3738 .fsctl_fn = vfswrap_fsctl,
3739 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
3740 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
3741 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
3742 .get_dos_attributes_send_fn = vfswrap_get_dos_attributes_send,
3743 .get_dos_attributes_recv_fn = vfswrap_get_dos_attributes_recv,
3744 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
3745 .offload_read_send_fn = vfswrap_offload_read_send,
3746 .offload_read_recv_fn = vfswrap_offload_read_recv,
3747 .offload_write_send_fn = vfswrap_offload_write_send,
3748 .offload_write_recv_fn = vfswrap_offload_write_recv,
3749 .get_compression_fn = vfswrap_get_compression,
3750 .set_compression_fn = vfswrap_set_compression,
3752 /* NT ACL operations. */
3754 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
3755 .get_nt_acl_fn = vfswrap_get_nt_acl,
3756 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
3757 .audit_file_fn = vfswrap_audit_file,
3759 /* POSIX ACL operations. */
3761 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
3762 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3763 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
3764 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3765 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
3766 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3767 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
3769 /* EA operations. */
3770 .getxattr_fn = vfswrap_getxattr,
3771 .getxattrat_send_fn = vfswrap_getxattrat_send,
3772 .getxattrat_recv_fn = vfswrap_getxattrat_recv,
3773 .fgetxattr_fn = vfswrap_fgetxattr,
3774 .listxattr_fn = vfswrap_listxattr,
3775 .flistxattr_fn = vfswrap_flistxattr,
3776 .removexattr_fn = vfswrap_removexattr,
3777 .fremovexattr_fn = vfswrap_fremovexattr,
3778 .setxattr_fn = vfswrap_setxattr,
3779 .fsetxattr_fn = vfswrap_fsetxattr,
3781 /* aio operations */
3782 .aio_force_fn = vfswrap_aio_force,
3784 /* durable handle operations */
3785 .durable_cookie_fn = vfswrap_durable_cookie,
3786 .durable_disconnect_fn = vfswrap_durable_disconnect,
3787 .durable_reconnect_fn = vfswrap_durable_reconnect,
3791 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3794 * Here we need to implement every call!
3796 * As this is the end of the vfs module chain.
3798 smb_vfs_assert_all_fns(&vfs_default_fns, DEFAULT_VFS_MODULE_NAME);
3799 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3800 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);