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 connection_struct *conn = handle->conn;
127 uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
128 struct smb_filename *smb_fname_cpath = NULL;
129 struct vfs_statvfs_struct statbuf;
132 smb_fname_cpath = synthetic_smb_fname(talloc_tos(), conn->connectpath,
134 if (smb_fname_cpath == NULL) {
138 ZERO_STRUCT(statbuf);
139 ret = SMB_VFS_STATVFS(conn, smb_fname_cpath, &statbuf);
141 caps = statbuf.FsCapabilities;
144 *p_ts_res = TIMESTAMP_SET_SECONDS;
146 /* Work out what timestamp resolution we can
147 * use when setting a timestamp. */
149 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
151 TALLOC_FREE(smb_fname_cpath);
155 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
156 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
157 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
158 /* If any of the normal UNIX directory timestamps
159 * have a non-zero tv_nsec component assume
160 * we might be able to set sub-second timestamps.
161 * See what filetime set primitives we have.
163 #if defined(HAVE_UTIMENSAT)
164 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
165 #elif defined(HAVE_UTIMES)
166 /* utimes allows msec timestamps to be set. */
167 *p_ts_res = TIMESTAMP_SET_MSEC;
168 #elif defined(HAVE_UTIME)
169 /* utime only allows sec timestamps to be set. */
170 *p_ts_res = TIMESTAMP_SET_SECONDS;
173 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
175 "available on share %s, directory %s\n",
176 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
177 lp_servicename(talloc_tos(), conn->params->service),
178 conn->connectpath ));
180 TALLOC_FREE(smb_fname_cpath);
184 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
185 struct dfs_GetDFSReferral *r)
187 struct junction_map *junction = NULL;
189 bool self_referral = false;
190 char *pathnamep = NULL;
191 char *local_dfs_path = NULL;
194 uint16_t max_referral_level = r->in.req.max_referral_level;
197 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
200 /* get the junction entry */
201 if (r->in.req.servername == NULL) {
202 return NT_STATUS_NOT_FOUND;
206 * Trim pathname sent by client so it begins with only one backslash.
207 * Two backslashes confuse some dfs clients
210 local_dfs_path = talloc_strdup(r, r->in.req.servername);
211 if (local_dfs_path == NULL) {
212 return NT_STATUS_NO_MEMORY;
214 pathnamep = local_dfs_path;
215 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
216 IS_DIRECTORY_SEP(pathnamep[1])) {
220 junction = talloc_zero(r, struct junction_map);
221 if (junction == NULL) {
222 return NT_STATUS_NO_MEMORY;
225 /* The following call can change cwd. */
226 status = get_referred_path(r, pathnamep,
227 handle->conn->sconn->remote_address,
228 handle->conn->sconn->local_address,
229 !handle->conn->sconn->using_smb2,
230 junction, &consumedcnt, &self_referral);
231 if (!NT_STATUS_IS_OK(status)) {
232 struct smb_filename connectpath_fname = {
233 .base_name = handle->conn->connectpath
235 vfs_ChDir(handle->conn, &connectpath_fname);
239 struct smb_filename connectpath_fname = {
240 .base_name = handle->conn->connectpath
242 vfs_ChDir(handle->conn, &connectpath_fname);
245 if (!self_referral) {
246 pathnamep[consumedcnt] = '\0';
249 dbgtext("Path %s to alternate path(s):",
251 for (i=0; i < junction->referral_count; i++) {
253 junction->referral_list[i].alternate_path);
259 if (r->in.req.max_referral_level <= 2) {
260 max_referral_level = 2;
262 if (r->in.req.max_referral_level >= 3) {
263 max_referral_level = 3;
266 r->out.resp = talloc_zero(r, struct dfs_referral_resp);
267 if (r->out.resp == NULL) {
268 return NT_STATUS_NO_MEMORY;
271 r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
272 r->out.resp->nb_referrals = junction->referral_count;
274 r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
276 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
279 r->out.resp->referral_entries = talloc_zero_array(r,
280 struct dfs_referral_type,
281 r->out.resp->nb_referrals);
282 if (r->out.resp->referral_entries == NULL) {
283 return NT_STATUS_NO_MEMORY;
286 switch (max_referral_level) {
288 for(i=0; i < junction->referral_count; i++) {
289 struct referral *ref = &junction->referral_list[i];
290 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
291 struct dfs_referral_type *t =
292 &r->out.resp->referral_entries[i];
293 struct dfs_referral_v2 *v2 = &t->referral.v2;
296 v2->size = VERSION2_REFERRAL_SIZE;
298 v2->server_type = DFS_SERVER_ROOT;
300 v2->server_type = DFS_SERVER_NON_ROOT;
303 v2->proximity = ref->proximity;
305 v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
306 if (v2->DFS_path == NULL) {
307 return NT_STATUS_NO_MEMORY;
309 v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
310 if (v2->DFS_alt_path == NULL) {
311 return NT_STATUS_NO_MEMORY;
313 v2->netw_address = talloc_strdup(mem_ctx,
314 ref->alternate_path);
315 if (v2->netw_address == NULL) {
316 return NT_STATUS_NO_MEMORY;
322 for(i=0; i < junction->referral_count; i++) {
323 struct referral *ref = &junction->referral_list[i];
324 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
325 struct dfs_referral_type *t =
326 &r->out.resp->referral_entries[i];
327 struct dfs_referral_v3 *v3 = &t->referral.v3;
328 struct dfs_normal_referral *r1 = &v3->referrals.r1;
331 v3->size = VERSION3_REFERRAL_SIZE;
333 v3->server_type = DFS_SERVER_ROOT;
335 v3->server_type = DFS_SERVER_NON_ROOT;
339 r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
340 if (r1->DFS_path == NULL) {
341 return NT_STATUS_NO_MEMORY;
343 r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
344 if (r1->DFS_alt_path == NULL) {
345 return NT_STATUS_NO_MEMORY;
347 r1->netw_address = talloc_strdup(mem_ctx,
348 ref->alternate_path);
349 if (r1->netw_address == NULL) {
350 return NT_STATUS_NO_MEMORY;
355 DEBUG(0,("Invalid dfs referral version: %d\n",
356 max_referral_level));
357 return NT_STATUS_INVALID_LEVEL;
361 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
367 static NTSTATUS vfswrap_snap_check_path(struct vfs_handle_struct *handle,
369 const char *service_path,
372 return NT_STATUS_NOT_SUPPORTED;
375 static NTSTATUS vfswrap_snap_create(struct vfs_handle_struct *handle,
377 const char *base_volume,
383 return NT_STATUS_NOT_SUPPORTED;
386 static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle,
391 return NT_STATUS_NOT_SUPPORTED;
394 /* Directory operations */
396 static DIR *vfswrap_opendir(vfs_handle_struct *handle,
397 const struct smb_filename *smb_fname,
403 START_PROFILE(syscall_opendir);
404 result = opendir(smb_fname->base_name);
405 END_PROFILE(syscall_opendir);
409 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
416 START_PROFILE(syscall_fdopendir);
417 result = sys_fdopendir(fsp->fh->fd);
418 END_PROFILE(syscall_fdopendir);
423 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
425 SMB_STRUCT_STAT *sbuf)
427 struct dirent *result;
429 START_PROFILE(syscall_readdir);
430 result = readdir(dirp);
431 END_PROFILE(syscall_readdir);
433 /* Default Posix readdir() does not give us stat info.
434 * Set to invalid to indicate we didn't return this info. */
435 SET_STAT_INVALID(*sbuf);
436 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
437 if (result != NULL) {
438 /* See if we can efficiently return this. */
440 int flags = AT_SYMLINK_NOFOLLOW;
441 int ret = fstatat(dirfd(dirp),
446 * As this is an optimization,
447 * ignore it if we stat'ed a
448 * symlink. Make the caller
449 * do it again as we don't
450 * know if they wanted the link
451 * info, or its target info.
453 if ((ret == 0) && (!S_ISLNK(st.st_mode))) {
454 init_stat_ex_from_stat(sbuf,
456 lp_fake_directory_create_times(
457 SNUM(handle->conn)));
465 static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
466 const struct smb_filename *fname,
468 struct readdir_attr_data **attr_data)
470 return NT_STATUS_NOT_SUPPORTED;
473 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
475 START_PROFILE(syscall_seekdir);
476 seekdir(dirp, offset);
477 END_PROFILE(syscall_seekdir);
480 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
483 START_PROFILE(syscall_telldir);
484 result = telldir(dirp);
485 END_PROFILE(syscall_telldir);
489 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
491 START_PROFILE(syscall_rewinddir);
493 END_PROFILE(syscall_rewinddir);
496 static int vfswrap_mkdir(vfs_handle_struct *handle,
497 const struct smb_filename *smb_fname,
501 const char *path = smb_fname->base_name;
504 START_PROFILE(syscall_mkdir);
506 if (lp_inherit_acls(SNUM(handle->conn))
507 && parent_dirname(talloc_tos(), path, &parent, NULL)
508 && directory_has_default_acl(handle->conn, parent)) {
509 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
514 result = mkdir(path, mode);
516 END_PROFILE(syscall_mkdir);
520 static int vfswrap_rmdir(vfs_handle_struct *handle,
521 const struct smb_filename *smb_fname)
525 START_PROFILE(syscall_rmdir);
526 result = rmdir(smb_fname->base_name);
527 END_PROFILE(syscall_rmdir);
531 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
535 START_PROFILE(syscall_closedir);
536 result = closedir(dirp);
537 END_PROFILE(syscall_closedir);
541 /* File operations */
543 static int vfswrap_open(vfs_handle_struct *handle,
544 struct smb_filename *smb_fname,
545 files_struct *fsp, int flags, mode_t mode)
549 START_PROFILE(syscall_open);
551 if (smb_fname->stream_name) {
556 result = open(smb_fname->base_name, flags, mode);
558 END_PROFILE(syscall_open);
562 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
563 struct smb_request *req,
564 uint16_t root_dir_fid,
565 struct smb_filename *smb_fname,
566 uint32_t access_mask,
567 uint32_t share_access,
568 uint32_t create_disposition,
569 uint32_t create_options,
570 uint32_t file_attributes,
571 uint32_t oplock_request,
572 const struct smb2_lease *lease,
573 uint64_t allocation_size,
574 uint32_t private_flags,
575 struct security_descriptor *sd,
576 struct ea_list *ea_list,
577 files_struct **result,
579 const struct smb2_create_blobs *in_context_blobs,
580 struct smb2_create_blobs *out_context_blobs)
582 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
583 access_mask, share_access,
584 create_disposition, create_options,
585 file_attributes, oplock_request, lease,
586 allocation_size, private_flags,
588 pinfo, in_context_blobs, out_context_blobs);
591 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
595 START_PROFILE(syscall_close);
596 result = fd_close_posix(fsp);
597 END_PROFILE(syscall_close);
601 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
602 size_t n, off_t offset)
606 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
607 START_PROFILE_BYTES(syscall_pread, n);
608 result = sys_pread(fsp->fh->fd, data, n, offset);
609 END_PROFILE_BYTES(syscall_pread);
611 if (result == -1 && errno == ESPIPE) {
612 /* Maintain the fiction that pipes can be seeked (sought?) on. */
613 result = sys_read(fsp->fh->fd, data, n);
617 #else /* HAVE_PREAD */
620 #endif /* HAVE_PREAD */
625 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
626 size_t n, off_t offset)
630 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
631 START_PROFILE_BYTES(syscall_pwrite, n);
632 result = sys_pwrite(fsp->fh->fd, data, n, offset);
633 END_PROFILE_BYTES(syscall_pwrite);
635 if (result == -1 && errno == ESPIPE) {
636 /* Maintain the fiction that pipes can be sought on. */
637 result = sys_write(fsp->fh->fd, data, n);
640 #else /* HAVE_PWRITE */
643 #endif /* HAVE_PWRITE */
648 struct vfswrap_pread_state {
655 struct vfs_aio_state vfs_aio_state;
656 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
659 static void vfs_pread_do(void *private_data);
660 static void vfs_pread_done(struct tevent_req *subreq);
661 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state);
663 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
665 struct tevent_context *ev,
666 struct files_struct *fsp,
668 size_t n, off_t offset)
670 struct tevent_req *req, *subreq;
671 struct vfswrap_pread_state *state;
673 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
679 state->fd = fsp->fh->fd;
682 state->offset = offset;
684 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
685 state->profile_bytes, n);
686 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
688 subreq = pthreadpool_tevent_job_send(
689 state, ev, handle->conn->sconn->pool,
690 vfs_pread_do, state);
691 if (tevent_req_nomem(subreq, req)) {
692 return tevent_req_post(req, ev);
694 tevent_req_set_callback(subreq, vfs_pread_done, req);
696 talloc_set_destructor(state, vfs_pread_state_destructor);
701 static void vfs_pread_do(void *private_data)
703 struct vfswrap_pread_state *state = talloc_get_type_abort(
704 private_data, struct vfswrap_pread_state);
705 struct timespec start_time;
706 struct timespec end_time;
708 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
710 PROFILE_TIMESTAMP(&start_time);
713 state->ret = pread(state->fd, state->buf, state->count,
715 } while ((state->ret == -1) && (errno == EINTR));
717 if (state->ret == -1) {
718 state->vfs_aio_state.error = errno;
721 PROFILE_TIMESTAMP(&end_time);
723 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
725 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
728 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state)
733 static void vfs_pread_done(struct tevent_req *subreq)
735 struct tevent_req *req = tevent_req_callback_data(
736 subreq, struct tevent_req);
737 struct vfswrap_pread_state *state = tevent_req_data(
738 req, struct vfswrap_pread_state);
741 ret = pthreadpool_tevent_job_recv(subreq);
743 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
744 talloc_set_destructor(state, NULL);
747 tevent_req_error(req, ret);
751 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
752 * means the lower level pthreadpool failed to create a new
753 * thread. Fallback to sync processing in that case to allow
754 * some progress for the client.
759 tevent_req_done(req);
762 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
763 struct vfs_aio_state *vfs_aio_state)
765 struct vfswrap_pread_state *state = tevent_req_data(
766 req, struct vfswrap_pread_state);
768 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
772 *vfs_aio_state = state->vfs_aio_state;
776 struct vfswrap_pwrite_state {
783 struct vfs_aio_state vfs_aio_state;
784 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
787 static void vfs_pwrite_do(void *private_data);
788 static void vfs_pwrite_done(struct tevent_req *subreq);
789 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state);
791 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
793 struct tevent_context *ev,
794 struct files_struct *fsp,
796 size_t n, off_t offset)
798 struct tevent_req *req, *subreq;
799 struct vfswrap_pwrite_state *state;
801 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
807 state->fd = fsp->fh->fd;
810 state->offset = offset;
812 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
813 state->profile_bytes, n);
814 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
816 subreq = pthreadpool_tevent_job_send(
817 state, ev, handle->conn->sconn->pool,
818 vfs_pwrite_do, state);
819 if (tevent_req_nomem(subreq, req)) {
820 return tevent_req_post(req, ev);
822 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
824 talloc_set_destructor(state, vfs_pwrite_state_destructor);
829 static void vfs_pwrite_do(void *private_data)
831 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
832 private_data, struct vfswrap_pwrite_state);
833 struct timespec start_time;
834 struct timespec end_time;
836 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
838 PROFILE_TIMESTAMP(&start_time);
841 state->ret = pwrite(state->fd, state->buf, state->count,
843 } while ((state->ret == -1) && (errno == EINTR));
845 if (state->ret == -1) {
846 state->vfs_aio_state.error = errno;
849 PROFILE_TIMESTAMP(&end_time);
851 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
853 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
856 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state)
861 static void vfs_pwrite_done(struct tevent_req *subreq)
863 struct tevent_req *req = tevent_req_callback_data(
864 subreq, struct tevent_req);
865 struct vfswrap_pwrite_state *state = tevent_req_data(
866 req, struct vfswrap_pwrite_state);
869 ret = pthreadpool_tevent_job_recv(subreq);
871 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
872 talloc_set_destructor(state, NULL);
875 tevent_req_error(req, ret);
879 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
880 * means the lower level pthreadpool failed to create a new
881 * thread. Fallback to sync processing in that case to allow
882 * some progress for the client.
884 vfs_pwrite_do(state);
887 tevent_req_done(req);
890 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
891 struct vfs_aio_state *vfs_aio_state)
893 struct vfswrap_pwrite_state *state = tevent_req_data(
894 req, struct vfswrap_pwrite_state);
896 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
900 *vfs_aio_state = state->vfs_aio_state;
904 struct vfswrap_fsync_state {
908 struct vfs_aio_state vfs_aio_state;
909 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
912 static void vfs_fsync_do(void *private_data);
913 static void vfs_fsync_done(struct tevent_req *subreq);
914 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state);
916 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
918 struct tevent_context *ev,
919 struct files_struct *fsp)
921 struct tevent_req *req, *subreq;
922 struct vfswrap_fsync_state *state;
924 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
930 state->fd = fsp->fh->fd;
932 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_fsync, profile_p,
933 state->profile_bytes, 0);
934 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
936 subreq = pthreadpool_tevent_job_send(
937 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
938 if (tevent_req_nomem(subreq, req)) {
939 return tevent_req_post(req, ev);
941 tevent_req_set_callback(subreq, vfs_fsync_done, req);
943 talloc_set_destructor(state, vfs_fsync_state_destructor);
948 static void vfs_fsync_do(void *private_data)
950 struct vfswrap_fsync_state *state = talloc_get_type_abort(
951 private_data, struct vfswrap_fsync_state);
952 struct timespec start_time;
953 struct timespec end_time;
955 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
957 PROFILE_TIMESTAMP(&start_time);
960 state->ret = fsync(state->fd);
961 } while ((state->ret == -1) && (errno == EINTR));
963 if (state->ret == -1) {
964 state->vfs_aio_state.error = errno;
967 PROFILE_TIMESTAMP(&end_time);
969 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
971 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
974 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state)
979 static void vfs_fsync_done(struct tevent_req *subreq)
981 struct tevent_req *req = tevent_req_callback_data(
982 subreq, struct tevent_req);
983 struct vfswrap_fsync_state *state = tevent_req_data(
984 req, struct vfswrap_fsync_state);
987 ret = pthreadpool_tevent_job_recv(subreq);
989 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
990 talloc_set_destructor(state, NULL);
993 tevent_req_error(req, ret);
997 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
998 * means the lower level pthreadpool failed to create a new
999 * thread. Fallback to sync processing in that case to allow
1000 * some progress for the client.
1002 vfs_fsync_do(state);
1005 tevent_req_done(req);
1008 static int vfswrap_fsync_recv(struct tevent_req *req,
1009 struct vfs_aio_state *vfs_aio_state)
1011 struct vfswrap_fsync_state *state = tevent_req_data(
1012 req, struct vfswrap_fsync_state);
1014 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1018 *vfs_aio_state = state->vfs_aio_state;
1022 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1026 START_PROFILE(syscall_lseek);
1028 result = lseek(fsp->fh->fd, offset, whence);
1030 * We want to maintain the fiction that we can seek
1031 * on a fifo for file system purposes. This allows
1032 * people to set up UNIX fifo's that feed data to Windows
1033 * applications. JRA.
1036 if((result == -1) && (errno == ESPIPE)) {
1041 END_PROFILE(syscall_lseek);
1045 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1046 off_t offset, size_t n)
1050 START_PROFILE_BYTES(syscall_sendfile, n);
1051 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
1052 END_PROFILE_BYTES(syscall_sendfile);
1056 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1058 files_struct *tofsp,
1064 START_PROFILE_BYTES(syscall_recvfile, n);
1065 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
1066 END_PROFILE_BYTES(syscall_recvfile);
1070 static int vfswrap_renameat(vfs_handle_struct *handle,
1071 files_struct *srcfsp,
1072 const struct smb_filename *smb_fname_src,
1073 files_struct *dstfsp,
1074 const struct smb_filename *smb_fname_dst)
1078 START_PROFILE(syscall_renameat);
1080 SMB_ASSERT(srcfsp->fh->fd == AT_FDCWD);
1081 SMB_ASSERT(dstfsp->fh->fd == AT_FDCWD);
1083 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
1088 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
1091 END_PROFILE(syscall_renameat);
1095 static int vfswrap_stat(vfs_handle_struct *handle,
1096 struct smb_filename *smb_fname)
1100 START_PROFILE(syscall_stat);
1102 if (smb_fname->stream_name) {
1107 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1108 lp_fake_directory_create_times(SNUM(handle->conn)));
1110 END_PROFILE(syscall_stat);
1114 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1118 START_PROFILE(syscall_fstat);
1119 result = sys_fstat(fsp->fh->fd,
1120 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1121 END_PROFILE(syscall_fstat);
1125 static int vfswrap_lstat(vfs_handle_struct *handle,
1126 struct smb_filename *smb_fname)
1130 START_PROFILE(syscall_lstat);
1132 if (smb_fname->stream_name) {
1137 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1138 lp_fake_directory_create_times(SNUM(handle->conn)));
1140 END_PROFILE(syscall_lstat);
1144 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1146 enum vfs_translate_direction direction,
1147 TALLOC_CTX *mem_ctx,
1150 return NT_STATUS_NONE_MAPPED;
1154 * Implement the default fsctl operation.
1156 static bool vfswrap_logged_ioctl_message = false;
1158 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1159 struct files_struct *fsp,
1162 uint16_t req_flags, /* Needed for UNICODE ... */
1163 const uint8_t *_in_data,
1165 uint8_t **_out_data,
1166 uint32_t max_out_len,
1169 const char *in_data = (const char *)_in_data;
1170 char **out_data = (char **)_out_data;
1174 case FSCTL_SET_SPARSE:
1176 bool set_sparse = true;
1178 if (in_len >= 1 && in_data[0] == 0) {
1182 status = file_set_sparse(handle->conn, fsp, set_sparse);
1184 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1185 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1186 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1187 nt_errstr(status)));
1192 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1194 unsigned char objid[16];
1195 char *return_data = NULL;
1197 /* This should return the object-id on this file.
1198 * I think I'll make this be the inode+dev. JRA.
1201 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1202 fsp_fnum_dbg(fsp)));
1204 *out_len = MIN(max_out_len, 64);
1206 /* Hmmm, will this cause problems if less data asked for? */
1207 return_data = talloc_array(ctx, char, 64);
1208 if (return_data == NULL) {
1209 return NT_STATUS_NO_MEMORY;
1212 /* For backwards compatibility only store the dev/inode. */
1213 push_file_id_16(return_data, &fsp->file_id);
1214 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1215 push_file_id_16(return_data+32, &fsp->file_id);
1216 memset(return_data+48, 0, 16);
1217 *out_data = return_data;
1218 return NT_STATUS_OK;
1221 case FSCTL_GET_REPARSE_POINT:
1223 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1224 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1225 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1226 return NT_STATUS_NOT_A_REPARSE_POINT;
1229 case FSCTL_SET_REPARSE_POINT:
1231 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1232 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1233 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1234 return NT_STATUS_NOT_A_REPARSE_POINT;
1237 case FSCTL_GET_SHADOW_COPY_DATA:
1240 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1241 * and return their volume names. If max_data_count is 16, then it is just
1242 * asking for the number of volumes and length of the combined names.
1244 * pdata is the data allocated by our caller, but that uses
1245 * total_data_count (which is 0 in our case) rather than max_data_count.
1246 * Allocate the correct amount and return the pointer to let
1247 * it be deallocated when we return.
1249 struct shadow_copy_data *shadow_data = NULL;
1250 bool labels = False;
1251 uint32_t labels_data_count = 0;
1253 char *cur_pdata = NULL;
1255 if (max_out_len < 16) {
1256 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1258 return NT_STATUS_INVALID_PARAMETER;
1261 if (max_out_len > 16) {
1265 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1266 if (shadow_data == NULL) {
1267 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1268 return NT_STATUS_NO_MEMORY;
1272 * Call the VFS routine to actually do the work.
1274 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1277 /* broken module didn't set errno on error */
1278 status = NT_STATUS_UNSUCCESSFUL;
1280 status = map_nt_error_from_unix(errno);
1281 if (NT_STATUS_EQUAL(status,
1282 NT_STATUS_NOT_SUPPORTED)) {
1286 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1287 "connectpath %s, failed - %s.\n",
1288 fsp->conn->connectpath,
1289 nt_errstr(status)));
1290 TALLOC_FREE(shadow_data);
1294 labels_data_count = (shadow_data->num_volumes * 2 *
1295 sizeof(SHADOW_COPY_LABEL)) + 2;
1300 *out_len = 12 + labels_data_count;
1303 if (max_out_len < *out_len) {
1304 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1305 max_out_len, *out_len));
1306 TALLOC_FREE(shadow_data);
1307 return NT_STATUS_BUFFER_TOO_SMALL;
1310 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1311 if (cur_pdata == NULL) {
1312 TALLOC_FREE(shadow_data);
1313 return NT_STATUS_NO_MEMORY;
1316 *out_data = cur_pdata;
1318 /* num_volumes 4 bytes */
1319 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1322 /* num_labels 4 bytes */
1323 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1326 /* needed_data_count 4 bytes */
1327 SIVAL(cur_pdata, 8, labels_data_count);
1331 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1332 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1333 if (labels && shadow_data->labels) {
1334 for (i=0; i<shadow_data->num_volumes; i++) {
1336 status = srvstr_push(cur_pdata, req_flags,
1337 cur_pdata, shadow_data->labels[i],
1338 2 * sizeof(SHADOW_COPY_LABEL),
1339 STR_UNICODE|STR_TERMINATE, &len);
1340 if (!NT_STATUS_IS_OK(status)) {
1341 TALLOC_FREE(*out_data);
1342 TALLOC_FREE(shadow_data);
1345 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1346 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1350 TALLOC_FREE(shadow_data);
1352 return NT_STATUS_OK;
1355 case FSCTL_FIND_FILES_BY_SID:
1357 /* pretend this succeeded -
1359 * we have to send back a list with all files owned by this SID
1361 * but I have to check that --metze
1365 struct dom_sid_buf buf;
1369 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1370 fsp_fnum_dbg(fsp)));
1373 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1374 return NT_STATUS_INVALID_PARAMETER;
1377 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1379 /* unknown 4 bytes: this is not the length of the sid :-( */
1380 /*unknown = IVAL(pdata,0);*/
1382 ret = sid_parse(_in_data + 4, sid_len, &sid);
1384 return NT_STATUS_INVALID_PARAMETER;
1386 DEBUGADD(10, ("for SID: %s\n",
1387 dom_sid_str_buf(&sid, &buf)));
1389 if (!sid_to_uid(&sid, &uid)) {
1390 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1391 dom_sid_str_buf(&sid, &buf),
1392 (unsigned long)sid_len));
1396 /* we can take a look at the find source :-)
1398 * find ./ -uid $uid -name '*' is what we need here
1401 * and send 4bytes len and then NULL terminated unicode strings
1404 * but I don't know how to deal with the paged results
1405 * (maybe we can hang the result anywhere in the fsp struct)
1407 * but I don't know how to deal with the paged results
1408 * (maybe we can hang the result anywhere in the fsp struct)
1410 * we don't send all files at once
1411 * and at the next we should *not* start from the beginning,
1412 * so we have to cache the result
1417 /* this works for now... */
1418 return NT_STATUS_OK;
1421 case FSCTL_QUERY_ALLOCATED_RANGES:
1423 /* FIXME: This is just a dummy reply, telling that all of the
1424 * file is allocated. MKS cp needs that.
1425 * Adding the real allocated ranges via FIEMAP on Linux
1426 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1427 * this FSCTL correct for sparse files.
1429 uint64_t offset, length;
1430 char *out_data_tmp = NULL;
1433 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1435 return NT_STATUS_INVALID_PARAMETER;
1438 if (max_out_len < 16) {
1439 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1441 return NT_STATUS_INVALID_PARAMETER;
1444 offset = BVAL(in_data,0);
1445 length = BVAL(in_data,8);
1447 if (offset + length < offset) {
1448 /* No 64-bit integer wrap. */
1449 return NT_STATUS_INVALID_PARAMETER;
1452 /* Shouldn't this be SMB_VFS_STAT ... ? */
1453 status = vfs_stat_fsp(fsp);
1454 if (!NT_STATUS_IS_OK(status)) {
1459 out_data_tmp = talloc_array(ctx, char, *out_len);
1460 if (out_data_tmp == NULL) {
1461 DEBUG(10, ("unable to allocate memory for response\n"));
1462 return NT_STATUS_NO_MEMORY;
1465 if (offset > fsp->fsp_name->st.st_ex_size ||
1466 fsp->fsp_name->st.st_ex_size == 0 ||
1468 memset(out_data_tmp, 0, *out_len);
1470 uint64_t end = offset + length;
1471 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1472 SBVAL(out_data_tmp, 0, 0);
1473 SBVAL(out_data_tmp, 8, end);
1476 *out_data = out_data_tmp;
1478 return NT_STATUS_OK;
1481 case FSCTL_IS_VOLUME_DIRTY:
1483 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1484 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1486 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1487 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1489 return NT_STATUS_INVALID_PARAMETER;
1494 * Only print once ... unfortunately there could be lots of
1495 * different FSCTLs that are called.
1497 if (!vfswrap_logged_ioctl_message) {
1498 vfswrap_logged_ioctl_message = true;
1499 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1500 __func__, function));
1504 return NT_STATUS_NOT_SUPPORTED;
1507 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
1508 const struct smb_filename *fname,
1509 SMB_STRUCT_STAT *sbuf);
1511 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1512 struct smb_filename *smb_fname,
1517 offline = vfswrap_is_offline(handle, smb_fname, &smb_fname->st);
1519 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1522 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1525 struct vfswrap_get_dos_attributes_state {
1526 struct vfs_aio_state aio_state;
1527 connection_struct *conn;
1528 TALLOC_CTX *mem_ctx;
1529 struct tevent_context *ev;
1530 files_struct *dir_fsp;
1531 struct smb_filename *smb_fname;
1536 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq);
1538 static struct tevent_req *vfswrap_get_dos_attributes_send(
1539 TALLOC_CTX *mem_ctx,
1540 struct tevent_context *ev,
1541 struct vfs_handle_struct *handle,
1542 files_struct *dir_fsp,
1543 struct smb_filename *smb_fname)
1545 struct tevent_req *req = NULL;
1546 struct tevent_req *subreq = NULL;
1547 struct vfswrap_get_dos_attributes_state *state = NULL;
1549 req = tevent_req_create(mem_ctx, &state,
1550 struct vfswrap_get_dos_attributes_state);
1555 *state = (struct vfswrap_get_dos_attributes_state) {
1556 .conn = dir_fsp->conn,
1560 .smb_fname = smb_fname,
1563 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1567 SAMBA_XATTR_DOS_ATTRIB,
1569 if (tevent_req_nomem(subreq, req)) {
1570 return tevent_req_post(req, ev);
1572 tevent_req_set_callback(subreq,
1573 vfswrap_get_dos_attributes_getxattr_done,
1579 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq)
1581 struct tevent_req *req =
1582 tevent_req_callback_data(subreq,
1584 struct vfswrap_get_dos_attributes_state *state =
1585 tevent_req_data(req,
1586 struct vfswrap_get_dos_attributes_state);
1588 DATA_BLOB blob = {0};
1591 xattr_size = SMB_VFS_GETXATTRAT_RECV(subreq,
1595 TALLOC_FREE(subreq);
1596 if (xattr_size == -1) {
1597 status = map_nt_error_from_unix(state->aio_state.error);
1599 if (state->as_root) {
1600 tevent_req_nterror(req, status);
1603 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1604 tevent_req_nterror(req, status);
1608 state->as_root = true;
1611 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1615 SAMBA_XATTR_DOS_ATTRIB,
1618 if (tevent_req_nomem(subreq, req)) {
1621 tevent_req_set_callback(subreq,
1622 vfswrap_get_dos_attributes_getxattr_done,
1627 blob.length = xattr_size;
1629 status = parse_dos_attribute_blob(state->smb_fname,
1632 if (!NT_STATUS_IS_OK(status)) {
1633 tevent_req_nterror(req, status);
1637 tevent_req_done(req);
1641 static NTSTATUS vfswrap_get_dos_attributes_recv(struct tevent_req *req,
1642 struct vfs_aio_state *aio_state,
1645 struct vfswrap_get_dos_attributes_state *state =
1646 tevent_req_data(req,
1647 struct vfswrap_get_dos_attributes_state);
1650 if (tevent_req_is_nterror(req, &status)) {
1651 tevent_req_received(req);
1655 *aio_state = state->aio_state;
1656 *dosmode = state->dosmode;
1657 tevent_req_received(req);
1658 return NT_STATUS_OK;
1661 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1662 struct files_struct *fsp,
1667 offline = vfswrap_is_offline(handle, fsp->fsp_name, &fsp->fsp_name->st);
1669 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1672 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1675 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1676 const struct smb_filename *smb_fname,
1679 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1682 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1683 struct files_struct *fsp,
1686 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1689 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1691 struct vfswrap_offload_read_state {
1695 static struct tevent_req *vfswrap_offload_read_send(
1696 TALLOC_CTX *mem_ctx,
1697 struct tevent_context *ev,
1698 struct vfs_handle_struct *handle,
1699 struct files_struct *fsp,
1705 struct tevent_req *req = NULL;
1706 struct vfswrap_offload_read_state *state = NULL;
1709 req = tevent_req_create(mem_ctx, &state,
1710 struct vfswrap_offload_read_state);
1715 status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1716 &vfswrap_offload_ctx);
1717 if (tevent_req_nterror(req, status)) {
1718 return tevent_req_post(req, ev);
1721 if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1722 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1723 return tevent_req_post(req, ev);
1726 status = vfs_offload_token_create_blob(state, fsp, fsctl,
1728 if (tevent_req_nterror(req, status)) {
1729 return tevent_req_post(req, ev);
1732 status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1734 if (tevent_req_nterror(req, status)) {
1735 return tevent_req_post(req, ev);
1738 tevent_req_done(req);
1739 return tevent_req_post(req, ev);
1742 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
1743 struct vfs_handle_struct *handle,
1744 TALLOC_CTX *mem_ctx,
1747 struct vfswrap_offload_read_state *state = tevent_req_data(
1748 req, struct vfswrap_offload_read_state);
1751 if (tevent_req_is_nterror(req, &status)) {
1752 tevent_req_received(req);
1756 token->length = state->token.length;
1757 token->data = talloc_move(mem_ctx, &state->token.data);
1759 tevent_req_received(req);
1760 return NT_STATUS_OK;
1763 struct vfswrap_offload_write_state {
1765 bool read_lck_locked;
1766 bool write_lck_locked;
1768 struct tevent_context *src_ev;
1769 struct files_struct *src_fsp;
1771 struct tevent_context *dst_ev;
1772 struct files_struct *dst_fsp;
1776 size_t next_io_size;
1779 static void vfswrap_offload_write_cleanup(struct tevent_req *req,
1780 enum tevent_req_state req_state)
1782 struct vfswrap_offload_write_state *state = tevent_req_data(
1783 req, struct vfswrap_offload_write_state);
1786 if (state->dst_fsp == NULL) {
1790 ok = change_to_user_by_fsp(state->dst_fsp);
1792 state->dst_fsp = NULL;
1795 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
1797 static struct tevent_req *vfswrap_offload_write_send(
1798 struct vfs_handle_struct *handle,
1799 TALLOC_CTX *mem_ctx,
1800 struct tevent_context *ev,
1803 off_t transfer_offset,
1804 struct files_struct *dest_fsp,
1808 struct tevent_req *req;
1809 struct vfswrap_offload_write_state *state = NULL;
1810 /* off_t is signed! */
1811 off_t max_offset = INT64_MAX - to_copy;
1812 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
1813 files_struct *src_fsp = NULL;
1817 req = tevent_req_create(mem_ctx, &state,
1818 struct vfswrap_offload_write_state);
1823 *state = (struct vfswrap_offload_write_state) {
1825 .src_off = transfer_offset,
1827 .dst_fsp = dest_fsp,
1828 .dst_off = dest_off,
1830 .remaining = to_copy,
1833 tevent_req_set_cleanup_fn(req, vfswrap_offload_write_cleanup);
1836 case FSCTL_SRV_COPYCHUNK:
1837 case FSCTL_SRV_COPYCHUNK_WRITE:
1840 case FSCTL_OFFLOAD_WRITE:
1841 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
1842 return tevent_req_post(req, ev);
1844 case FSCTL_DUP_EXTENTS_TO_FILE:
1845 DBG_DEBUG("COW clones not supported by vfs_default\n");
1846 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1847 return tevent_req_post(req, ev);
1850 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1851 return tevent_req_post(req, ev);
1855 * From here on we assume a copy-chunk fsctl
1859 tevent_req_done(req);
1860 return tevent_req_post(req, ev);
1863 if (state->src_off > max_offset) {
1865 * Protect integer checks below.
1867 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1868 return tevent_req_post(req, ev);
1870 if (state->src_off < 0) {
1872 * Protect integer checks below.
1874 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1875 return tevent_req_post(req, ev);
1877 if (state->dst_off > max_offset) {
1879 * Protect integer checks below.
1881 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1882 return tevent_req_post(req, ev);
1884 if (state->dst_off < 0) {
1886 * Protect integer checks below.
1888 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1889 return tevent_req_post(req, ev);
1892 status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
1894 if (tevent_req_nterror(req, status)) {
1895 return tevent_req_post(req, ev);
1898 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
1900 status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
1901 if (!NT_STATUS_IS_OK(status)) {
1902 tevent_req_nterror(req, status);
1903 return tevent_req_post(req, ev);
1906 ok = change_to_user_by_fsp(src_fsp);
1908 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1909 return tevent_req_post(req, ev);
1912 state->src_ev = src_fsp->conn->sconn->ev_ctx;
1913 state->src_fsp = src_fsp;
1915 status = vfs_stat_fsp(src_fsp);
1916 if (tevent_req_nterror(req, status)) {
1917 return tevent_req_post(req, ev);
1920 if (src_fsp->fsp_name->st.st_ex_size < state->src_off + to_copy) {
1922 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1923 * If the SourceOffset or SourceOffset + Length extends beyond
1924 * the end of file, the server SHOULD<240> treat this as a
1925 * STATUS_END_OF_FILE error.
1927 * <240> Section 3.3.5.15.6: Windows servers will return
1928 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1930 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1931 return tevent_req_post(req, ev);
1934 state->buf = talloc_array(state, uint8_t, num);
1935 if (tevent_req_nomem(state->buf, req)) {
1936 return tevent_req_post(req, ev);
1939 status = vfswrap_offload_write_loop(req);
1940 if (!NT_STATUS_IS_OK(status)) {
1941 tevent_req_nterror(req, status);
1942 return tevent_req_post(req, ev);
1948 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
1950 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
1952 struct vfswrap_offload_write_state *state = tevent_req_data(
1953 req, struct vfswrap_offload_write_state);
1954 struct tevent_req *subreq = NULL;
1955 struct lock_struct read_lck;
1959 * This is called under the context of state->src_fsp.
1962 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
1964 init_strict_lock_struct(state->src_fsp,
1965 state->src_fsp->op->global->open_persistent_id,
1967 state->next_io_size,
1971 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
1975 return NT_STATUS_FILE_LOCK_CONFLICT;
1978 subreq = SMB_VFS_PREAD_SEND(state,
1982 state->next_io_size,
1984 if (subreq == NULL) {
1985 return NT_STATUS_NO_MEMORY;
1987 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
1989 return NT_STATUS_OK;
1992 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
1994 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
1996 struct tevent_req *req = tevent_req_callback_data(
1997 subreq, struct tevent_req);
1998 struct vfswrap_offload_write_state *state = tevent_req_data(
1999 req, struct vfswrap_offload_write_state);
2000 struct vfs_aio_state aio_state;
2001 struct lock_struct write_lck;
2005 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
2006 TALLOC_FREE(subreq);
2008 DBG_ERR("read failed: %s\n", strerror(aio_state.error));
2009 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2012 if (nread != state->next_io_size) {
2013 DBG_ERR("Short read, only %zd of %zu\n",
2014 nread, state->next_io_size);
2015 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2019 state->src_off += nread;
2021 ok = change_to_user_by_fsp(state->dst_fsp);
2023 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2027 init_strict_lock_struct(state->dst_fsp,
2028 state->dst_fsp->op->global->open_persistent_id,
2030 state->next_io_size,
2034 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
2038 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
2042 subreq = SMB_VFS_PWRITE_SEND(state,
2046 state->next_io_size,
2048 if (subreq == NULL) {
2049 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2052 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
2055 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
2057 struct tevent_req *req = tevent_req_callback_data(
2058 subreq, struct tevent_req);
2059 struct vfswrap_offload_write_state *state = tevent_req_data(
2060 req, struct vfswrap_offload_write_state);
2061 struct vfs_aio_state aio_state;
2066 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
2067 TALLOC_FREE(subreq);
2068 if (nwritten == -1) {
2069 DBG_ERR("write failed: %s\n", strerror(aio_state.error));
2070 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2073 if (nwritten != state->next_io_size) {
2074 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
2075 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2079 state->dst_off += nwritten;
2081 if (state->remaining < nwritten) {
2082 /* Paranoia check */
2083 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2086 state->remaining -= nwritten;
2087 if (state->remaining == 0) {
2088 tevent_req_done(req);
2092 ok = change_to_user_by_fsp(state->src_fsp);
2094 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2098 status = vfswrap_offload_write_loop(req);
2099 if (!NT_STATUS_IS_OK(status)) {
2100 tevent_req_nterror(req, status);
2107 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
2108 struct tevent_req *req,
2111 struct vfswrap_offload_write_state *state = tevent_req_data(
2112 req, struct vfswrap_offload_write_state);
2115 if (tevent_req_is_nterror(req, &status)) {
2116 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
2118 tevent_req_received(req);
2122 *copied = state->to_copy;
2123 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
2124 tevent_req_received(req);
2126 return NT_STATUS_OK;
2129 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
2130 TALLOC_CTX *mem_ctx,
2131 struct files_struct *fsp,
2132 struct smb_filename *smb_fname,
2133 uint16_t *_compression_fmt)
2135 return NT_STATUS_INVALID_DEVICE_REQUEST;
2138 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
2139 TALLOC_CTX *mem_ctx,
2140 struct files_struct *fsp,
2141 uint16_t compression_fmt)
2143 return NT_STATUS_INVALID_DEVICE_REQUEST;
2146 /********************************************************************
2147 Given a stat buffer return the allocated size on disk, taking into
2148 account sparse files.
2149 ********************************************************************/
2150 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
2151 struct files_struct *fsp,
2152 const SMB_STRUCT_STAT *sbuf)
2156 START_PROFILE(syscall_get_alloc_size);
2158 if(S_ISDIR(sbuf->st_ex_mode)) {
2163 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2164 /* The type of st_blocksize is blkcnt_t which *MUST* be
2165 signed (according to POSIX) and can be less than 64-bits.
2166 Ensure when we're converting to 64 bits wide we don't
2168 #if defined(SIZEOF_BLKCNT_T_8)
2169 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2170 #elif defined(SIZEOF_BLKCNT_T_4)
2172 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2173 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2176 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2180 * Some file systems do not allocate a block for very
2181 * small files. But for non-empty file should report a
2185 uint64_t filesize = get_file_size_stat(sbuf);
2187 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2191 result = get_file_size_stat(sbuf);
2194 if (fsp && fsp->initial_allocation_size)
2195 result = MAX(result,fsp->initial_allocation_size);
2197 result = smb_roundup(handle->conn, result);
2200 END_PROFILE(syscall_get_alloc_size);
2204 static int vfswrap_unlink(vfs_handle_struct *handle,
2205 const struct smb_filename *smb_fname)
2209 START_PROFILE(syscall_unlink);
2211 if (smb_fname->stream_name) {
2215 result = unlink(smb_fname->base_name);
2218 END_PROFILE(syscall_unlink);
2222 static int vfswrap_chmod(vfs_handle_struct *handle,
2223 const struct smb_filename *smb_fname,
2228 START_PROFILE(syscall_chmod);
2229 result = chmod(smb_fname->base_name, mode);
2230 END_PROFILE(syscall_chmod);
2234 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2238 START_PROFILE(syscall_fchmod);
2239 #if defined(HAVE_FCHMOD)
2240 result = fchmod(fsp->fh->fd, mode);
2246 END_PROFILE(syscall_fchmod);
2250 static int vfswrap_chown(vfs_handle_struct *handle,
2251 const struct smb_filename *smb_fname,
2257 START_PROFILE(syscall_chown);
2258 result = chown(smb_fname->base_name, uid, gid);
2259 END_PROFILE(syscall_chown);
2263 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2268 START_PROFILE(syscall_fchown);
2269 result = fchown(fsp->fh->fd, uid, gid);
2270 END_PROFILE(syscall_fchown);
2278 static int vfswrap_lchown(vfs_handle_struct *handle,
2279 const struct smb_filename *smb_fname,
2285 START_PROFILE(syscall_lchown);
2286 result = lchown(smb_fname->base_name, uid, gid);
2287 END_PROFILE(syscall_lchown);
2291 static int vfswrap_chdir(vfs_handle_struct *handle,
2292 const struct smb_filename *smb_fname)
2296 START_PROFILE(syscall_chdir);
2297 result = chdir(smb_fname->base_name);
2298 END_PROFILE(syscall_chdir);
2302 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2306 struct smb_filename *smb_fname = NULL;
2308 START_PROFILE(syscall_getwd);
2309 result = sys_getwd();
2310 END_PROFILE(syscall_getwd);
2312 if (result == NULL) {
2315 smb_fname = synthetic_smb_fname(ctx,
2321 * sys_getwd() *always* returns malloced memory.
2322 * We must free here to avoid leaks:
2323 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2329 /*********************************************************************
2330 nsec timestamp resolution call. Convert down to whatever the underlying
2331 system will support.
2332 **********************************************************************/
2334 static int vfswrap_ntimes(vfs_handle_struct *handle,
2335 const struct smb_filename *smb_fname,
2336 struct smb_file_time *ft)
2340 START_PROFILE(syscall_ntimes);
2342 if (smb_fname->stream_name) {
2348 if (null_timespec(ft->atime)) {
2349 ft->atime= smb_fname->st.st_ex_atime;
2352 if (null_timespec(ft->mtime)) {
2353 ft->mtime = smb_fname->st.st_ex_mtime;
2356 if (!null_timespec(ft->create_time)) {
2357 set_create_timespec_ea(handle->conn,
2362 if ((timespec_compare(&ft->atime,
2363 &smb_fname->st.st_ex_atime) == 0) &&
2364 (timespec_compare(&ft->mtime,
2365 &smb_fname->st.st_ex_mtime) == 0)) {
2370 #if defined(HAVE_UTIMENSAT)
2372 struct timespec ts[2];
2375 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2377 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2379 if (!((result == -1) && (errno == ENOSYS))) {
2383 #if defined(HAVE_UTIMES)
2385 struct timeval tv[2];
2386 tv[0] = convert_timespec_to_timeval(ft->atime);
2387 tv[1] = convert_timespec_to_timeval(ft->mtime);
2388 result = utimes(smb_fname->base_name, tv);
2390 result = utimes(smb_fname->base_name, NULL);
2392 if (!((result == -1) && (errno == ENOSYS))) {
2396 #if defined(HAVE_UTIME)
2398 struct utimbuf times;
2399 times.actime = convert_timespec_to_time_t(ft->atime);
2400 times.modtime = convert_timespec_to_time_t(ft->mtime);
2401 result = utime(smb_fname->base_name, ×);
2403 result = utime(smb_fname->base_name, NULL);
2405 if (!((result == -1) && (errno == ENOSYS))) {
2413 END_PROFILE(syscall_ntimes);
2417 /*********************************************************************
2418 A version of ftruncate that will write the space on disk if strict
2420 **********************************************************************/
2422 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2424 off_t space_to_write;
2425 uint64_t space_avail;
2426 uint64_t bsize,dfree,dsize;
2429 SMB_STRUCT_STAT *pst;
2431 status = vfs_stat_fsp(fsp);
2432 if (!NT_STATUS_IS_OK(status)) {
2435 pst = &fsp->fsp_name->st;
2438 if (S_ISFIFO(pst->st_ex_mode))
2442 if (pst->st_ex_size == len)
2445 /* Shrink - just ftruncate. */
2446 if (pst->st_ex_size > len)
2447 return ftruncate(fsp->fh->fd, len);
2449 space_to_write = len - pst->st_ex_size;
2451 /* for allocation try fallocate first. This can fail on some
2452 platforms e.g. when the filesystem doesn't support it and no
2453 emulation is being done by the libc (like on AIX with JFS1). In that
2454 case we do our own emulation. fallocate implementations can
2455 return ENOTSUP or EINVAL in cases like that. */
2456 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2457 if (ret == -1 && errno == ENOSPC) {
2463 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2464 "error %d. Falling back to slow manual allocation\n", errno));
2466 /* available disk space is enough or not? */
2468 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2469 /* space_avail is 1k blocks */
2470 if (space_avail == (uint64_t)-1 ||
2471 ((uint64_t)space_to_write/1024 > space_avail) ) {
2476 /* Write out the real space on disk. */
2477 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2485 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2488 SMB_STRUCT_STAT *pst;
2492 START_PROFILE(syscall_ftruncate);
2494 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2495 result = strict_allocate_ftruncate(handle, fsp, len);
2496 END_PROFILE(syscall_ftruncate);
2500 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2501 ftruncate if the system supports it. Then I discovered that
2502 you can have some filesystems that support ftruncate
2503 expansion and some that don't! On Linux fat can't do
2504 ftruncate extend but ext2 can. */
2506 result = ftruncate(fsp->fh->fd, len);
2508 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2509 extend a file with ftruncate. Provide alternate implementation
2512 /* Do an fstat to see if the file is longer than the requested
2513 size in which case the ftruncate above should have
2514 succeeded or shorter, in which case seek to len - 1 and
2515 write 1 byte of zero */
2516 status = vfs_stat_fsp(fsp);
2517 if (!NT_STATUS_IS_OK(status)) {
2521 /* We need to update the files_struct after successful ftruncate */
2526 pst = &fsp->fsp_name->st;
2529 if (S_ISFIFO(pst->st_ex_mode)) {
2535 if (pst->st_ex_size == len) {
2540 if (pst->st_ex_size > len) {
2541 /* the ftruncate should have worked */
2545 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2553 END_PROFILE(syscall_ftruncate);
2557 static int vfswrap_fallocate(vfs_handle_struct *handle,
2565 START_PROFILE(syscall_fallocate);
2567 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2569 * posix_fallocate returns 0 on success, errno on error
2570 * and doesn't set errno. Make it behave like fallocate()
2571 * which returns -1, and sets errno on failure.
2578 /* sys_fallocate handles filtering of unsupported mode flags */
2579 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2581 END_PROFILE(syscall_fallocate);
2585 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2589 START_PROFILE(syscall_fcntl_lock);
2591 if (fsp->use_ofd_locks) {
2592 op = map_process_lock_to_ofd_lock(op);
2595 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2596 END_PROFILE(syscall_fcntl_lock);
2600 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2601 uint32_t share_mode, uint32_t access_mask)
2603 START_PROFILE(syscall_kernel_flock);
2604 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2605 END_PROFILE(syscall_kernel_flock);
2609 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2614 START_PROFILE(syscall_fcntl_getlock);
2616 if (fsp->use_ofd_locks) {
2617 op = map_process_lock_to_ofd_lock(op);
2620 result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2621 END_PROFILE(syscall_fcntl_getlock);
2625 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2630 START_PROFILE(syscall_linux_setlease);
2632 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2633 result = linux_setlease(fsp->fh->fd, leasetype);
2637 END_PROFILE(syscall_linux_setlease);
2641 static int vfswrap_symlink(vfs_handle_struct *handle,
2642 const char *link_target,
2643 const struct smb_filename *new_smb_fname)
2647 START_PROFILE(syscall_symlink);
2648 result = symlink(link_target, new_smb_fname->base_name);
2649 END_PROFILE(syscall_symlink);
2653 static int vfswrap_readlink(vfs_handle_struct *handle,
2654 const struct smb_filename *smb_fname,
2660 START_PROFILE(syscall_readlink);
2661 result = readlink(smb_fname->base_name, buf, bufsiz);
2662 END_PROFILE(syscall_readlink);
2666 static int vfswrap_link(vfs_handle_struct *handle,
2667 const struct smb_filename *old_smb_fname,
2668 const struct smb_filename *new_smb_fname)
2672 START_PROFILE(syscall_link);
2673 result = link(old_smb_fname->base_name, new_smb_fname->base_name);
2674 END_PROFILE(syscall_link);
2678 static int vfswrap_mknod(vfs_handle_struct *handle,
2679 const struct smb_filename *smb_fname,
2685 START_PROFILE(syscall_mknod);
2686 result = sys_mknod(smb_fname->base_name, mode, dev);
2687 END_PROFILE(syscall_mknod);
2691 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2693 const struct smb_filename *smb_fname)
2696 struct smb_filename *result_fname = NULL;
2698 START_PROFILE(syscall_realpath);
2699 result = sys_realpath(smb_fname->base_name);
2700 END_PROFILE(syscall_realpath);
2702 result_fname = synthetic_smb_fname(ctx, result, NULL, NULL, 0);
2705 return result_fname;
2708 static int vfswrap_chflags(vfs_handle_struct *handle,
2709 const struct smb_filename *smb_fname,
2713 return chflags(smb_fname->base_name, flags);
2720 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2721 const SMB_STRUCT_STAT *sbuf)
2725 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2729 key.devid = sbuf->st_ex_dev;
2730 key.inode = sbuf->st_ex_ino;
2731 /* key.extid is unused by default. */
2736 static uint64_t vfswrap_fs_file_id(struct vfs_handle_struct *handle,
2737 const SMB_STRUCT_STAT *psbuf)
2741 if (!(psbuf->st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)) {
2742 return psbuf->st_ex_file_id;
2745 if (handle->conn->base_share_dev == psbuf->st_ex_dev) {
2746 return (uint64_t)psbuf->st_ex_ino;
2750 file_id = ((psbuf->st_ex_ino) & UINT32_MAX);
2753 file_id |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32;
2758 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2759 struct files_struct *fsp,
2760 const struct smb_filename *smb_fname,
2761 TALLOC_CTX *mem_ctx,
2762 unsigned int *pnum_streams,
2763 struct stream_struct **pstreams)
2765 SMB_STRUCT_STAT sbuf;
2766 struct stream_struct *tmp_streams = NULL;
2769 if ((fsp != NULL) && (fsp->is_directory)) {
2771 * No default streams on directories
2776 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2777 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2780 struct smb_filename smb_fname_cp;
2782 ZERO_STRUCT(smb_fname_cp);
2783 smb_fname_cp.base_name = discard_const_p(char,
2784 smb_fname->base_name);
2785 smb_fname_cp.flags = smb_fname->flags;
2787 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
2788 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2790 ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2792 sbuf = smb_fname_cp.st;
2796 return map_nt_error_from_unix(errno);
2799 if (S_ISDIR(sbuf.st_ex_mode)) {
2803 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2804 (*pnum_streams) + 1);
2805 if (tmp_streams == NULL) {
2806 return NT_STATUS_NO_MEMORY;
2808 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2809 if (tmp_streams[*pnum_streams].name == NULL) {
2810 return NT_STATUS_NO_MEMORY;
2812 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2813 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2816 *pstreams = tmp_streams;
2818 return NT_STATUS_OK;
2821 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2824 TALLOC_CTX *mem_ctx,
2828 * Don't fall back to get_real_filename so callers can differentiate
2829 * between a full directory scan and an actual case-insensitive stat.
2835 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2836 const struct smb_filename *smb_fname)
2838 return handle->conn->connectpath;
2841 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2842 struct byte_range_lock *br_lck,
2843 struct lock_struct *plock)
2845 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2847 /* Note: blr is not used in the default implementation. */
2848 return brl_lock_windows_default(br_lck, plock);
2851 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2852 struct byte_range_lock *br_lck,
2853 const struct lock_struct *plock)
2855 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2857 return brl_unlock_windows_default(br_lck, plock);
2860 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
2862 struct lock_struct *plock)
2864 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2865 plock->lock_type == WRITE_LOCK);
2867 return strict_lock_check_default(fsp, plock);
2870 /* NT ACL operations. */
2872 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2874 uint32_t security_info,
2875 TALLOC_CTX *mem_ctx,
2876 struct security_descriptor **ppdesc)
2880 START_PROFILE(fget_nt_acl);
2881 result = posix_fget_nt_acl(fsp, security_info,
2883 END_PROFILE(fget_nt_acl);
2887 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2888 const struct smb_filename *smb_fname,
2889 uint32_t security_info,
2890 TALLOC_CTX *mem_ctx,
2891 struct security_descriptor **ppdesc)
2895 START_PROFILE(get_nt_acl);
2896 result = posix_get_nt_acl(handle->conn,
2901 END_PROFILE(get_nt_acl);
2905 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2909 START_PROFILE(fset_nt_acl);
2910 result = set_nt_acl(fsp, security_info_sent, psd);
2911 END_PROFILE(fset_nt_acl);
2915 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2916 struct smb_filename *file,
2917 struct security_acl *sacl,
2918 uint32_t access_requested,
2919 uint32_t access_denied)
2921 return NT_STATUS_OK; /* Nothing to do here ... */
2924 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2925 const struct smb_filename *smb_fname,
2926 SMB_ACL_TYPE_T type,
2927 TALLOC_CTX *mem_ctx)
2929 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
2932 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2934 TALLOC_CTX *mem_ctx)
2936 return sys_acl_get_fd(handle, fsp, mem_ctx);
2939 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
2940 const struct smb_filename *smb_fname,
2941 SMB_ACL_TYPE_T acltype,
2944 return sys_acl_set_file(handle, smb_fname, acltype, theacl);
2947 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2949 return sys_acl_set_fd(handle, fsp, theacl);
2952 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
2953 const struct smb_filename *smb_fname)
2955 return sys_acl_delete_def_file(handle, smb_fname);
2958 /****************************************************************
2959 Extended attribute operations.
2960 *****************************************************************/
2962 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
2963 const struct smb_filename *smb_fname,
2968 return getxattr(smb_fname->base_name, name, value, size);
2971 struct vfswrap_getxattrat_state {
2972 struct tevent_context *ev;
2973 files_struct *dir_fsp;
2974 const struct smb_filename *smb_fname;
2975 struct tevent_req *req;
2978 * The following variables are talloced off "state" which is protected
2979 * by a destructor and thus are guaranteed to be safe to be used in the
2980 * job function in the worker thread.
2983 const char *xattr_name;
2984 uint8_t *xattr_value;
2985 struct security_unix_token *token;
2988 struct vfs_aio_state vfs_aio_state;
2989 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
2992 static int vfswrap_getxattrat_state_destructor(
2993 struct vfswrap_getxattrat_state *state)
2998 static void vfswrap_getxattrat_do_sync(struct tevent_req *req);
2999 static void vfswrap_getxattrat_do_async(void *private_data);
3000 static void vfswrap_getxattrat_done(struct tevent_req *subreq);
3002 static struct tevent_req *vfswrap_getxattrat_send(
3003 TALLOC_CTX *mem_ctx,
3004 struct tevent_context *ev,
3005 struct vfs_handle_struct *handle,
3006 files_struct *dir_fsp,
3007 const struct smb_filename *smb_fname,
3008 const char *xattr_name,
3011 struct tevent_req *req = NULL;
3012 struct tevent_req *subreq = NULL;
3013 struct vfswrap_getxattrat_state *state = NULL;
3014 size_t max_threads = 0;
3015 bool have_per_thread_cwd = false;
3016 bool have_per_thread_creds = false;
3017 bool do_async = false;
3019 req = tevent_req_create(mem_ctx, &state,
3020 struct vfswrap_getxattrat_state);
3024 *state = (struct vfswrap_getxattrat_state) {
3027 .smb_fname = smb_fname,
3031 max_threads = pthreadpool_tevent_max_threads(dir_fsp->conn->sconn->pool);
3032 if (max_threads >= 1) {
3034 * We need a non sync threadpool!
3036 have_per_thread_cwd = per_thread_cwd_supported();
3038 #ifdef HAVE_LINUX_THREAD_CREDENTIALS
3039 have_per_thread_creds = true;
3041 if (have_per_thread_cwd && have_per_thread_creds) {
3045 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat, profile_p,
3046 state->profile_bytes, 0);
3048 if (dir_fsp->fh->fd == -1) {
3049 DBG_ERR("Need a valid directory fd\n");
3050 tevent_req_error(req, EINVAL);
3051 return tevent_req_post(req, ev);
3054 if (alloc_hint > 0) {
3055 state->xattr_value = talloc_zero_array(state,
3058 if (tevent_req_nomem(state->xattr_value, req)) {
3059 return tevent_req_post(req, ev);
3064 vfswrap_getxattrat_do_sync(req);
3065 return tevent_req_post(req, ev);
3069 * Now allocate all parameters from a memory context that won't go away
3070 * no matter what. These paremeters will get used in threads and we
3071 * can't reliably cancel threads, so all buffers passed to the threads
3072 * must not be freed before all referencing threads terminate.
3075 state->name = talloc_strdup(state, smb_fname->base_name);
3076 if (tevent_req_nomem(state->name, req)) {
3077 return tevent_req_post(req, ev);
3080 state->xattr_name = talloc_strdup(state, xattr_name);
3081 if (tevent_req_nomem(state->xattr_name, req)) {
3082 return tevent_req_post(req, ev);
3086 * This is a hot codepath so at first glance one might think we should
3087 * somehow optimize away the token allocation and do a
3088 * talloc_reference() or similar black magic instead. But due to the
3089 * talloc_stackframe pool per SMB2 request this should be a simple copy
3090 * without a malloc in most cases.
3092 if (geteuid() == sec_initial_uid()) {
3093 state->token = root_unix_token(state);
3095 state->token = copy_unix_token(
3097 dir_fsp->conn->session_info->unix_token);
3099 if (tevent_req_nomem(state->token, req)) {
3100 return tevent_req_post(req, ev);
3103 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3105 subreq = pthreadpool_tevent_job_send(
3108 dir_fsp->conn->sconn->pool,
3109 vfswrap_getxattrat_do_async,
3111 if (tevent_req_nomem(subreq, req)) {
3112 return tevent_req_post(req, ev);
3114 tevent_req_set_callback(subreq, vfswrap_getxattrat_done, req);
3116 talloc_set_destructor(state, vfswrap_getxattrat_state_destructor);
3121 static void vfswrap_getxattrat_do_sync(struct tevent_req *req)
3123 struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3124 req, struct vfswrap_getxattrat_state);
3126 char *tofree = NULL;
3127 char pathbuf[PATH_MAX+1];
3131 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
3132 state->smb_fname->base_name,
3137 if (pathlen == -1) {
3138 tevent_req_error(req, ENOMEM);
3142 state->xattr_size = getxattr(path,
3145 talloc_array_length(state->xattr_value));
3147 TALLOC_FREE(tofree);
3148 if (state->xattr_size == -1) {
3149 tevent_req_error(req, err);
3153 tevent_req_done(req);
3157 static void vfswrap_getxattrat_do_async(void *private_data)
3159 struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3160 private_data, struct vfswrap_getxattrat_state);
3161 struct timespec start_time;
3162 struct timespec end_time;
3165 PROFILE_TIMESTAMP(&start_time);
3166 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
3169 * Here we simulate a getxattrat()
3170 * call using fchdir();getxattr()
3173 per_thread_cwd_activate();
3175 /* Become the correct credential on this thread. */
3176 ret = set_thread_credentials(state->token->uid,
3178 (size_t)state->token->ngroups,
3179 state->token->groups);
3181 state->xattr_size = -1;
3182 state->vfs_aio_state.error = errno;
3186 ret = fchdir(state->dir_fsp->fh->fd);
3188 state->xattr_size = -1;
3189 state->vfs_aio_state.error = errno;
3193 state->xattr_size = getxattr(state->name,
3196 talloc_array_length(state->xattr_value));
3197 if (state->xattr_size == -1) {
3198 state->vfs_aio_state.error = errno;
3202 PROFILE_TIMESTAMP(&end_time);
3203 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
3204 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3207 static void vfswrap_getxattrat_done(struct tevent_req *subreq)
3209 struct tevent_req *req = tevent_req_callback_data(
3210 subreq, struct tevent_req);
3211 struct vfswrap_getxattrat_state *state = tevent_req_data(
3212 req, struct vfswrap_getxattrat_state);
3217 * Make sure we run as the user again
3219 ok = change_to_user_by_fsp(state->dir_fsp);
3222 ret = pthreadpool_tevent_job_recv(subreq);
3223 TALLOC_FREE(subreq);
3224 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
3225 talloc_set_destructor(state, NULL);
3227 if (ret != EAGAIN) {
3228 tevent_req_error(req, ret);
3232 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
3233 * means the lower level pthreadpool failed to create a new
3234 * thread. Fallback to sync processing in that case to allow
3235 * some progress for the client.
3237 vfswrap_getxattrat_do_sync(req);
3241 if (state->xattr_size == -1) {
3242 tevent_req_error(req, state->vfs_aio_state.error);
3246 if (state->xattr_value == NULL) {
3248 * The caller only wanted the size.
3250 tevent_req_done(req);
3255 * shrink the buffer to the returned size.
3256 * (can't fail). It means NULL if size is 0.
3258 state->xattr_value = talloc_realloc(state,
3263 tevent_req_done(req);
3266 static ssize_t vfswrap_getxattrat_recv(struct tevent_req *req,
3267 struct vfs_aio_state *aio_state,
3268 TALLOC_CTX *mem_ctx,
3269 uint8_t **xattr_value)
3271 struct vfswrap_getxattrat_state *state = tevent_req_data(
3272 req, struct vfswrap_getxattrat_state);
3275 if (tevent_req_is_unix_error(req, &aio_state->error)) {
3276 tevent_req_received(req);
3280 *aio_state = state->vfs_aio_state;
3281 xattr_size = state->xattr_size;
3282 if (xattr_value != NULL) {
3283 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
3286 tevent_req_received(req);
3290 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
3292 return fgetxattr(fsp->fh->fd, name, value, size);
3295 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
3296 const struct smb_filename *smb_fname,
3300 return listxattr(smb_fname->base_name, list, size);
3303 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
3305 return flistxattr(fsp->fh->fd, list, size);
3308 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
3309 const struct smb_filename *smb_fname,
3312 return removexattr(smb_fname->base_name, name);
3315 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
3317 return fremovexattr(fsp->fh->fd, name);
3320 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
3321 const struct smb_filename *smb_fname,
3327 return setxattr(smb_fname->base_name, name, value, size, flags);
3330 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
3332 return fsetxattr(fsp->fh->fd, name, value, size, flags);
3335 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
3340 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
3341 const struct smb_filename *fname,
3342 SMB_STRUCT_STAT *sbuf)
3346 bool offline = false;
3348 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
3352 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
3353 #if defined(ENOTSUP)
3359 status = get_full_smb_filename(talloc_tos(), fname, &path);
3360 if (!NT_STATUS_IS_OK(status)) {
3361 errno = map_errno_from_nt_status(status);
3365 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
3372 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
3373 struct files_struct *fsp,
3374 TALLOC_CTX *mem_ctx,
3377 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
3380 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
3381 struct files_struct *fsp,
3382 const DATA_BLOB old_cookie,
3383 TALLOC_CTX *mem_ctx,
3384 DATA_BLOB *new_cookie)
3386 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
3390 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
3391 struct smb_request *smb1req,
3392 struct smbXsrv_open *op,
3393 const DATA_BLOB old_cookie,
3394 TALLOC_CTX *mem_ctx,
3395 struct files_struct **fsp,
3396 DATA_BLOB *new_cookie)
3398 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
3399 old_cookie, mem_ctx,
3403 static struct vfs_fn_pointers vfs_default_fns = {
3404 /* Disk operations */
3406 .connect_fn = vfswrap_connect,
3407 .disconnect_fn = vfswrap_disconnect,
3408 .disk_free_fn = vfswrap_disk_free,
3409 .get_quota_fn = vfswrap_get_quota,
3410 .set_quota_fn = vfswrap_set_quota,
3411 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3412 .statvfs_fn = vfswrap_statvfs,
3413 .fs_capabilities_fn = vfswrap_fs_capabilities,
3414 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3415 .snap_check_path_fn = vfswrap_snap_check_path,
3416 .snap_create_fn = vfswrap_snap_create,
3417 .snap_delete_fn = vfswrap_snap_delete,
3419 /* Directory operations */
3421 .opendir_fn = vfswrap_opendir,
3422 .fdopendir_fn = vfswrap_fdopendir,
3423 .readdir_fn = vfswrap_readdir,
3424 .readdir_attr_fn = vfswrap_readdir_attr,
3425 .seekdir_fn = vfswrap_seekdir,
3426 .telldir_fn = vfswrap_telldir,
3427 .rewind_dir_fn = vfswrap_rewinddir,
3428 .mkdir_fn = vfswrap_mkdir,
3429 .rmdir_fn = vfswrap_rmdir,
3430 .closedir_fn = vfswrap_closedir,
3432 /* File operations */
3434 .open_fn = vfswrap_open,
3435 .create_file_fn = vfswrap_create_file,
3436 .close_fn = vfswrap_close,
3437 .pread_fn = vfswrap_pread,
3438 .pread_send_fn = vfswrap_pread_send,
3439 .pread_recv_fn = vfswrap_pread_recv,
3440 .pwrite_fn = vfswrap_pwrite,
3441 .pwrite_send_fn = vfswrap_pwrite_send,
3442 .pwrite_recv_fn = vfswrap_pwrite_recv,
3443 .lseek_fn = vfswrap_lseek,
3444 .sendfile_fn = vfswrap_sendfile,
3445 .recvfile_fn = vfswrap_recvfile,
3446 .renameat_fn = vfswrap_renameat,
3447 .fsync_send_fn = vfswrap_fsync_send,
3448 .fsync_recv_fn = vfswrap_fsync_recv,
3449 .stat_fn = vfswrap_stat,
3450 .fstat_fn = vfswrap_fstat,
3451 .lstat_fn = vfswrap_lstat,
3452 .get_alloc_size_fn = vfswrap_get_alloc_size,
3453 .unlink_fn = vfswrap_unlink,
3454 .chmod_fn = vfswrap_chmod,
3455 .fchmod_fn = vfswrap_fchmod,
3456 .chown_fn = vfswrap_chown,
3457 .fchown_fn = vfswrap_fchown,
3458 .lchown_fn = vfswrap_lchown,
3459 .chdir_fn = vfswrap_chdir,
3460 .getwd_fn = vfswrap_getwd,
3461 .ntimes_fn = vfswrap_ntimes,
3462 .ftruncate_fn = vfswrap_ftruncate,
3463 .fallocate_fn = vfswrap_fallocate,
3464 .lock_fn = vfswrap_lock,
3465 .kernel_flock_fn = vfswrap_kernel_flock,
3466 .linux_setlease_fn = vfswrap_linux_setlease,
3467 .getlock_fn = vfswrap_getlock,
3468 .symlink_fn = vfswrap_symlink,
3469 .readlink_fn = vfswrap_readlink,
3470 .link_fn = vfswrap_link,
3471 .mknod_fn = vfswrap_mknod,
3472 .realpath_fn = vfswrap_realpath,
3473 .chflags_fn = vfswrap_chflags,
3474 .file_id_create_fn = vfswrap_file_id_create,
3475 .fs_file_id_fn = vfswrap_fs_file_id,
3476 .streaminfo_fn = vfswrap_streaminfo,
3477 .get_real_filename_fn = vfswrap_get_real_filename,
3478 .connectpath_fn = vfswrap_connectpath,
3479 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
3480 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3481 .strict_lock_check_fn = vfswrap_strict_lock_check,
3482 .translate_name_fn = vfswrap_translate_name,
3483 .fsctl_fn = vfswrap_fsctl,
3484 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
3485 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
3486 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
3487 .get_dos_attributes_send_fn = vfswrap_get_dos_attributes_send,
3488 .get_dos_attributes_recv_fn = vfswrap_get_dos_attributes_recv,
3489 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
3490 .offload_read_send_fn = vfswrap_offload_read_send,
3491 .offload_read_recv_fn = vfswrap_offload_read_recv,
3492 .offload_write_send_fn = vfswrap_offload_write_send,
3493 .offload_write_recv_fn = vfswrap_offload_write_recv,
3494 .get_compression_fn = vfswrap_get_compression,
3495 .set_compression_fn = vfswrap_set_compression,
3497 /* NT ACL operations. */
3499 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
3500 .get_nt_acl_fn = vfswrap_get_nt_acl,
3501 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
3502 .audit_file_fn = vfswrap_audit_file,
3504 /* POSIX ACL operations. */
3506 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
3507 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3508 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
3509 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3510 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
3511 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3512 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
3514 /* EA operations. */
3515 .getxattr_fn = vfswrap_getxattr,
3516 .getxattrat_send_fn = vfswrap_getxattrat_send,
3517 .getxattrat_recv_fn = vfswrap_getxattrat_recv,
3518 .fgetxattr_fn = vfswrap_fgetxattr,
3519 .listxattr_fn = vfswrap_listxattr,
3520 .flistxattr_fn = vfswrap_flistxattr,
3521 .removexattr_fn = vfswrap_removexattr,
3522 .fremovexattr_fn = vfswrap_fremovexattr,
3523 .setxattr_fn = vfswrap_setxattr,
3524 .fsetxattr_fn = vfswrap_fsetxattr,
3526 /* aio operations */
3527 .aio_force_fn = vfswrap_aio_force,
3529 /* durable handle operations */
3530 .durable_cookie_fn = vfswrap_durable_cookie,
3531 .durable_disconnect_fn = vfswrap_durable_disconnect,
3532 .durable_reconnect_fn = vfswrap_durable_reconnect,
3536 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3539 * Here we need to implement every call!
3541 * As this is the end of the vfs module chain.
3543 smb_vfs_assert_all_fns(&vfs_default_fns, DEFAULT_VFS_MODULE_NAME);
3544 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3545 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);