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)
1018 static void vfs_pwrite_done(struct tevent_req *subreq)
1020 struct vfswrap_pwrite_state *state = tevent_req_callback_data(
1021 subreq, struct vfswrap_pwrite_state);
1022 struct tevent_req *req = state->req;
1025 ret = pthreadpool_tevent_job_recv(subreq);
1026 TALLOC_FREE(subreq);
1027 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1028 talloc_set_destructor(state, NULL);
1030 if (ret != EAGAIN) {
1031 tevent_req_error(req, ret);
1035 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1036 * means the lower level pthreadpool failed to create a new
1037 * thread. Fallback to sync processing in that case to allow
1038 * some progress for the client.
1040 vfs_pwrite_do(state);
1043 tevent_req_done(req);
1046 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
1047 struct vfs_aio_state *vfs_aio_state)
1049 struct vfswrap_pwrite_state *state = tevent_req_data(
1050 req, struct vfswrap_pwrite_state);
1052 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1056 *vfs_aio_state = state->vfs_aio_state;
1060 struct vfswrap_fsync_state {
1064 struct vfs_aio_state vfs_aio_state;
1065 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
1068 static void vfs_fsync_do(void *private_data);
1069 static void vfs_fsync_done(struct tevent_req *subreq);
1070 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state);
1072 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
1073 TALLOC_CTX *mem_ctx,
1074 struct tevent_context *ev,
1075 struct files_struct *fsp)
1077 struct tevent_req *req, *subreq;
1078 struct vfswrap_fsync_state *state;
1080 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
1086 state->fd = fsp->fh->fd;
1088 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_fsync, profile_p,
1089 state->profile_bytes, 0);
1090 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1092 subreq = pthreadpool_tevent_job_send(
1093 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
1094 if (tevent_req_nomem(subreq, req)) {
1095 return tevent_req_post(req, ev);
1097 tevent_req_set_callback(subreq, vfs_fsync_done, req);
1099 talloc_set_destructor(state, vfs_fsync_state_destructor);
1104 static void vfs_fsync_do(void *private_data)
1106 struct vfswrap_fsync_state *state = talloc_get_type_abort(
1107 private_data, struct vfswrap_fsync_state);
1108 struct timespec start_time;
1109 struct timespec end_time;
1111 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
1113 PROFILE_TIMESTAMP(&start_time);
1116 state->ret = fsync(state->fd);
1117 } while ((state->ret == -1) && (errno == EINTR));
1119 if (state->ret == -1) {
1120 state->vfs_aio_state.error = errno;
1123 PROFILE_TIMESTAMP(&end_time);
1125 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1127 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1130 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state)
1135 static void vfs_fsync_done(struct tevent_req *subreq)
1137 struct tevent_req *req = tevent_req_callback_data(
1138 subreq, struct tevent_req);
1139 struct vfswrap_fsync_state *state = tevent_req_data(
1140 req, struct vfswrap_fsync_state);
1143 ret = pthreadpool_tevent_job_recv(subreq);
1144 TALLOC_FREE(subreq);
1145 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1146 talloc_set_destructor(state, NULL);
1148 if (ret != EAGAIN) {
1149 tevent_req_error(req, ret);
1153 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1154 * means the lower level pthreadpool failed to create a new
1155 * thread. Fallback to sync processing in that case to allow
1156 * some progress for the client.
1158 vfs_fsync_do(state);
1161 tevent_req_done(req);
1164 static int vfswrap_fsync_recv(struct tevent_req *req,
1165 struct vfs_aio_state *vfs_aio_state)
1167 struct vfswrap_fsync_state *state = tevent_req_data(
1168 req, struct vfswrap_fsync_state);
1170 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1174 *vfs_aio_state = state->vfs_aio_state;
1178 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1182 START_PROFILE(syscall_lseek);
1184 result = lseek(fsp->fh->fd, offset, whence);
1186 * We want to maintain the fiction that we can seek
1187 * on a fifo for file system purposes. This allows
1188 * people to set up UNIX fifo's that feed data to Windows
1189 * applications. JRA.
1192 if((result == -1) && (errno == ESPIPE)) {
1197 END_PROFILE(syscall_lseek);
1201 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1202 off_t offset, size_t n)
1206 START_PROFILE_BYTES(syscall_sendfile, n);
1207 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
1208 END_PROFILE_BYTES(syscall_sendfile);
1212 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1214 files_struct *tofsp,
1220 START_PROFILE_BYTES(syscall_recvfile, n);
1221 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
1222 END_PROFILE_BYTES(syscall_recvfile);
1226 static int vfswrap_renameat(vfs_handle_struct *handle,
1227 files_struct *srcfsp,
1228 const struct smb_filename *smb_fname_src,
1229 files_struct *dstfsp,
1230 const struct smb_filename *smb_fname_dst)
1234 START_PROFILE(syscall_renameat);
1236 if (is_named_stream(smb_fname_src) || is_named_stream(smb_fname_dst)) {
1241 result = renameat(srcfsp->fh->fd,
1242 smb_fname_src->base_name,
1244 smb_fname_dst->base_name);
1247 END_PROFILE(syscall_renameat);
1251 static int vfswrap_stat(vfs_handle_struct *handle,
1252 struct smb_filename *smb_fname)
1256 START_PROFILE(syscall_stat);
1258 if (is_named_stream(smb_fname)) {
1263 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1264 lp_fake_directory_create_times(SNUM(handle->conn)));
1266 END_PROFILE(syscall_stat);
1270 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1274 START_PROFILE(syscall_fstat);
1275 result = sys_fstat(fsp->fh->fd,
1276 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1277 END_PROFILE(syscall_fstat);
1281 static int vfswrap_lstat(vfs_handle_struct *handle,
1282 struct smb_filename *smb_fname)
1286 START_PROFILE(syscall_lstat);
1288 if (is_named_stream(smb_fname)) {
1293 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1294 lp_fake_directory_create_times(SNUM(handle->conn)));
1296 END_PROFILE(syscall_lstat);
1300 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1302 enum vfs_translate_direction direction,
1303 TALLOC_CTX *mem_ctx,
1306 return NT_STATUS_NONE_MAPPED;
1310 * Implement the default fsctl operation.
1312 static bool vfswrap_logged_ioctl_message = false;
1314 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1315 struct files_struct *fsp,
1318 uint16_t req_flags, /* Needed for UNICODE ... */
1319 const uint8_t *_in_data,
1321 uint8_t **_out_data,
1322 uint32_t max_out_len,
1325 const char *in_data = (const char *)_in_data;
1326 char **out_data = (char **)_out_data;
1330 case FSCTL_SET_SPARSE:
1332 bool set_sparse = true;
1334 if (in_len >= 1 && in_data[0] == 0) {
1338 status = file_set_sparse(handle->conn, fsp, set_sparse);
1340 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1341 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1342 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1343 nt_errstr(status)));
1348 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1350 unsigned char objid[16];
1351 char *return_data = NULL;
1353 /* This should return the object-id on this file.
1354 * I think I'll make this be the inode+dev. JRA.
1357 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1358 fsp_fnum_dbg(fsp)));
1360 *out_len = MIN(max_out_len, 64);
1362 /* Hmmm, will this cause problems if less data asked for? */
1363 return_data = talloc_array(ctx, char, 64);
1364 if (return_data == NULL) {
1365 return NT_STATUS_NO_MEMORY;
1368 /* For backwards compatibility only store the dev/inode. */
1369 push_file_id_16(return_data, &fsp->file_id);
1370 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1371 push_file_id_16(return_data+32, &fsp->file_id);
1372 memset(return_data+48, 0, 16);
1373 *out_data = return_data;
1374 return NT_STATUS_OK;
1377 case FSCTL_GET_REPARSE_POINT:
1379 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1380 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1381 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1382 return NT_STATUS_NOT_A_REPARSE_POINT;
1385 case FSCTL_SET_REPARSE_POINT:
1387 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1388 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1389 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1390 return NT_STATUS_NOT_A_REPARSE_POINT;
1393 case FSCTL_GET_SHADOW_COPY_DATA:
1396 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1397 * and return their volume names. If max_data_count is 16, then it is just
1398 * asking for the number of volumes and length of the combined names.
1400 * pdata is the data allocated by our caller, but that uses
1401 * total_data_count (which is 0 in our case) rather than max_data_count.
1402 * Allocate the correct amount and return the pointer to let
1403 * it be deallocated when we return.
1405 struct shadow_copy_data *shadow_data = NULL;
1406 bool labels = False;
1407 uint32_t labels_data_count = 0;
1409 char *cur_pdata = NULL;
1411 if (max_out_len < 16) {
1412 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1414 return NT_STATUS_INVALID_PARAMETER;
1417 if (max_out_len > 16) {
1421 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1422 if (shadow_data == NULL) {
1423 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1424 return NT_STATUS_NO_MEMORY;
1428 * Call the VFS routine to actually do the work.
1430 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1433 /* broken module didn't set errno on error */
1434 status = NT_STATUS_UNSUCCESSFUL;
1436 status = map_nt_error_from_unix(errno);
1437 if (NT_STATUS_EQUAL(status,
1438 NT_STATUS_NOT_SUPPORTED)) {
1442 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1443 "connectpath %s, failed - %s.\n",
1444 fsp->conn->connectpath,
1445 nt_errstr(status)));
1446 TALLOC_FREE(shadow_data);
1450 labels_data_count = (shadow_data->num_volumes * 2 *
1451 sizeof(SHADOW_COPY_LABEL)) + 2;
1456 *out_len = 12 + labels_data_count;
1459 if (max_out_len < *out_len) {
1460 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1461 max_out_len, *out_len));
1462 TALLOC_FREE(shadow_data);
1463 return NT_STATUS_BUFFER_TOO_SMALL;
1466 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1467 if (cur_pdata == NULL) {
1468 TALLOC_FREE(shadow_data);
1469 return NT_STATUS_NO_MEMORY;
1472 *out_data = cur_pdata;
1474 /* num_volumes 4 bytes */
1475 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1478 /* num_labels 4 bytes */
1479 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1482 /* needed_data_count 4 bytes */
1483 SIVAL(cur_pdata, 8, labels_data_count);
1487 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1488 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1489 if (labels && shadow_data->labels) {
1490 for (i=0; i<shadow_data->num_volumes; i++) {
1492 status = srvstr_push(cur_pdata, req_flags,
1493 cur_pdata, shadow_data->labels[i],
1494 2 * sizeof(SHADOW_COPY_LABEL),
1495 STR_UNICODE|STR_TERMINATE, &len);
1496 if (!NT_STATUS_IS_OK(status)) {
1497 TALLOC_FREE(*out_data);
1498 TALLOC_FREE(shadow_data);
1501 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1502 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1506 TALLOC_FREE(shadow_data);
1508 return NT_STATUS_OK;
1511 case FSCTL_FIND_FILES_BY_SID:
1513 /* pretend this succeeded -
1515 * we have to send back a list with all files owned by this SID
1517 * but I have to check that --metze
1521 struct dom_sid_buf buf;
1525 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1526 fsp_fnum_dbg(fsp)));
1529 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1530 return NT_STATUS_INVALID_PARAMETER;
1533 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1535 /* unknown 4 bytes: this is not the length of the sid :-( */
1536 /*unknown = IVAL(pdata,0);*/
1538 ret = sid_parse(_in_data + 4, sid_len, &sid);
1540 return NT_STATUS_INVALID_PARAMETER;
1542 DEBUGADD(10, ("for SID: %s\n",
1543 dom_sid_str_buf(&sid, &buf)));
1545 if (!sid_to_uid(&sid, &uid)) {
1546 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1547 dom_sid_str_buf(&sid, &buf),
1548 (unsigned long)sid_len));
1552 /* we can take a look at the find source :-)
1554 * find ./ -uid $uid -name '*' is what we need here
1557 * and send 4bytes len and then NULL terminated unicode strings
1560 * but I don't know how to deal with the paged results
1561 * (maybe we can hang the result anywhere in the fsp struct)
1563 * but I don't know how to deal with the paged results
1564 * (maybe we can hang the result anywhere in the fsp struct)
1566 * we don't send all files at once
1567 * and at the next we should *not* start from the beginning,
1568 * so we have to cache the result
1573 /* this works for now... */
1574 return NT_STATUS_OK;
1577 case FSCTL_QUERY_ALLOCATED_RANGES:
1579 /* FIXME: This is just a dummy reply, telling that all of the
1580 * file is allocated. MKS cp needs that.
1581 * Adding the real allocated ranges via FIEMAP on Linux
1582 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1583 * this FSCTL correct for sparse files.
1585 uint64_t offset, length;
1586 char *out_data_tmp = NULL;
1589 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1591 return NT_STATUS_INVALID_PARAMETER;
1594 if (max_out_len < 16) {
1595 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1597 return NT_STATUS_INVALID_PARAMETER;
1600 offset = BVAL(in_data,0);
1601 length = BVAL(in_data,8);
1603 if (offset + length < offset) {
1604 /* No 64-bit integer wrap. */
1605 return NT_STATUS_INVALID_PARAMETER;
1608 /* Shouldn't this be SMB_VFS_STAT ... ? */
1609 status = vfs_stat_fsp(fsp);
1610 if (!NT_STATUS_IS_OK(status)) {
1615 out_data_tmp = talloc_array(ctx, char, *out_len);
1616 if (out_data_tmp == NULL) {
1617 DEBUG(10, ("unable to allocate memory for response\n"));
1618 return NT_STATUS_NO_MEMORY;
1621 if (offset > fsp->fsp_name->st.st_ex_size ||
1622 fsp->fsp_name->st.st_ex_size == 0 ||
1624 memset(out_data_tmp, 0, *out_len);
1626 uint64_t end = offset + length;
1627 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1628 SBVAL(out_data_tmp, 0, 0);
1629 SBVAL(out_data_tmp, 8, end);
1632 *out_data = out_data_tmp;
1634 return NT_STATUS_OK;
1637 case FSCTL_IS_VOLUME_DIRTY:
1639 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1640 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1642 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1643 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1645 return NT_STATUS_INVALID_PARAMETER;
1650 * Only print once ... unfortunately there could be lots of
1651 * different FSCTLs that are called.
1653 if (!vfswrap_logged_ioctl_message) {
1654 vfswrap_logged_ioctl_message = true;
1655 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1656 __func__, function));
1660 return NT_STATUS_NOT_SUPPORTED;
1663 static bool vfswrap_is_offline(struct connection_struct *conn,
1664 const struct smb_filename *fname);
1666 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1667 struct smb_filename *smb_fname,
1672 offline = vfswrap_is_offline(handle->conn, smb_fname);
1674 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1677 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1680 struct vfswrap_get_dos_attributes_state {
1681 struct vfs_aio_state aio_state;
1682 connection_struct *conn;
1683 TALLOC_CTX *mem_ctx;
1684 struct tevent_context *ev;
1685 files_struct *dir_fsp;
1686 struct smb_filename *smb_fname;
1691 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq);
1693 static struct tevent_req *vfswrap_get_dos_attributes_send(
1694 TALLOC_CTX *mem_ctx,
1695 struct tevent_context *ev,
1696 struct vfs_handle_struct *handle,
1697 files_struct *dir_fsp,
1698 struct smb_filename *smb_fname)
1700 struct tevent_req *req = NULL;
1701 struct tevent_req *subreq = NULL;
1702 struct vfswrap_get_dos_attributes_state *state = NULL;
1704 req = tevent_req_create(mem_ctx, &state,
1705 struct vfswrap_get_dos_attributes_state);
1710 *state = (struct vfswrap_get_dos_attributes_state) {
1711 .conn = dir_fsp->conn,
1715 .smb_fname = smb_fname,
1718 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1722 SAMBA_XATTR_DOS_ATTRIB,
1724 if (tevent_req_nomem(subreq, req)) {
1725 return tevent_req_post(req, ev);
1727 tevent_req_set_callback(subreq,
1728 vfswrap_get_dos_attributes_getxattr_done,
1734 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq)
1736 struct tevent_req *req =
1737 tevent_req_callback_data(subreq,
1739 struct vfswrap_get_dos_attributes_state *state =
1740 tevent_req_data(req,
1741 struct vfswrap_get_dos_attributes_state);
1743 DATA_BLOB blob = {0};
1745 char *tofree = NULL;
1746 char pathbuf[PATH_MAX+1];
1748 struct smb_filename smb_fname;
1752 xattr_size = SMB_VFS_GETXATTRAT_RECV(subreq,
1756 TALLOC_FREE(subreq);
1757 if (xattr_size == -1) {
1758 status = map_nt_error_from_unix(state->aio_state.error);
1760 if (state->as_root) {
1761 tevent_req_nterror(req, status);
1764 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1765 tevent_req_nterror(req, status);
1769 state->as_root = true;
1772 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1776 SAMBA_XATTR_DOS_ATTRIB,
1779 if (tevent_req_nomem(subreq, req)) {
1782 tevent_req_set_callback(subreq,
1783 vfswrap_get_dos_attributes_getxattr_done,
1788 blob.length = xattr_size;
1790 status = parse_dos_attribute_blob(state->smb_fname,
1793 if (!NT_STATUS_IS_OK(status)) {
1794 tevent_req_nterror(req, status);
1798 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
1799 state->smb_fname->base_name,
1804 if (pathlen == -1) {
1805 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1809 smb_fname = (struct smb_filename) {
1811 .st = state->smb_fname->st,
1812 .flags = state->smb_fname->flags,
1815 offline = vfswrap_is_offline(state->conn, &smb_fname);
1817 state->dosmode |= FILE_ATTRIBUTE_OFFLINE;
1819 TALLOC_FREE(tofree);
1821 tevent_req_done(req);
1825 static NTSTATUS vfswrap_get_dos_attributes_recv(struct tevent_req *req,
1826 struct vfs_aio_state *aio_state,
1829 struct vfswrap_get_dos_attributes_state *state =
1830 tevent_req_data(req,
1831 struct vfswrap_get_dos_attributes_state);
1834 if (tevent_req_is_nterror(req, &status)) {
1835 tevent_req_received(req);
1839 *aio_state = state->aio_state;
1840 *dosmode = state->dosmode;
1841 tevent_req_received(req);
1842 return NT_STATUS_OK;
1845 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1846 struct files_struct *fsp,
1851 offline = vfswrap_is_offline(handle->conn, fsp->fsp_name);
1853 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1856 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1859 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1860 const struct smb_filename *smb_fname,
1863 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1866 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1867 struct files_struct *fsp,
1870 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1873 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1875 struct vfswrap_offload_read_state {
1879 static struct tevent_req *vfswrap_offload_read_send(
1880 TALLOC_CTX *mem_ctx,
1881 struct tevent_context *ev,
1882 struct vfs_handle_struct *handle,
1883 struct files_struct *fsp,
1889 struct tevent_req *req = NULL;
1890 struct vfswrap_offload_read_state *state = NULL;
1893 req = tevent_req_create(mem_ctx, &state,
1894 struct vfswrap_offload_read_state);
1899 status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1900 &vfswrap_offload_ctx);
1901 if (tevent_req_nterror(req, status)) {
1902 return tevent_req_post(req, ev);
1905 if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1906 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1907 return tevent_req_post(req, ev);
1910 status = vfs_offload_token_create_blob(state, fsp, fsctl,
1912 if (tevent_req_nterror(req, status)) {
1913 return tevent_req_post(req, ev);
1916 status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1918 if (tevent_req_nterror(req, status)) {
1919 return tevent_req_post(req, ev);
1922 tevent_req_done(req);
1923 return tevent_req_post(req, ev);
1926 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
1927 struct vfs_handle_struct *handle,
1928 TALLOC_CTX *mem_ctx,
1931 struct vfswrap_offload_read_state *state = tevent_req_data(
1932 req, struct vfswrap_offload_read_state);
1935 if (tevent_req_is_nterror(req, &status)) {
1936 tevent_req_received(req);
1940 token->length = state->token.length;
1941 token->data = talloc_move(mem_ctx, &state->token.data);
1943 tevent_req_received(req);
1944 return NT_STATUS_OK;
1947 struct vfswrap_offload_write_state {
1949 bool read_lck_locked;
1950 bool write_lck_locked;
1952 struct tevent_context *src_ev;
1953 struct files_struct *src_fsp;
1955 struct tevent_context *dst_ev;
1956 struct files_struct *dst_fsp;
1960 size_t next_io_size;
1963 static void vfswrap_offload_write_cleanup(struct tevent_req *req,
1964 enum tevent_req_state req_state)
1966 struct vfswrap_offload_write_state *state = tevent_req_data(
1967 req, struct vfswrap_offload_write_state);
1970 if (state->dst_fsp == NULL) {
1974 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
1976 state->dst_fsp = NULL;
1979 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
1981 static struct tevent_req *vfswrap_offload_write_send(
1982 struct vfs_handle_struct *handle,
1983 TALLOC_CTX *mem_ctx,
1984 struct tevent_context *ev,
1987 off_t transfer_offset,
1988 struct files_struct *dest_fsp,
1992 struct tevent_req *req;
1993 struct vfswrap_offload_write_state *state = NULL;
1994 /* off_t is signed! */
1995 off_t max_offset = INT64_MAX - to_copy;
1996 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
1997 files_struct *src_fsp = NULL;
2001 req = tevent_req_create(mem_ctx, &state,
2002 struct vfswrap_offload_write_state);
2007 *state = (struct vfswrap_offload_write_state) {
2009 .src_off = transfer_offset,
2011 .dst_fsp = dest_fsp,
2012 .dst_off = dest_off,
2014 .remaining = to_copy,
2017 tevent_req_set_cleanup_fn(req, vfswrap_offload_write_cleanup);
2020 case FSCTL_SRV_COPYCHUNK:
2021 case FSCTL_SRV_COPYCHUNK_WRITE:
2024 case FSCTL_OFFLOAD_WRITE:
2025 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
2026 return tevent_req_post(req, ev);
2028 case FSCTL_DUP_EXTENTS_TO_FILE:
2029 DBG_DEBUG("COW clones not supported by vfs_default\n");
2030 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2031 return tevent_req_post(req, ev);
2034 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2035 return tevent_req_post(req, ev);
2039 * From here on we assume a copy-chunk fsctl
2043 tevent_req_done(req);
2044 return tevent_req_post(req, ev);
2047 if (state->src_off > max_offset) {
2049 * Protect integer checks below.
2051 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2052 return tevent_req_post(req, ev);
2054 if (state->src_off < 0) {
2056 * Protect integer checks below.
2058 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2059 return tevent_req_post(req, ev);
2061 if (state->dst_off > max_offset) {
2063 * Protect integer checks below.
2065 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2066 return tevent_req_post(req, ev);
2068 if (state->dst_off < 0) {
2070 * Protect integer checks below.
2072 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2073 return tevent_req_post(req, ev);
2076 status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
2078 if (tevent_req_nterror(req, status)) {
2079 return tevent_req_post(req, ev);
2082 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
2084 status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
2085 if (!NT_STATUS_IS_OK(status)) {
2086 tevent_req_nterror(req, status);
2087 return tevent_req_post(req, ev);
2090 ok = change_to_user_and_service_by_fsp(src_fsp);
2092 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2093 return tevent_req_post(req, ev);
2096 state->src_ev = src_fsp->conn->sconn->ev_ctx;
2097 state->src_fsp = src_fsp;
2099 status = vfs_stat_fsp(src_fsp);
2100 if (tevent_req_nterror(req, status)) {
2101 return tevent_req_post(req, ev);
2104 if (src_fsp->fsp_name->st.st_ex_size < state->src_off + to_copy) {
2106 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
2107 * If the SourceOffset or SourceOffset + Length extends beyond
2108 * the end of file, the server SHOULD<240> treat this as a
2109 * STATUS_END_OF_FILE error.
2111 * <240> Section 3.3.5.15.6: Windows servers will return
2112 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
2114 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
2115 return tevent_req_post(req, ev);
2118 state->buf = talloc_array(state, uint8_t, num);
2119 if (tevent_req_nomem(state->buf, req)) {
2120 return tevent_req_post(req, ev);
2123 status = vfswrap_offload_write_loop(req);
2124 if (!NT_STATUS_IS_OK(status)) {
2125 tevent_req_nterror(req, status);
2126 return tevent_req_post(req, ev);
2132 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
2134 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
2136 struct vfswrap_offload_write_state *state = tevent_req_data(
2137 req, struct vfswrap_offload_write_state);
2138 struct tevent_req *subreq = NULL;
2139 struct lock_struct read_lck;
2143 * This is called under the context of state->src_fsp.
2146 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
2148 init_strict_lock_struct(state->src_fsp,
2149 state->src_fsp->op->global->open_persistent_id,
2151 state->next_io_size,
2155 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
2159 return NT_STATUS_FILE_LOCK_CONFLICT;
2162 subreq = SMB_VFS_PREAD_SEND(state,
2166 state->next_io_size,
2168 if (subreq == NULL) {
2169 return NT_STATUS_NO_MEMORY;
2171 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
2173 return NT_STATUS_OK;
2176 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
2178 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
2180 struct tevent_req *req = tevent_req_callback_data(
2181 subreq, struct tevent_req);
2182 struct vfswrap_offload_write_state *state = tevent_req_data(
2183 req, struct vfswrap_offload_write_state);
2184 struct vfs_aio_state aio_state;
2185 struct lock_struct write_lck;
2189 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
2190 TALLOC_FREE(subreq);
2192 DBG_ERR("read failed: %s\n", strerror(aio_state.error));
2193 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2196 if (nread != state->next_io_size) {
2197 DBG_ERR("Short read, only %zd of %zu\n",
2198 nread, state->next_io_size);
2199 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2203 state->src_off += nread;
2205 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2207 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2211 init_strict_lock_struct(state->dst_fsp,
2212 state->dst_fsp->op->global->open_persistent_id,
2214 state->next_io_size,
2218 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
2222 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
2226 subreq = SMB_VFS_PWRITE_SEND(state,
2230 state->next_io_size,
2232 if (subreq == NULL) {
2233 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2236 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
2239 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
2241 struct tevent_req *req = tevent_req_callback_data(
2242 subreq, struct tevent_req);
2243 struct vfswrap_offload_write_state *state = tevent_req_data(
2244 req, struct vfswrap_offload_write_state);
2245 struct vfs_aio_state aio_state;
2250 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
2251 TALLOC_FREE(subreq);
2252 if (nwritten == -1) {
2253 DBG_ERR("write failed: %s\n", strerror(aio_state.error));
2254 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2257 if (nwritten != state->next_io_size) {
2258 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
2259 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2263 state->dst_off += nwritten;
2265 if (state->remaining < nwritten) {
2266 /* Paranoia check */
2267 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2270 state->remaining -= nwritten;
2271 if (state->remaining == 0) {
2272 tevent_req_done(req);
2276 ok = change_to_user_and_service_by_fsp(state->src_fsp);
2278 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2282 status = vfswrap_offload_write_loop(req);
2283 if (!NT_STATUS_IS_OK(status)) {
2284 tevent_req_nterror(req, status);
2291 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
2292 struct tevent_req *req,
2295 struct vfswrap_offload_write_state *state = tevent_req_data(
2296 req, struct vfswrap_offload_write_state);
2299 if (tevent_req_is_nterror(req, &status)) {
2300 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
2302 tevent_req_received(req);
2306 *copied = state->to_copy;
2307 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
2308 tevent_req_received(req);
2310 return NT_STATUS_OK;
2313 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
2314 TALLOC_CTX *mem_ctx,
2315 struct files_struct *fsp,
2316 struct smb_filename *smb_fname,
2317 uint16_t *_compression_fmt)
2319 return NT_STATUS_INVALID_DEVICE_REQUEST;
2322 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
2323 TALLOC_CTX *mem_ctx,
2324 struct files_struct *fsp,
2325 uint16_t compression_fmt)
2327 return NT_STATUS_INVALID_DEVICE_REQUEST;
2330 /********************************************************************
2331 Given a stat buffer return the allocated size on disk, taking into
2332 account sparse files.
2333 ********************************************************************/
2334 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
2335 struct files_struct *fsp,
2336 const SMB_STRUCT_STAT *sbuf)
2340 START_PROFILE(syscall_get_alloc_size);
2342 if(S_ISDIR(sbuf->st_ex_mode)) {
2347 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2348 /* The type of st_blocksize is blkcnt_t which *MUST* be
2349 signed (according to POSIX) and can be less than 64-bits.
2350 Ensure when we're converting to 64 bits wide we don't
2352 #if defined(SIZEOF_BLKCNT_T_8)
2353 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2354 #elif defined(SIZEOF_BLKCNT_T_4)
2356 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2357 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2360 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2364 * Some file systems do not allocate a block for very
2365 * small files. But for non-empty file should report a
2369 uint64_t filesize = get_file_size_stat(sbuf);
2371 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2375 result = get_file_size_stat(sbuf);
2378 if (fsp && fsp->initial_allocation_size)
2379 result = MAX(result,fsp->initial_allocation_size);
2381 result = smb_roundup(handle->conn, result);
2384 END_PROFILE(syscall_get_alloc_size);
2388 static int vfswrap_unlinkat(vfs_handle_struct *handle,
2389 struct files_struct *dirfsp,
2390 const struct smb_filename *smb_fname,
2395 START_PROFILE(syscall_unlinkat);
2397 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2399 if (is_named_stream(smb_fname)) {
2403 result = unlinkat(dirfsp->fh->fd,
2404 smb_fname->base_name,
2408 END_PROFILE(syscall_unlinkat);
2412 static int vfswrap_chmod(vfs_handle_struct *handle,
2413 const struct smb_filename *smb_fname,
2418 START_PROFILE(syscall_chmod);
2419 result = chmod(smb_fname->base_name, mode);
2420 END_PROFILE(syscall_chmod);
2424 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2428 START_PROFILE(syscall_fchmod);
2429 #if defined(HAVE_FCHMOD)
2430 result = fchmod(fsp->fh->fd, mode);
2436 END_PROFILE(syscall_fchmod);
2440 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2445 START_PROFILE(syscall_fchown);
2446 result = fchown(fsp->fh->fd, uid, gid);
2447 END_PROFILE(syscall_fchown);
2455 static int vfswrap_lchown(vfs_handle_struct *handle,
2456 const struct smb_filename *smb_fname,
2462 START_PROFILE(syscall_lchown);
2463 result = lchown(smb_fname->base_name, uid, gid);
2464 END_PROFILE(syscall_lchown);
2468 static int vfswrap_chdir(vfs_handle_struct *handle,
2469 const struct smb_filename *smb_fname)
2473 START_PROFILE(syscall_chdir);
2474 result = chdir(smb_fname->base_name);
2475 END_PROFILE(syscall_chdir);
2479 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2483 struct smb_filename *smb_fname = NULL;
2485 START_PROFILE(syscall_getwd);
2486 result = sys_getwd();
2487 END_PROFILE(syscall_getwd);
2489 if (result == NULL) {
2492 smb_fname = synthetic_smb_fname(ctx,
2498 * sys_getwd() *always* returns malloced memory.
2499 * We must free here to avoid leaks:
2500 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2506 /*********************************************************************
2507 nsec timestamp resolution call. Convert down to whatever the underlying
2508 system will support.
2509 **********************************************************************/
2511 static int vfswrap_ntimes(vfs_handle_struct *handle,
2512 const struct smb_filename *smb_fname,
2513 struct smb_file_time *ft)
2517 START_PROFILE(syscall_ntimes);
2519 if (is_named_stream(smb_fname)) {
2525 if (is_omit_timespec(&ft->atime)) {
2526 ft->atime= smb_fname->st.st_ex_atime;
2529 if (is_omit_timespec(&ft->mtime)) {
2530 ft->mtime = smb_fname->st.st_ex_mtime;
2533 if (!is_omit_timespec(&ft->create_time)) {
2534 set_create_timespec_ea(handle->conn,
2539 if ((timespec_compare(&ft->atime,
2540 &smb_fname->st.st_ex_atime) == 0) &&
2541 (timespec_compare(&ft->mtime,
2542 &smb_fname->st.st_ex_mtime) == 0)) {
2547 #if defined(HAVE_UTIMENSAT)
2549 struct timespec ts[2];
2552 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2554 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2556 if (!((result == -1) && (errno == ENOSYS))) {
2560 #if defined(HAVE_UTIMES)
2562 struct timeval tv[2];
2563 tv[0] = convert_timespec_to_timeval(ft->atime);
2564 tv[1] = convert_timespec_to_timeval(ft->mtime);
2565 result = utimes(smb_fname->base_name, tv);
2567 result = utimes(smb_fname->base_name, NULL);
2569 if (!((result == -1) && (errno == ENOSYS))) {
2573 #if defined(HAVE_UTIME)
2575 struct utimbuf times;
2576 times.actime = convert_timespec_to_time_t(ft->atime);
2577 times.modtime = convert_timespec_to_time_t(ft->mtime);
2578 result = utime(smb_fname->base_name, ×);
2580 result = utime(smb_fname->base_name, NULL);
2582 if (!((result == -1) && (errno == ENOSYS))) {
2590 END_PROFILE(syscall_ntimes);
2594 /*********************************************************************
2595 A version of ftruncate that will write the space on disk if strict
2597 **********************************************************************/
2599 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2601 off_t space_to_write;
2602 uint64_t space_avail;
2603 uint64_t bsize,dfree,dsize;
2606 SMB_STRUCT_STAT *pst;
2608 status = vfs_stat_fsp(fsp);
2609 if (!NT_STATUS_IS_OK(status)) {
2612 pst = &fsp->fsp_name->st;
2615 if (S_ISFIFO(pst->st_ex_mode))
2619 if (pst->st_ex_size == len)
2622 /* Shrink - just ftruncate. */
2623 if (pst->st_ex_size > len)
2624 return ftruncate(fsp->fh->fd, len);
2626 space_to_write = len - pst->st_ex_size;
2628 /* for allocation try fallocate first. This can fail on some
2629 platforms e.g. when the filesystem doesn't support it and no
2630 emulation is being done by the libc (like on AIX with JFS1). In that
2631 case we do our own emulation. fallocate implementations can
2632 return ENOTSUP or EINVAL in cases like that. */
2633 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2634 if (ret == -1 && errno == ENOSPC) {
2640 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2641 "error %d. Falling back to slow manual allocation\n", errno));
2643 /* available disk space is enough or not? */
2645 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2646 /* space_avail is 1k blocks */
2647 if (space_avail == (uint64_t)-1 ||
2648 ((uint64_t)space_to_write/1024 > space_avail) ) {
2653 /* Write out the real space on disk. */
2654 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2662 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2665 SMB_STRUCT_STAT *pst;
2669 START_PROFILE(syscall_ftruncate);
2671 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2672 result = strict_allocate_ftruncate(handle, fsp, len);
2673 END_PROFILE(syscall_ftruncate);
2677 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2678 ftruncate if the system supports it. Then I discovered that
2679 you can have some filesystems that support ftruncate
2680 expansion and some that don't! On Linux fat can't do
2681 ftruncate extend but ext2 can. */
2683 result = ftruncate(fsp->fh->fd, len);
2685 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2686 extend a file with ftruncate. Provide alternate implementation
2689 /* Do an fstat to see if the file is longer than the requested
2690 size in which case the ftruncate above should have
2691 succeeded or shorter, in which case seek to len - 1 and
2692 write 1 byte of zero */
2693 status = vfs_stat_fsp(fsp);
2694 if (!NT_STATUS_IS_OK(status)) {
2698 /* We need to update the files_struct after successful ftruncate */
2703 pst = &fsp->fsp_name->st;
2706 if (S_ISFIFO(pst->st_ex_mode)) {
2712 if (pst->st_ex_size == len) {
2717 if (pst->st_ex_size > len) {
2718 /* the ftruncate should have worked */
2722 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2730 END_PROFILE(syscall_ftruncate);
2734 static int vfswrap_fallocate(vfs_handle_struct *handle,
2742 START_PROFILE(syscall_fallocate);
2744 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2746 * posix_fallocate returns 0 on success, errno on error
2747 * and doesn't set errno. Make it behave like fallocate()
2748 * which returns -1, and sets errno on failure.
2755 /* sys_fallocate handles filtering of unsupported mode flags */
2756 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2758 END_PROFILE(syscall_fallocate);
2762 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2766 START_PROFILE(syscall_fcntl_lock);
2768 if (fsp->use_ofd_locks) {
2769 op = map_process_lock_to_ofd_lock(op);
2772 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2773 END_PROFILE(syscall_fcntl_lock);
2777 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2778 uint32_t share_access, uint32_t access_mask)
2780 START_PROFILE(syscall_kernel_flock);
2781 kernel_flock(fsp->fh->fd, share_access, access_mask);
2782 END_PROFILE(syscall_kernel_flock);
2786 static int vfswrap_fcntl(vfs_handle_struct *handle, files_struct *fsp, int cmd,
2790 va_list dup_cmd_arg;
2794 START_PROFILE(syscall_fcntl);
2796 va_copy(dup_cmd_arg, cmd_arg);
2802 #if defined(HAVE_OFD_LOCKS)
2807 #if defined(HAVE_F_OWNER_EX)
2811 #if defined(HAVE_RW_HINTS)
2814 case F_GET_FILE_RW_HINT:
2815 case F_SET_FILE_RW_HINT:
2817 argp = va_arg(dup_cmd_arg, void *);
2818 result = sys_fcntl_ptr(fsp->fh->fd, cmd, argp);
2821 val = va_arg(dup_cmd_arg, int);
2822 result = sys_fcntl_int(fsp->fh->fd, cmd, val);
2825 va_end(dup_cmd_arg);
2827 END_PROFILE(syscall_fcntl);
2831 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2836 START_PROFILE(syscall_fcntl_getlock);
2838 if (fsp->use_ofd_locks) {
2839 op = map_process_lock_to_ofd_lock(op);
2842 result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2843 END_PROFILE(syscall_fcntl_getlock);
2847 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2852 START_PROFILE(syscall_linux_setlease);
2854 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2855 result = linux_setlease(fsp->fh->fd, leasetype);
2859 END_PROFILE(syscall_linux_setlease);
2863 static int vfswrap_symlinkat(vfs_handle_struct *handle,
2864 const char *link_target,
2865 struct files_struct *dirfsp,
2866 const struct smb_filename *new_smb_fname)
2870 START_PROFILE(syscall_symlinkat);
2872 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2874 result = symlinkat(link_target,
2876 new_smb_fname->base_name);
2877 END_PROFILE(syscall_symlinkat);
2881 static int vfswrap_readlinkat(vfs_handle_struct *handle,
2882 files_struct *dirfsp,
2883 const struct smb_filename *smb_fname,
2889 START_PROFILE(syscall_readlinkat);
2891 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2893 result = readlinkat(dirfsp->fh->fd,
2894 smb_fname->base_name,
2898 END_PROFILE(syscall_readlinkat);
2902 static int vfswrap_linkat(vfs_handle_struct *handle,
2903 files_struct *srcfsp,
2904 const struct smb_filename *old_smb_fname,
2905 files_struct *dstfsp,
2906 const struct smb_filename *new_smb_fname,
2911 START_PROFILE(syscall_linkat);
2913 SMB_ASSERT(srcfsp == srcfsp->conn->cwd_fsp);
2914 SMB_ASSERT(dstfsp == dstfsp->conn->cwd_fsp);
2916 result = linkat(srcfsp->fh->fd,
2917 old_smb_fname->base_name,
2919 new_smb_fname->base_name,
2922 END_PROFILE(syscall_linkat);
2926 static int vfswrap_mknodat(vfs_handle_struct *handle,
2927 files_struct *dirfsp,
2928 const struct smb_filename *smb_fname,
2934 START_PROFILE(syscall_mknodat);
2936 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2938 result = sys_mknodat(dirfsp->fh->fd,
2939 smb_fname->base_name,
2943 END_PROFILE(syscall_mknodat);
2947 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2949 const struct smb_filename *smb_fname)
2952 struct smb_filename *result_fname = NULL;
2954 START_PROFILE(syscall_realpath);
2955 result = sys_realpath(smb_fname->base_name);
2956 END_PROFILE(syscall_realpath);
2958 result_fname = synthetic_smb_fname(ctx, result, NULL, NULL, 0);
2961 return result_fname;
2964 static int vfswrap_chflags(vfs_handle_struct *handle,
2965 const struct smb_filename *smb_fname,
2969 return chflags(smb_fname->base_name, flags);
2976 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2977 const SMB_STRUCT_STAT *sbuf)
2981 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2985 key.devid = sbuf->st_ex_dev;
2986 key.inode = sbuf->st_ex_ino;
2987 /* key.extid is unused by default. */
2992 static uint64_t vfswrap_fs_file_id(struct vfs_handle_struct *handle,
2993 const SMB_STRUCT_STAT *psbuf)
2997 if (!(psbuf->st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)) {
2998 return psbuf->st_ex_file_id;
3001 if (handle->conn->base_share_dev == psbuf->st_ex_dev) {
3002 return (uint64_t)psbuf->st_ex_ino;
3006 file_id = ((psbuf->st_ex_ino) & UINT32_MAX);
3009 file_id |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32;
3014 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
3015 struct files_struct *fsp,
3016 const struct smb_filename *smb_fname,
3017 TALLOC_CTX *mem_ctx,
3018 unsigned int *pnum_streams,
3019 struct stream_struct **pstreams)
3021 SMB_STRUCT_STAT sbuf;
3022 struct stream_struct *tmp_streams = NULL;
3025 if ((fsp != NULL) && (fsp->is_directory)) {
3027 * No default streams on directories
3032 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
3033 ret = SMB_VFS_FSTAT(fsp, &sbuf);
3036 struct smb_filename smb_fname_cp;
3038 ZERO_STRUCT(smb_fname_cp);
3039 smb_fname_cp.base_name = discard_const_p(char,
3040 smb_fname->base_name);
3041 smb_fname_cp.flags = smb_fname->flags;
3043 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
3044 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
3046 ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
3048 sbuf = smb_fname_cp.st;
3052 return map_nt_error_from_unix(errno);
3055 if (S_ISDIR(sbuf.st_ex_mode)) {
3059 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
3060 (*pnum_streams) + 1);
3061 if (tmp_streams == NULL) {
3062 return NT_STATUS_NO_MEMORY;
3064 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
3065 if (tmp_streams[*pnum_streams].name == NULL) {
3066 return NT_STATUS_NO_MEMORY;
3068 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
3069 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
3072 *pstreams = tmp_streams;
3074 return NT_STATUS_OK;
3077 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
3080 TALLOC_CTX *mem_ctx,
3084 * Don't fall back to get_real_filename so callers can differentiate
3085 * between a full directory scan and an actual case-insensitive stat.
3091 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
3092 const struct smb_filename *smb_fname)
3094 return handle->conn->connectpath;
3097 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
3098 struct byte_range_lock *br_lck,
3099 struct lock_struct *plock)
3101 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3103 /* Note: blr is not used in the default implementation. */
3104 return brl_lock_windows_default(br_lck, plock);
3107 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
3108 struct byte_range_lock *br_lck,
3109 const struct lock_struct *plock)
3111 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3113 return brl_unlock_windows_default(br_lck, plock);
3116 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
3118 struct lock_struct *plock)
3120 SMB_ASSERT(plock->lock_type == READ_LOCK ||
3121 plock->lock_type == WRITE_LOCK);
3123 return strict_lock_check_default(fsp, plock);
3126 /* NT ACL operations. */
3128 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
3130 uint32_t security_info,
3131 TALLOC_CTX *mem_ctx,
3132 struct security_descriptor **ppdesc)
3136 START_PROFILE(fget_nt_acl);
3137 result = posix_fget_nt_acl(fsp, security_info,
3139 END_PROFILE(fget_nt_acl);
3143 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
3144 const struct smb_filename *smb_fname,
3145 uint32_t security_info,
3146 TALLOC_CTX *mem_ctx,
3147 struct security_descriptor **ppdesc)
3151 START_PROFILE(get_nt_acl);
3152 result = posix_get_nt_acl(handle->conn,
3157 END_PROFILE(get_nt_acl);
3161 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
3165 START_PROFILE(fset_nt_acl);
3166 result = set_nt_acl(fsp, security_info_sent, psd);
3167 END_PROFILE(fset_nt_acl);
3171 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
3172 struct smb_filename *file,
3173 struct security_acl *sacl,
3174 uint32_t access_requested,
3175 uint32_t access_denied)
3177 return NT_STATUS_OK; /* Nothing to do here ... */
3180 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
3181 const struct smb_filename *smb_fname,
3182 SMB_ACL_TYPE_T type,
3183 TALLOC_CTX *mem_ctx)
3185 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
3188 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
3190 TALLOC_CTX *mem_ctx)
3192 return sys_acl_get_fd(handle, fsp, mem_ctx);
3195 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
3196 const struct smb_filename *smb_fname,
3197 SMB_ACL_TYPE_T acltype,
3200 return sys_acl_set_file(handle, smb_fname, acltype, theacl);
3203 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
3205 return sys_acl_set_fd(handle, fsp, theacl);
3208 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
3209 const struct smb_filename *smb_fname)
3211 return sys_acl_delete_def_file(handle, smb_fname);
3214 /****************************************************************
3215 Extended attribute operations.
3216 *****************************************************************/
3218 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
3219 const struct smb_filename *smb_fname,
3224 return getxattr(smb_fname->base_name, name, value, size);
3227 struct vfswrap_getxattrat_state {
3228 struct tevent_context *ev;
3229 files_struct *dir_fsp;
3230 const struct smb_filename *smb_fname;
3231 struct tevent_req *req;
3234 * The following variables are talloced off "state" which is protected
3235 * by a destructor and thus are guaranteed to be safe to be used in the
3236 * job function in the worker thread.
3239 const char *xattr_name;
3240 uint8_t *xattr_value;
3241 struct security_unix_token *token;
3244 struct vfs_aio_state vfs_aio_state;
3245 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
3248 static int vfswrap_getxattrat_state_destructor(
3249 struct vfswrap_getxattrat_state *state)
3254 static void vfswrap_getxattrat_do_sync(struct tevent_req *req);
3255 static void vfswrap_getxattrat_do_async(void *private_data);
3256 static void vfswrap_getxattrat_done(struct tevent_req *subreq);
3258 static struct tevent_req *vfswrap_getxattrat_send(
3259 TALLOC_CTX *mem_ctx,
3260 struct tevent_context *ev,
3261 struct vfs_handle_struct *handle,
3262 files_struct *dir_fsp,
3263 const struct smb_filename *smb_fname,
3264 const char *xattr_name,
3267 struct tevent_req *req = NULL;
3268 struct tevent_req *subreq = NULL;
3269 struct vfswrap_getxattrat_state *state = NULL;
3270 size_t max_threads = 0;
3271 bool have_per_thread_cwd = false;
3272 bool have_per_thread_creds = false;
3273 bool do_async = false;
3275 req = tevent_req_create(mem_ctx, &state,
3276 struct vfswrap_getxattrat_state);
3280 *state = (struct vfswrap_getxattrat_state) {
3283 .smb_fname = smb_fname,
3287 max_threads = pthreadpool_tevent_max_threads(dir_fsp->conn->sconn->pool);
3288 if (max_threads >= 1) {
3290 * We need a non sync threadpool!
3292 have_per_thread_cwd = per_thread_cwd_supported();
3294 #ifdef HAVE_LINUX_THREAD_CREDENTIALS
3295 have_per_thread_creds = true;
3297 if (have_per_thread_cwd && have_per_thread_creds) {
3301 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat, profile_p,
3302 state->profile_bytes, 0);
3304 if (dir_fsp->fh->fd == -1) {
3305 DBG_ERR("Need a valid directory fd\n");
3306 tevent_req_error(req, EINVAL);
3307 return tevent_req_post(req, ev);
3310 if (alloc_hint > 0) {
3311 state->xattr_value = talloc_zero_array(state,
3314 if (tevent_req_nomem(state->xattr_value, req)) {
3315 return tevent_req_post(req, ev);
3320 vfswrap_getxattrat_do_sync(req);
3321 return tevent_req_post(req, ev);
3325 * Now allocate all parameters from a memory context that won't go away
3326 * no matter what. These paremeters will get used in threads and we
3327 * can't reliably cancel threads, so all buffers passed to the threads
3328 * must not be freed before all referencing threads terminate.
3331 state->name = talloc_strdup(state, smb_fname->base_name);
3332 if (tevent_req_nomem(state->name, req)) {
3333 return tevent_req_post(req, ev);
3336 state->xattr_name = talloc_strdup(state, xattr_name);
3337 if (tevent_req_nomem(state->xattr_name, req)) {
3338 return tevent_req_post(req, ev);
3342 * This is a hot codepath so at first glance one might think we should
3343 * somehow optimize away the token allocation and do a
3344 * talloc_reference() or similar black magic instead. But due to the
3345 * talloc_stackframe pool per SMB2 request this should be a simple copy
3346 * without a malloc in most cases.
3348 if (geteuid() == sec_initial_uid()) {
3349 state->token = root_unix_token(state);
3351 state->token = copy_unix_token(
3353 dir_fsp->conn->session_info->unix_token);
3355 if (tevent_req_nomem(state->token, req)) {
3356 return tevent_req_post(req, ev);
3359 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3361 subreq = pthreadpool_tevent_job_send(
3364 dir_fsp->conn->sconn->pool,
3365 vfswrap_getxattrat_do_async,
3367 if (tevent_req_nomem(subreq, req)) {
3368 return tevent_req_post(req, ev);
3370 tevent_req_set_callback(subreq, vfswrap_getxattrat_done, req);
3372 talloc_set_destructor(state, vfswrap_getxattrat_state_destructor);
3377 static void vfswrap_getxattrat_do_sync(struct tevent_req *req)
3379 struct vfswrap_getxattrat_state *state = tevent_req_data(
3380 req, struct vfswrap_getxattrat_state);
3382 char *tofree = NULL;
3383 char pathbuf[PATH_MAX+1];
3387 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
3388 state->smb_fname->base_name,
3393 if (pathlen == -1) {
3394 tevent_req_error(req, ENOMEM);
3398 state->xattr_size = getxattr(path,
3401 talloc_array_length(state->xattr_value));
3403 TALLOC_FREE(tofree);
3404 if (state->xattr_size == -1) {
3405 tevent_req_error(req, err);
3409 tevent_req_done(req);
3413 static void vfswrap_getxattrat_do_async(void *private_data)
3415 struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3416 private_data, struct vfswrap_getxattrat_state);
3417 struct timespec start_time;
3418 struct timespec end_time;
3421 PROFILE_TIMESTAMP(&start_time);
3422 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
3425 * Here we simulate a getxattrat()
3426 * call using fchdir();getxattr()
3429 per_thread_cwd_activate();
3431 /* Become the correct credential on this thread. */
3432 ret = set_thread_credentials(state->token->uid,
3434 (size_t)state->token->ngroups,
3435 state->token->groups);
3437 state->xattr_size = -1;
3438 state->vfs_aio_state.error = errno;
3442 ret = fchdir(state->dir_fsp->fh->fd);
3444 state->xattr_size = -1;
3445 state->vfs_aio_state.error = errno;
3449 state->xattr_size = getxattr(state->name,
3452 talloc_array_length(state->xattr_value));
3453 if (state->xattr_size == -1) {
3454 state->vfs_aio_state.error = errno;
3458 PROFILE_TIMESTAMP(&end_time);
3459 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
3460 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3463 static void vfswrap_getxattrat_done(struct tevent_req *subreq)
3465 struct tevent_req *req = tevent_req_callback_data(
3466 subreq, struct tevent_req);
3467 struct vfswrap_getxattrat_state *state = tevent_req_data(
3468 req, struct vfswrap_getxattrat_state);
3473 * Make sure we run as the user again
3475 ok = change_to_user_and_service_by_fsp(state->dir_fsp);
3478 ret = pthreadpool_tevent_job_recv(subreq);
3479 TALLOC_FREE(subreq);
3480 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
3481 talloc_set_destructor(state, NULL);
3483 if (ret != EAGAIN) {
3484 tevent_req_error(req, ret);
3488 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
3489 * means the lower level pthreadpool failed to create a new
3490 * thread. Fallback to sync processing in that case to allow
3491 * some progress for the client.
3493 vfswrap_getxattrat_do_sync(req);
3497 if (state->xattr_size == -1) {
3498 tevent_req_error(req, state->vfs_aio_state.error);
3502 if (state->xattr_value == NULL) {
3504 * The caller only wanted the size.
3506 tevent_req_done(req);
3511 * shrink the buffer to the returned size.
3512 * (can't fail). It means NULL if size is 0.
3514 state->xattr_value = talloc_realloc(state,
3519 tevent_req_done(req);
3522 static ssize_t vfswrap_getxattrat_recv(struct tevent_req *req,
3523 struct vfs_aio_state *aio_state,
3524 TALLOC_CTX *mem_ctx,
3525 uint8_t **xattr_value)
3527 struct vfswrap_getxattrat_state *state = tevent_req_data(
3528 req, struct vfswrap_getxattrat_state);
3531 if (tevent_req_is_unix_error(req, &aio_state->error)) {
3532 tevent_req_received(req);
3536 *aio_state = state->vfs_aio_state;
3537 xattr_size = state->xattr_size;
3538 if (xattr_value != NULL) {
3539 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
3542 tevent_req_received(req);
3546 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
3548 return fgetxattr(fsp->fh->fd, name, value, size);
3551 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
3552 const struct smb_filename *smb_fname,
3556 return listxattr(smb_fname->base_name, list, size);
3559 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
3561 return flistxattr(fsp->fh->fd, list, size);
3564 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
3565 const struct smb_filename *smb_fname,
3568 return removexattr(smb_fname->base_name, name);
3571 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
3573 return fremovexattr(fsp->fh->fd, name);
3576 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
3577 const struct smb_filename *smb_fname,
3583 return setxattr(smb_fname->base_name, name, value, size, flags);
3586 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
3588 return fsetxattr(fsp->fh->fd, name, value, size, flags);
3591 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
3596 static bool vfswrap_is_offline(struct connection_struct *conn,
3597 const struct smb_filename *fname)
3601 bool offline = false;
3603 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
3607 if (!lp_dmapi_support(SNUM(conn)) || !dmapi_have_session()) {
3608 #if defined(ENOTSUP)
3614 status = get_full_smb_filename(talloc_tos(), fname, &path);
3615 if (!NT_STATUS_IS_OK(status)) {
3616 errno = map_errno_from_nt_status(status);
3620 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
3627 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
3628 struct files_struct *fsp,
3629 TALLOC_CTX *mem_ctx,
3632 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
3635 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
3636 struct files_struct *fsp,
3637 const DATA_BLOB old_cookie,
3638 TALLOC_CTX *mem_ctx,
3639 DATA_BLOB *new_cookie)
3641 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
3645 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
3646 struct smb_request *smb1req,
3647 struct smbXsrv_open *op,
3648 const DATA_BLOB old_cookie,
3649 TALLOC_CTX *mem_ctx,
3650 struct files_struct **fsp,
3651 DATA_BLOB *new_cookie)
3653 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
3654 old_cookie, mem_ctx,
3658 static struct vfs_fn_pointers vfs_default_fns = {
3659 /* Disk operations */
3661 .connect_fn = vfswrap_connect,
3662 .disconnect_fn = vfswrap_disconnect,
3663 .disk_free_fn = vfswrap_disk_free,
3664 .get_quota_fn = vfswrap_get_quota,
3665 .set_quota_fn = vfswrap_set_quota,
3666 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3667 .statvfs_fn = vfswrap_statvfs,
3668 .fs_capabilities_fn = vfswrap_fs_capabilities,
3669 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3670 .create_dfs_pathat_fn = vfswrap_create_dfs_pathat,
3671 .read_dfs_pathat_fn = vfswrap_read_dfs_pathat,
3672 .snap_check_path_fn = vfswrap_snap_check_path,
3673 .snap_create_fn = vfswrap_snap_create,
3674 .snap_delete_fn = vfswrap_snap_delete,
3676 /* Directory operations */
3678 .opendir_fn = vfswrap_opendir,
3679 .fdopendir_fn = vfswrap_fdopendir,
3680 .readdir_fn = vfswrap_readdir,
3681 .readdir_attr_fn = vfswrap_readdir_attr,
3682 .seekdir_fn = vfswrap_seekdir,
3683 .telldir_fn = vfswrap_telldir,
3684 .rewind_dir_fn = vfswrap_rewinddir,
3685 .mkdirat_fn = vfswrap_mkdirat,
3686 .closedir_fn = vfswrap_closedir,
3688 /* File operations */
3690 .open_fn = vfswrap_open,
3691 .create_file_fn = vfswrap_create_file,
3692 .close_fn = vfswrap_close,
3693 .pread_fn = vfswrap_pread,
3694 .pread_send_fn = vfswrap_pread_send,
3695 .pread_recv_fn = vfswrap_pread_recv,
3696 .pwrite_fn = vfswrap_pwrite,
3697 .pwrite_send_fn = vfswrap_pwrite_send,
3698 .pwrite_recv_fn = vfswrap_pwrite_recv,
3699 .lseek_fn = vfswrap_lseek,
3700 .sendfile_fn = vfswrap_sendfile,
3701 .recvfile_fn = vfswrap_recvfile,
3702 .renameat_fn = vfswrap_renameat,
3703 .fsync_send_fn = vfswrap_fsync_send,
3704 .fsync_recv_fn = vfswrap_fsync_recv,
3705 .stat_fn = vfswrap_stat,
3706 .fstat_fn = vfswrap_fstat,
3707 .lstat_fn = vfswrap_lstat,
3708 .get_alloc_size_fn = vfswrap_get_alloc_size,
3709 .unlinkat_fn = vfswrap_unlinkat,
3710 .chmod_fn = vfswrap_chmod,
3711 .fchmod_fn = vfswrap_fchmod,
3712 .fchown_fn = vfswrap_fchown,
3713 .lchown_fn = vfswrap_lchown,
3714 .chdir_fn = vfswrap_chdir,
3715 .getwd_fn = vfswrap_getwd,
3716 .ntimes_fn = vfswrap_ntimes,
3717 .ftruncate_fn = vfswrap_ftruncate,
3718 .fallocate_fn = vfswrap_fallocate,
3719 .lock_fn = vfswrap_lock,
3720 .kernel_flock_fn = vfswrap_kernel_flock,
3721 .fcntl_fn = vfswrap_fcntl,
3722 .linux_setlease_fn = vfswrap_linux_setlease,
3723 .getlock_fn = vfswrap_getlock,
3724 .symlinkat_fn = vfswrap_symlinkat,
3725 .readlinkat_fn = vfswrap_readlinkat,
3726 .linkat_fn = vfswrap_linkat,
3727 .mknodat_fn = vfswrap_mknodat,
3728 .realpath_fn = vfswrap_realpath,
3729 .chflags_fn = vfswrap_chflags,
3730 .file_id_create_fn = vfswrap_file_id_create,
3731 .fs_file_id_fn = vfswrap_fs_file_id,
3732 .streaminfo_fn = vfswrap_streaminfo,
3733 .get_real_filename_fn = vfswrap_get_real_filename,
3734 .connectpath_fn = vfswrap_connectpath,
3735 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
3736 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3737 .strict_lock_check_fn = vfswrap_strict_lock_check,
3738 .translate_name_fn = vfswrap_translate_name,
3739 .fsctl_fn = vfswrap_fsctl,
3740 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
3741 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
3742 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
3743 .get_dos_attributes_send_fn = vfswrap_get_dos_attributes_send,
3744 .get_dos_attributes_recv_fn = vfswrap_get_dos_attributes_recv,
3745 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
3746 .offload_read_send_fn = vfswrap_offload_read_send,
3747 .offload_read_recv_fn = vfswrap_offload_read_recv,
3748 .offload_write_send_fn = vfswrap_offload_write_send,
3749 .offload_write_recv_fn = vfswrap_offload_write_recv,
3750 .get_compression_fn = vfswrap_get_compression,
3751 .set_compression_fn = vfswrap_set_compression,
3753 /* NT ACL operations. */
3755 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
3756 .get_nt_acl_fn = vfswrap_get_nt_acl,
3757 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
3758 .audit_file_fn = vfswrap_audit_file,
3760 /* POSIX ACL operations. */
3762 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
3763 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3764 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
3765 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3766 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
3767 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3768 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
3770 /* EA operations. */
3771 .getxattr_fn = vfswrap_getxattr,
3772 .getxattrat_send_fn = vfswrap_getxattrat_send,
3773 .getxattrat_recv_fn = vfswrap_getxattrat_recv,
3774 .fgetxattr_fn = vfswrap_fgetxattr,
3775 .listxattr_fn = vfswrap_listxattr,
3776 .flistxattr_fn = vfswrap_flistxattr,
3777 .removexattr_fn = vfswrap_removexattr,
3778 .fremovexattr_fn = vfswrap_fremovexattr,
3779 .setxattr_fn = vfswrap_setxattr,
3780 .fsetxattr_fn = vfswrap_fsetxattr,
3782 /* aio operations */
3783 .aio_force_fn = vfswrap_aio_force,
3785 /* durable handle operations */
3786 .durable_cookie_fn = vfswrap_durable_cookie,
3787 .durable_disconnect_fn = vfswrap_durable_disconnect,
3788 .durable_reconnect_fn = vfswrap_durable_reconnect,
3792 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3795 * Here we need to implement every call!
3797 * As this is the end of the vfs module chain.
3799 smb_vfs_assert_all_fns(&vfs_default_fns, DEFAULT_VFS_MODULE_NAME);
3800 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3801 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);