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 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_rename(vfs_handle_struct *handle,
1071 const struct smb_filename *smb_fname_src,
1072 const struct smb_filename *smb_fname_dst)
1076 START_PROFILE(syscall_rename);
1078 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
1083 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
1086 END_PROFILE(syscall_rename);
1090 static int vfswrap_stat(vfs_handle_struct *handle,
1091 struct smb_filename *smb_fname)
1095 START_PROFILE(syscall_stat);
1097 if (smb_fname->stream_name) {
1102 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1103 lp_fake_directory_create_times(SNUM(handle->conn)));
1105 END_PROFILE(syscall_stat);
1109 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1113 START_PROFILE(syscall_fstat);
1114 result = sys_fstat(fsp->fh->fd,
1115 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1116 END_PROFILE(syscall_fstat);
1120 static int vfswrap_lstat(vfs_handle_struct *handle,
1121 struct smb_filename *smb_fname)
1125 START_PROFILE(syscall_lstat);
1127 if (smb_fname->stream_name) {
1132 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1133 lp_fake_directory_create_times(SNUM(handle->conn)));
1135 END_PROFILE(syscall_lstat);
1139 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1141 enum vfs_translate_direction direction,
1142 TALLOC_CTX *mem_ctx,
1145 return NT_STATUS_NONE_MAPPED;
1149 * Implement the default fsctl operation.
1151 static bool vfswrap_logged_ioctl_message = false;
1153 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1154 struct files_struct *fsp,
1157 uint16_t req_flags, /* Needed for UNICODE ... */
1158 const uint8_t *_in_data,
1160 uint8_t **_out_data,
1161 uint32_t max_out_len,
1164 const char *in_data = (const char *)_in_data;
1165 char **out_data = (char **)_out_data;
1169 case FSCTL_SET_SPARSE:
1171 bool set_sparse = true;
1173 if (in_len >= 1 && in_data[0] == 0) {
1177 status = file_set_sparse(handle->conn, fsp, set_sparse);
1179 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1180 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1181 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1182 nt_errstr(status)));
1187 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1189 unsigned char objid[16];
1190 char *return_data = NULL;
1192 /* This should return the object-id on this file.
1193 * I think I'll make this be the inode+dev. JRA.
1196 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1197 fsp_fnum_dbg(fsp)));
1199 *out_len = MIN(max_out_len, 64);
1201 /* Hmmm, will this cause problems if less data asked for? */
1202 return_data = talloc_array(ctx, char, 64);
1203 if (return_data == NULL) {
1204 return NT_STATUS_NO_MEMORY;
1207 /* For backwards compatibility only store the dev/inode. */
1208 push_file_id_16(return_data, &fsp->file_id);
1209 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1210 push_file_id_16(return_data+32, &fsp->file_id);
1211 memset(return_data+48, 0, 16);
1212 *out_data = return_data;
1213 return NT_STATUS_OK;
1216 case FSCTL_GET_REPARSE_POINT:
1218 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1219 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1220 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1221 return NT_STATUS_NOT_A_REPARSE_POINT;
1224 case FSCTL_SET_REPARSE_POINT:
1226 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1227 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1228 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1229 return NT_STATUS_NOT_A_REPARSE_POINT;
1232 case FSCTL_GET_SHADOW_COPY_DATA:
1235 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1236 * and return their volume names. If max_data_count is 16, then it is just
1237 * asking for the number of volumes and length of the combined names.
1239 * pdata is the data allocated by our caller, but that uses
1240 * total_data_count (which is 0 in our case) rather than max_data_count.
1241 * Allocate the correct amount and return the pointer to let
1242 * it be deallocated when we return.
1244 struct shadow_copy_data *shadow_data = NULL;
1245 bool labels = False;
1246 uint32_t labels_data_count = 0;
1248 char *cur_pdata = NULL;
1250 if (max_out_len < 16) {
1251 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1253 return NT_STATUS_INVALID_PARAMETER;
1256 if (max_out_len > 16) {
1260 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1261 if (shadow_data == NULL) {
1262 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1263 return NT_STATUS_NO_MEMORY;
1267 * Call the VFS routine to actually do the work.
1269 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1272 /* broken module didn't set errno on error */
1273 status = NT_STATUS_UNSUCCESSFUL;
1275 status = map_nt_error_from_unix(errno);
1276 if (NT_STATUS_EQUAL(status,
1277 NT_STATUS_NOT_SUPPORTED)) {
1281 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1282 "connectpath %s, failed - %s.\n",
1283 fsp->conn->connectpath,
1284 nt_errstr(status)));
1285 TALLOC_FREE(shadow_data);
1289 labels_data_count = (shadow_data->num_volumes * 2 *
1290 sizeof(SHADOW_COPY_LABEL)) + 2;
1295 *out_len = 12 + labels_data_count;
1298 if (max_out_len < *out_len) {
1299 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1300 max_out_len, *out_len));
1301 TALLOC_FREE(shadow_data);
1302 return NT_STATUS_BUFFER_TOO_SMALL;
1305 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1306 if (cur_pdata == NULL) {
1307 TALLOC_FREE(shadow_data);
1308 return NT_STATUS_NO_MEMORY;
1311 *out_data = cur_pdata;
1313 /* num_volumes 4 bytes */
1314 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1317 /* num_labels 4 bytes */
1318 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1321 /* needed_data_count 4 bytes */
1322 SIVAL(cur_pdata, 8, labels_data_count);
1326 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1327 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1328 if (labels && shadow_data->labels) {
1329 for (i=0; i<shadow_data->num_volumes; i++) {
1331 status = srvstr_push(cur_pdata, req_flags,
1332 cur_pdata, shadow_data->labels[i],
1333 2 * sizeof(SHADOW_COPY_LABEL),
1334 STR_UNICODE|STR_TERMINATE, &len);
1335 if (!NT_STATUS_IS_OK(status)) {
1336 TALLOC_FREE(*out_data);
1337 TALLOC_FREE(shadow_data);
1340 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1341 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1345 TALLOC_FREE(shadow_data);
1347 return NT_STATUS_OK;
1350 case FSCTL_FIND_FILES_BY_SID:
1352 /* pretend this succeeded -
1354 * we have to send back a list with all files owned by this SID
1356 * but I have to check that --metze
1358 struct sid_parse_ret ret;
1360 struct dom_sid_buf buf;
1364 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1365 fsp_fnum_dbg(fsp)));
1368 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1369 return NT_STATUS_INVALID_PARAMETER;
1372 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1374 /* unknown 4 bytes: this is not the length of the sid :-( */
1375 /*unknown = IVAL(pdata,0);*/
1377 ret = sid_parse(_in_data + 4, sid_len, &sid);
1378 if (ret.len == -1) {
1379 return NT_STATUS_INVALID_PARAMETER;
1381 DEBUGADD(10, ("for SID: %s\n",
1382 dom_sid_str_buf(&sid, &buf)));
1384 if (!sid_to_uid(&sid, &uid)) {
1385 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1386 dom_sid_str_buf(&sid, &buf),
1387 (unsigned long)sid_len));
1391 /* we can take a look at the find source :-)
1393 * find ./ -uid $uid -name '*' is what we need here
1396 * and send 4bytes len and then NULL terminated unicode strings
1399 * but I don't know how to deal with the paged results
1400 * (maybe we can hang the result anywhere in the fsp struct)
1402 * but I don't know how to deal with the paged results
1403 * (maybe we can hang the result anywhere in the fsp struct)
1405 * we don't send all files at once
1406 * and at the next we should *not* start from the beginning,
1407 * so we have to cache the result
1412 /* this works for now... */
1413 return NT_STATUS_OK;
1416 case FSCTL_QUERY_ALLOCATED_RANGES:
1418 /* FIXME: This is just a dummy reply, telling that all of the
1419 * file is allocated. MKS cp needs that.
1420 * Adding the real allocated ranges via FIEMAP on Linux
1421 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1422 * this FSCTL correct for sparse files.
1424 uint64_t offset, length;
1425 char *out_data_tmp = NULL;
1428 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1430 return NT_STATUS_INVALID_PARAMETER;
1433 if (max_out_len < 16) {
1434 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1436 return NT_STATUS_INVALID_PARAMETER;
1439 offset = BVAL(in_data,0);
1440 length = BVAL(in_data,8);
1442 if (offset + length < offset) {
1443 /* No 64-bit integer wrap. */
1444 return NT_STATUS_INVALID_PARAMETER;
1447 /* Shouldn't this be SMB_VFS_STAT ... ? */
1448 status = vfs_stat_fsp(fsp);
1449 if (!NT_STATUS_IS_OK(status)) {
1454 out_data_tmp = talloc_array(ctx, char, *out_len);
1455 if (out_data_tmp == NULL) {
1456 DEBUG(10, ("unable to allocate memory for response\n"));
1457 return NT_STATUS_NO_MEMORY;
1460 if (offset > fsp->fsp_name->st.st_ex_size ||
1461 fsp->fsp_name->st.st_ex_size == 0 ||
1463 memset(out_data_tmp, 0, *out_len);
1465 uint64_t end = offset + length;
1466 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1467 SBVAL(out_data_tmp, 0, 0);
1468 SBVAL(out_data_tmp, 8, end);
1471 *out_data = out_data_tmp;
1473 return NT_STATUS_OK;
1476 case FSCTL_IS_VOLUME_DIRTY:
1478 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1479 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1481 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1482 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1484 return NT_STATUS_INVALID_PARAMETER;
1489 * Only print once ... unfortunately there could be lots of
1490 * different FSCTLs that are called.
1492 if (!vfswrap_logged_ioctl_message) {
1493 vfswrap_logged_ioctl_message = true;
1494 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1495 __func__, function));
1499 return NT_STATUS_NOT_SUPPORTED;
1502 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
1503 const struct smb_filename *fname,
1504 SMB_STRUCT_STAT *sbuf);
1506 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1507 struct smb_filename *smb_fname,
1512 offline = vfswrap_is_offline(handle, smb_fname, &smb_fname->st);
1514 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1517 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1520 struct vfswrap_get_dos_attributes_state {
1521 struct vfs_aio_state aio_state;
1522 connection_struct *conn;
1523 TALLOC_CTX *mem_ctx;
1524 struct tevent_context *ev;
1525 files_struct *dir_fsp;
1526 struct smb_filename *smb_fname;
1531 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq);
1533 static struct tevent_req *vfswrap_get_dos_attributes_send(
1534 TALLOC_CTX *mem_ctx,
1535 struct tevent_context *ev,
1536 struct vfs_handle_struct *handle,
1537 files_struct *dir_fsp,
1538 struct smb_filename *smb_fname)
1540 struct tevent_req *req = NULL;
1541 struct tevent_req *subreq = NULL;
1542 struct vfswrap_get_dos_attributes_state *state = NULL;
1544 req = tevent_req_create(mem_ctx, &state,
1545 struct vfswrap_get_dos_attributes_state);
1550 *state = (struct vfswrap_get_dos_attributes_state) {
1551 .conn = dir_fsp->conn,
1555 .smb_fname = smb_fname,
1558 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1562 SAMBA_XATTR_DOS_ATTRIB,
1564 if (tevent_req_nomem(subreq, req)) {
1565 return tevent_req_post(req, ev);
1567 tevent_req_set_callback(subreq,
1568 vfswrap_get_dos_attributes_getxattr_done,
1574 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq)
1576 struct tevent_req *req =
1577 tevent_req_callback_data(subreq,
1579 struct vfswrap_get_dos_attributes_state *state =
1580 tevent_req_data(req,
1581 struct vfswrap_get_dos_attributes_state);
1583 DATA_BLOB blob = {0};
1586 xattr_size = SMB_VFS_GETXATTRAT_RECV(subreq,
1590 TALLOC_FREE(subreq);
1591 if (xattr_size == -1) {
1592 status = map_nt_error_from_unix(state->aio_state.error);
1594 if (state->as_root) {
1595 tevent_req_nterror(req, status);
1598 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1599 tevent_req_nterror(req, status);
1603 state->as_root = true;
1606 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1610 SAMBA_XATTR_DOS_ATTRIB,
1613 if (tevent_req_nomem(subreq, req)) {
1616 tevent_req_set_callback(subreq,
1617 vfswrap_get_dos_attributes_getxattr_done,
1622 blob.length = xattr_size;
1624 status = parse_dos_attribute_blob(state->smb_fname,
1627 if (!NT_STATUS_IS_OK(status)) {
1628 tevent_req_nterror(req, status);
1632 tevent_req_done(req);
1636 static NTSTATUS vfswrap_get_dos_attributes_recv(struct tevent_req *req,
1637 struct vfs_aio_state *aio_state,
1640 struct vfswrap_get_dos_attributes_state *state =
1641 tevent_req_data(req,
1642 struct vfswrap_get_dos_attributes_state);
1645 if (tevent_req_is_nterror(req, &status)) {
1646 tevent_req_received(req);
1650 *aio_state = state->aio_state;
1651 *dosmode = state->dosmode;
1652 tevent_req_received(req);
1653 return NT_STATUS_OK;
1656 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1657 struct files_struct *fsp,
1662 offline = vfswrap_is_offline(handle, fsp->fsp_name, &fsp->fsp_name->st);
1664 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1667 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1670 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1671 const struct smb_filename *smb_fname,
1674 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1677 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1678 struct files_struct *fsp,
1681 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1684 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1686 struct vfswrap_offload_read_state {
1690 static struct tevent_req *vfswrap_offload_read_send(
1691 TALLOC_CTX *mem_ctx,
1692 struct tevent_context *ev,
1693 struct vfs_handle_struct *handle,
1694 struct files_struct *fsp,
1700 struct tevent_req *req = NULL;
1701 struct vfswrap_offload_read_state *state = NULL;
1704 req = tevent_req_create(mem_ctx, &state,
1705 struct vfswrap_offload_read_state);
1710 status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1711 &vfswrap_offload_ctx);
1712 if (tevent_req_nterror(req, status)) {
1713 return tevent_req_post(req, ev);
1716 if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1717 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1718 return tevent_req_post(req, ev);
1721 status = vfs_offload_token_create_blob(state, fsp, fsctl,
1723 if (tevent_req_nterror(req, status)) {
1724 return tevent_req_post(req, ev);
1727 status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1729 if (tevent_req_nterror(req, status)) {
1730 return tevent_req_post(req, ev);
1733 tevent_req_done(req);
1734 return tevent_req_post(req, ev);
1737 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
1738 struct vfs_handle_struct *handle,
1739 TALLOC_CTX *mem_ctx,
1742 struct vfswrap_offload_read_state *state = tevent_req_data(
1743 req, struct vfswrap_offload_read_state);
1746 if (tevent_req_is_nterror(req, &status)) {
1747 tevent_req_received(req);
1751 token->length = state->token.length;
1752 token->data = talloc_move(mem_ctx, &state->token.data);
1754 tevent_req_received(req);
1755 return NT_STATUS_OK;
1758 struct vfswrap_offload_write_state {
1760 bool read_lck_locked;
1761 bool write_lck_locked;
1763 struct tevent_context *src_ev;
1764 struct files_struct *src_fsp;
1766 struct tevent_context *dst_ev;
1767 struct files_struct *dst_fsp;
1771 size_t next_io_size;
1774 static void vfswrap_offload_write_cleanup(struct tevent_req *req,
1775 enum tevent_req_state req_state)
1777 struct vfswrap_offload_write_state *state = tevent_req_data(
1778 req, struct vfswrap_offload_write_state);
1781 if (state->dst_fsp == NULL) {
1785 ok = change_to_user_by_fsp(state->dst_fsp);
1787 state->dst_fsp = NULL;
1790 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
1792 static struct tevent_req *vfswrap_offload_write_send(
1793 struct vfs_handle_struct *handle,
1794 TALLOC_CTX *mem_ctx,
1795 struct tevent_context *ev,
1798 off_t transfer_offset,
1799 struct files_struct *dest_fsp,
1803 struct tevent_req *req;
1804 struct vfswrap_offload_write_state *state = NULL;
1805 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
1806 files_struct *src_fsp = NULL;
1810 req = tevent_req_create(mem_ctx, &state,
1811 struct vfswrap_offload_write_state);
1816 *state = (struct vfswrap_offload_write_state) {
1818 .src_off = transfer_offset,
1820 .dst_fsp = dest_fsp,
1821 .dst_off = dest_off,
1823 .remaining = to_copy,
1826 tevent_req_set_cleanup_fn(req, vfswrap_offload_write_cleanup);
1829 case FSCTL_SRV_COPYCHUNK:
1830 case FSCTL_SRV_COPYCHUNK_WRITE:
1833 case FSCTL_OFFLOAD_WRITE:
1834 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
1835 return tevent_req_post(req, ev);
1837 case FSCTL_DUP_EXTENTS_TO_FILE:
1838 DBG_DEBUG("COW clones not supported by vfs_default\n");
1839 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1840 return tevent_req_post(req, ev);
1843 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1844 return tevent_req_post(req, ev);
1848 * From here on we assume a copy-chunk fsctl
1852 tevent_req_done(req);
1853 return tevent_req_post(req, ev);
1856 status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
1858 if (tevent_req_nterror(req, status)) {
1859 return tevent_req_post(req, ev);
1862 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
1864 status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
1865 if (!NT_STATUS_IS_OK(status)) {
1866 tevent_req_nterror(req, status);
1867 return tevent_req_post(req, ev);
1870 ok = change_to_user_by_fsp(src_fsp);
1872 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1873 return tevent_req_post(req, ev);
1876 state->src_ev = src_fsp->conn->sconn->ev_ctx;
1877 state->src_fsp = src_fsp;
1879 state->buf = talloc_array(state, uint8_t, num);
1880 if (tevent_req_nomem(state->buf, req)) {
1881 return tevent_req_post(req, ev);
1884 status = vfs_stat_fsp(src_fsp);
1885 if (tevent_req_nterror(req, status)) {
1886 return tevent_req_post(req, ev);
1889 if (src_fsp->fsp_name->st.st_ex_size < state->src_off + num) {
1891 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1892 * If the SourceOffset or SourceOffset + Length extends beyond
1893 * the end of file, the server SHOULD<240> treat this as a
1894 * STATUS_END_OF_FILE error.
1896 * <240> Section 3.3.5.15.6: Windows servers will return
1897 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1899 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1900 return tevent_req_post(req, ev);
1903 status = vfswrap_offload_write_loop(req);
1904 if (!NT_STATUS_IS_OK(status)) {
1905 tevent_req_nterror(req, status);
1906 return tevent_req_post(req, ev);
1912 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
1914 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
1916 struct vfswrap_offload_write_state *state = tevent_req_data(
1917 req, struct vfswrap_offload_write_state);
1918 struct tevent_req *subreq = NULL;
1919 struct lock_struct read_lck;
1923 * This is called under the context of state->src_fsp.
1926 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
1928 init_strict_lock_struct(state->src_fsp,
1929 state->src_fsp->op->global->open_persistent_id,
1931 state->next_io_size,
1935 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
1939 return NT_STATUS_FILE_LOCK_CONFLICT;
1942 subreq = SMB_VFS_PREAD_SEND(state,
1946 state->next_io_size,
1948 if (subreq == NULL) {
1949 return NT_STATUS_NO_MEMORY;
1951 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
1953 return NT_STATUS_OK;
1956 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
1958 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
1960 struct tevent_req *req = tevent_req_callback_data(
1961 subreq, struct tevent_req);
1962 struct vfswrap_offload_write_state *state = tevent_req_data(
1963 req, struct vfswrap_offload_write_state);
1964 struct vfs_aio_state aio_state;
1965 struct lock_struct write_lck;
1969 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
1970 TALLOC_FREE(subreq);
1972 DBG_ERR("read failed: %s\n", strerror(errno));
1973 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1976 if (nread != state->next_io_size) {
1977 DBG_ERR("Short read, only %zd of %zu\n",
1978 nread, state->next_io_size);
1979 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1983 state->src_off += nread;
1985 ok = change_to_user_by_fsp(state->dst_fsp);
1987 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1991 init_strict_lock_struct(state->dst_fsp,
1992 state->dst_fsp->op->global->open_persistent_id,
1994 state->next_io_size,
1998 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
2002 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
2006 subreq = SMB_VFS_PWRITE_SEND(state,
2010 state->next_io_size,
2012 if (subreq == NULL) {
2013 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2016 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
2019 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
2021 struct tevent_req *req = tevent_req_callback_data(
2022 subreq, struct tevent_req);
2023 struct vfswrap_offload_write_state *state = tevent_req_data(
2024 req, struct vfswrap_offload_write_state);
2025 struct vfs_aio_state aio_state;
2030 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
2031 TALLOC_FREE(subreq);
2032 if (nwritten == -1) {
2033 DBG_ERR("write failed: %s\n", strerror(errno));
2034 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2037 if (nwritten != state->next_io_size) {
2038 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
2039 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2043 state->dst_off += nwritten;
2045 if (state->remaining < nwritten) {
2046 /* Paranoia check */
2047 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2050 state->remaining -= nwritten;
2051 if (state->remaining == 0) {
2052 tevent_req_done(req);
2056 ok = change_to_user_by_fsp(state->src_fsp);
2058 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2062 status = vfswrap_offload_write_loop(req);
2063 if (!NT_STATUS_IS_OK(status)) {
2064 tevent_req_nterror(req, status);
2071 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
2072 struct tevent_req *req,
2075 struct vfswrap_offload_write_state *state = tevent_req_data(
2076 req, struct vfswrap_offload_write_state);
2079 if (tevent_req_is_nterror(req, &status)) {
2080 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
2082 tevent_req_received(req);
2086 *copied = state->to_copy;
2087 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
2088 tevent_req_received(req);
2090 return NT_STATUS_OK;
2093 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
2094 TALLOC_CTX *mem_ctx,
2095 struct files_struct *fsp,
2096 struct smb_filename *smb_fname,
2097 uint16_t *_compression_fmt)
2099 return NT_STATUS_INVALID_DEVICE_REQUEST;
2102 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
2103 TALLOC_CTX *mem_ctx,
2104 struct files_struct *fsp,
2105 uint16_t compression_fmt)
2107 return NT_STATUS_INVALID_DEVICE_REQUEST;
2110 /********************************************************************
2111 Given a stat buffer return the allocated size on disk, taking into
2112 account sparse files.
2113 ********************************************************************/
2114 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
2115 struct files_struct *fsp,
2116 const SMB_STRUCT_STAT *sbuf)
2120 START_PROFILE(syscall_get_alloc_size);
2122 if(S_ISDIR(sbuf->st_ex_mode)) {
2127 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2128 /* The type of st_blocksize is blkcnt_t which *MUST* be
2129 signed (according to POSIX) and can be less than 64-bits.
2130 Ensure when we're converting to 64 bits wide we don't
2132 #if defined(SIZEOF_BLKCNT_T_8)
2133 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2134 #elif defined(SIZEOF_BLKCNT_T_4)
2136 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2137 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2140 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2144 * Some file systems do not allocate a block for very
2145 * small files. But for non-empty file should report a
2149 uint64_t filesize = get_file_size_stat(sbuf);
2151 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2155 result = get_file_size_stat(sbuf);
2158 if (fsp && fsp->initial_allocation_size)
2159 result = MAX(result,fsp->initial_allocation_size);
2161 result = smb_roundup(handle->conn, result);
2164 END_PROFILE(syscall_get_alloc_size);
2168 static int vfswrap_unlink(vfs_handle_struct *handle,
2169 const struct smb_filename *smb_fname)
2173 START_PROFILE(syscall_unlink);
2175 if (smb_fname->stream_name) {
2179 result = unlink(smb_fname->base_name);
2182 END_PROFILE(syscall_unlink);
2186 static int vfswrap_chmod(vfs_handle_struct *handle,
2187 const struct smb_filename *smb_fname,
2192 START_PROFILE(syscall_chmod);
2193 result = chmod(smb_fname->base_name, mode);
2194 END_PROFILE(syscall_chmod);
2198 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2202 START_PROFILE(syscall_fchmod);
2203 #if defined(HAVE_FCHMOD)
2204 result = fchmod(fsp->fh->fd, mode);
2210 END_PROFILE(syscall_fchmod);
2214 static int vfswrap_chown(vfs_handle_struct *handle,
2215 const struct smb_filename *smb_fname,
2221 START_PROFILE(syscall_chown);
2222 result = chown(smb_fname->base_name, uid, gid);
2223 END_PROFILE(syscall_chown);
2227 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2232 START_PROFILE(syscall_fchown);
2233 result = fchown(fsp->fh->fd, uid, gid);
2234 END_PROFILE(syscall_fchown);
2242 static int vfswrap_lchown(vfs_handle_struct *handle,
2243 const struct smb_filename *smb_fname,
2249 START_PROFILE(syscall_lchown);
2250 result = lchown(smb_fname->base_name, uid, gid);
2251 END_PROFILE(syscall_lchown);
2255 static int vfswrap_chdir(vfs_handle_struct *handle,
2256 const struct smb_filename *smb_fname)
2260 START_PROFILE(syscall_chdir);
2261 result = chdir(smb_fname->base_name);
2262 END_PROFILE(syscall_chdir);
2266 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2270 struct smb_filename *smb_fname = NULL;
2272 START_PROFILE(syscall_getwd);
2273 result = sys_getwd();
2274 END_PROFILE(syscall_getwd);
2276 if (result == NULL) {
2279 smb_fname = synthetic_smb_fname(ctx,
2285 * sys_getwd() *always* returns malloced memory.
2286 * We must free here to avoid leaks:
2287 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2293 /*********************************************************************
2294 nsec timestamp resolution call. Convert down to whatever the underlying
2295 system will support.
2296 **********************************************************************/
2298 static int vfswrap_ntimes(vfs_handle_struct *handle,
2299 const struct smb_filename *smb_fname,
2300 struct smb_file_time *ft)
2304 START_PROFILE(syscall_ntimes);
2306 if (smb_fname->stream_name) {
2312 if (null_timespec(ft->atime)) {
2313 ft->atime= smb_fname->st.st_ex_atime;
2316 if (null_timespec(ft->mtime)) {
2317 ft->mtime = smb_fname->st.st_ex_mtime;
2320 if (!null_timespec(ft->create_time)) {
2321 set_create_timespec_ea(handle->conn,
2326 if ((timespec_compare(&ft->atime,
2327 &smb_fname->st.st_ex_atime) == 0) &&
2328 (timespec_compare(&ft->mtime,
2329 &smb_fname->st.st_ex_mtime) == 0)) {
2334 #if defined(HAVE_UTIMENSAT)
2336 struct timespec ts[2];
2339 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2341 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2343 if (!((result == -1) && (errno == ENOSYS))) {
2347 #if defined(HAVE_UTIMES)
2349 struct timeval tv[2];
2350 tv[0] = convert_timespec_to_timeval(ft->atime);
2351 tv[1] = convert_timespec_to_timeval(ft->mtime);
2352 result = utimes(smb_fname->base_name, tv);
2354 result = utimes(smb_fname->base_name, NULL);
2356 if (!((result == -1) && (errno == ENOSYS))) {
2360 #if defined(HAVE_UTIME)
2362 struct utimbuf times;
2363 times.actime = convert_timespec_to_time_t(ft->atime);
2364 times.modtime = convert_timespec_to_time_t(ft->mtime);
2365 result = utime(smb_fname->base_name, ×);
2367 result = utime(smb_fname->base_name, NULL);
2369 if (!((result == -1) && (errno == ENOSYS))) {
2377 END_PROFILE(syscall_ntimes);
2381 /*********************************************************************
2382 A version of ftruncate that will write the space on disk if strict
2384 **********************************************************************/
2386 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2388 off_t space_to_write;
2389 uint64_t space_avail;
2390 uint64_t bsize,dfree,dsize;
2393 SMB_STRUCT_STAT *pst;
2395 status = vfs_stat_fsp(fsp);
2396 if (!NT_STATUS_IS_OK(status)) {
2399 pst = &fsp->fsp_name->st;
2402 if (S_ISFIFO(pst->st_ex_mode))
2406 if (pst->st_ex_size == len)
2409 /* Shrink - just ftruncate. */
2410 if (pst->st_ex_size > len)
2411 return ftruncate(fsp->fh->fd, len);
2413 space_to_write = len - pst->st_ex_size;
2415 /* for allocation try fallocate first. This can fail on some
2416 platforms e.g. when the filesystem doesn't support it and no
2417 emulation is being done by the libc (like on AIX with JFS1). In that
2418 case we do our own emulation. fallocate implementations can
2419 return ENOTSUP or EINVAL in cases like that. */
2420 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2421 if (ret == -1 && errno == ENOSPC) {
2427 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2428 "error %d. Falling back to slow manual allocation\n", errno));
2430 /* available disk space is enough or not? */
2432 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2433 /* space_avail is 1k blocks */
2434 if (space_avail == (uint64_t)-1 ||
2435 ((uint64_t)space_to_write/1024 > space_avail) ) {
2440 /* Write out the real space on disk. */
2441 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2449 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2452 SMB_STRUCT_STAT *pst;
2456 START_PROFILE(syscall_ftruncate);
2458 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2459 result = strict_allocate_ftruncate(handle, fsp, len);
2460 END_PROFILE(syscall_ftruncate);
2464 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2465 ftruncate if the system supports it. Then I discovered that
2466 you can have some filesystems that support ftruncate
2467 expansion and some that don't! On Linux fat can't do
2468 ftruncate extend but ext2 can. */
2470 result = ftruncate(fsp->fh->fd, len);
2472 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2473 extend a file with ftruncate. Provide alternate implementation
2476 /* Do an fstat to see if the file is longer than the requested
2477 size in which case the ftruncate above should have
2478 succeeded or shorter, in which case seek to len - 1 and
2479 write 1 byte of zero */
2480 status = vfs_stat_fsp(fsp);
2481 if (!NT_STATUS_IS_OK(status)) {
2485 /* We need to update the files_struct after successful ftruncate */
2490 pst = &fsp->fsp_name->st;
2493 if (S_ISFIFO(pst->st_ex_mode)) {
2499 if (pst->st_ex_size == len) {
2504 if (pst->st_ex_size > len) {
2505 /* the ftruncate should have worked */
2509 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2517 END_PROFILE(syscall_ftruncate);
2521 static int vfswrap_fallocate(vfs_handle_struct *handle,
2529 START_PROFILE(syscall_fallocate);
2531 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2533 * posix_fallocate returns 0 on success, errno on error
2534 * and doesn't set errno. Make it behave like fallocate()
2535 * which returns -1, and sets errno on failure.
2542 /* sys_fallocate handles filtering of unsupported mode flags */
2543 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2545 END_PROFILE(syscall_fallocate);
2549 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2553 START_PROFILE(syscall_fcntl_lock);
2555 if (fsp->use_ofd_locks) {
2556 op = map_process_lock_to_ofd_lock(op);
2559 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2560 END_PROFILE(syscall_fcntl_lock);
2564 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2565 uint32_t share_mode, uint32_t access_mask)
2567 START_PROFILE(syscall_kernel_flock);
2568 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2569 END_PROFILE(syscall_kernel_flock);
2573 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2578 START_PROFILE(syscall_fcntl_getlock);
2580 if (fsp->use_ofd_locks) {
2581 op = map_process_lock_to_ofd_lock(op);
2584 result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2585 END_PROFILE(syscall_fcntl_getlock);
2589 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2594 START_PROFILE(syscall_linux_setlease);
2596 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2597 result = linux_setlease(fsp->fh->fd, leasetype);
2601 END_PROFILE(syscall_linux_setlease);
2605 static int vfswrap_symlink(vfs_handle_struct *handle,
2606 const char *link_target,
2607 const struct smb_filename *new_smb_fname)
2611 START_PROFILE(syscall_symlink);
2612 result = symlink(link_target, new_smb_fname->base_name);
2613 END_PROFILE(syscall_symlink);
2617 static int vfswrap_readlink(vfs_handle_struct *handle,
2618 const struct smb_filename *smb_fname,
2624 START_PROFILE(syscall_readlink);
2625 result = readlink(smb_fname->base_name, buf, bufsiz);
2626 END_PROFILE(syscall_readlink);
2630 static int vfswrap_link(vfs_handle_struct *handle,
2631 const struct smb_filename *old_smb_fname,
2632 const struct smb_filename *new_smb_fname)
2636 START_PROFILE(syscall_link);
2637 result = link(old_smb_fname->base_name, new_smb_fname->base_name);
2638 END_PROFILE(syscall_link);
2642 static int vfswrap_mknod(vfs_handle_struct *handle,
2643 const struct smb_filename *smb_fname,
2649 START_PROFILE(syscall_mknod);
2650 result = sys_mknod(smb_fname->base_name, mode, dev);
2651 END_PROFILE(syscall_mknod);
2655 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2657 const struct smb_filename *smb_fname)
2660 struct smb_filename *result_fname = NULL;
2662 START_PROFILE(syscall_realpath);
2663 result = sys_realpath(smb_fname->base_name);
2664 END_PROFILE(syscall_realpath);
2666 result_fname = synthetic_smb_fname(ctx, result, NULL, NULL, 0);
2669 return result_fname;
2672 static int vfswrap_chflags(vfs_handle_struct *handle,
2673 const struct smb_filename *smb_fname,
2677 return chflags(smb_fname->base_name, flags);
2684 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2685 const SMB_STRUCT_STAT *sbuf)
2689 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2693 key.devid = sbuf->st_ex_dev;
2694 key.inode = sbuf->st_ex_ino;
2695 /* key.extid is unused by default. */
2700 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2701 struct files_struct *fsp,
2702 const struct smb_filename *smb_fname,
2703 TALLOC_CTX *mem_ctx,
2704 unsigned int *pnum_streams,
2705 struct stream_struct **pstreams)
2707 SMB_STRUCT_STAT sbuf;
2708 struct stream_struct *tmp_streams = NULL;
2711 if ((fsp != NULL) && (fsp->is_directory)) {
2713 * No default streams on directories
2718 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2719 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2722 struct smb_filename smb_fname_cp;
2724 ZERO_STRUCT(smb_fname_cp);
2725 smb_fname_cp.base_name = discard_const_p(char,
2726 smb_fname->base_name);
2727 smb_fname_cp.flags = smb_fname->flags;
2729 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
2730 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2732 ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2734 sbuf = smb_fname_cp.st;
2738 return map_nt_error_from_unix(errno);
2741 if (S_ISDIR(sbuf.st_ex_mode)) {
2745 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2746 (*pnum_streams) + 1);
2747 if (tmp_streams == NULL) {
2748 return NT_STATUS_NO_MEMORY;
2750 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2751 if (tmp_streams[*pnum_streams].name == NULL) {
2752 return NT_STATUS_NO_MEMORY;
2754 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2755 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2758 *pstreams = tmp_streams;
2760 return NT_STATUS_OK;
2763 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2766 TALLOC_CTX *mem_ctx,
2770 * Don't fall back to get_real_filename so callers can differentiate
2771 * between a full directory scan and an actual case-insensitive stat.
2777 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2778 const struct smb_filename *smb_fname)
2780 return handle->conn->connectpath;
2783 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2784 struct byte_range_lock *br_lck,
2785 struct lock_struct *plock,
2788 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2790 /* Note: blr is not used in the default implementation. */
2791 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2794 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2795 struct messaging_context *msg_ctx,
2796 struct byte_range_lock *br_lck,
2797 const struct lock_struct *plock)
2799 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2801 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2804 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2805 struct byte_range_lock *br_lck,
2806 struct lock_struct *plock)
2808 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2810 /* Note: blr is not used in the default implementation. */
2811 return brl_lock_cancel_default(br_lck, plock);
2814 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
2816 struct lock_struct *plock)
2818 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2819 plock->lock_type == WRITE_LOCK);
2821 return strict_lock_check_default(fsp, plock);
2824 /* NT ACL operations. */
2826 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2828 uint32_t security_info,
2829 TALLOC_CTX *mem_ctx,
2830 struct security_descriptor **ppdesc)
2834 START_PROFILE(fget_nt_acl);
2835 result = posix_fget_nt_acl(fsp, security_info,
2837 END_PROFILE(fget_nt_acl);
2841 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2842 const struct smb_filename *smb_fname,
2843 uint32_t security_info,
2844 TALLOC_CTX *mem_ctx,
2845 struct security_descriptor **ppdesc)
2849 START_PROFILE(get_nt_acl);
2850 result = posix_get_nt_acl(handle->conn,
2855 END_PROFILE(get_nt_acl);
2859 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2863 START_PROFILE(fset_nt_acl);
2864 result = set_nt_acl(fsp, security_info_sent, psd);
2865 END_PROFILE(fset_nt_acl);
2869 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2870 struct smb_filename *file,
2871 struct security_acl *sacl,
2872 uint32_t access_requested,
2873 uint32_t access_denied)
2875 return NT_STATUS_OK; /* Nothing to do here ... */
2878 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2879 const struct smb_filename *smb_fname,
2880 SMB_ACL_TYPE_T type,
2881 TALLOC_CTX *mem_ctx)
2883 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
2886 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2888 TALLOC_CTX *mem_ctx)
2890 return sys_acl_get_fd(handle, fsp, mem_ctx);
2893 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
2894 const struct smb_filename *smb_fname,
2895 SMB_ACL_TYPE_T acltype,
2898 return sys_acl_set_file(handle, smb_fname, acltype, theacl);
2901 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2903 return sys_acl_set_fd(handle, fsp, theacl);
2906 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
2907 const struct smb_filename *smb_fname)
2909 return sys_acl_delete_def_file(handle, smb_fname);
2912 /****************************************************************
2913 Extended attribute operations.
2914 *****************************************************************/
2916 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
2917 const struct smb_filename *smb_fname,
2922 return getxattr(smb_fname->base_name, name, value, size);
2925 struct vfswrap_getxattrat_state {
2926 struct tevent_context *ev;
2927 files_struct *dir_fsp;
2928 const struct smb_filename *smb_fname;
2929 struct tevent_req *req;
2932 * The following variables are talloced off "state" which is protected
2933 * by a destructor and thus are guaranteed to be safe to be used in the
2934 * job function in the worker thread.
2937 const char *xattr_name;
2938 uint8_t *xattr_value;
2939 struct security_unix_token *token;
2942 struct vfs_aio_state vfs_aio_state;
2943 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
2946 static int vfswrap_getxattrat_state_destructor(
2947 struct vfswrap_getxattrat_state *state)
2952 static void vfswrap_getxattrat_do_sync(struct tevent_req *req);
2953 static void vfswrap_getxattrat_do_async(void *private_data);
2954 static void vfswrap_getxattrat_done(struct tevent_req *subreq);
2956 static struct tevent_req *vfswrap_getxattrat_send(
2957 TALLOC_CTX *mem_ctx,
2958 struct tevent_context *ev,
2959 struct vfs_handle_struct *handle,
2960 files_struct *dir_fsp,
2961 const struct smb_filename *smb_fname,
2962 const char *xattr_name,
2965 struct tevent_req *req = NULL;
2966 struct tevent_req *subreq = NULL;
2967 struct vfswrap_getxattrat_state *state = NULL;
2968 size_t max_threads = 0;
2969 bool have_per_thread_cwd = false;
2970 bool have_per_thread_creds = false;
2971 bool do_async = false;
2973 req = tevent_req_create(mem_ctx, &state,
2974 struct vfswrap_getxattrat_state);
2978 *state = (struct vfswrap_getxattrat_state) {
2981 .smb_fname = smb_fname,
2985 max_threads = pthreadpool_tevent_max_threads(dir_fsp->conn->sconn->pool);
2986 if (max_threads >= 1) {
2988 * We need a non sync threadpool!
2990 have_per_thread_cwd = per_thread_cwd_supported();
2992 #ifdef HAVE_LINUX_THREAD_CREDENTIALS
2993 have_per_thread_creds = true;
2995 if (have_per_thread_cwd && have_per_thread_creds) {
2999 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat, profile_p,
3000 state->profile_bytes, 0);
3002 if (dir_fsp->fh->fd == -1) {
3003 DBG_ERR("Need a valid directory fd\n");
3004 tevent_req_error(req, EINVAL);
3005 return tevent_req_post(req, ev);
3008 if (alloc_hint > 0) {
3009 state->xattr_value = talloc_zero_array(state,
3012 if (tevent_req_nomem(state->xattr_value, req)) {
3013 return tevent_req_post(req, ev);
3018 vfswrap_getxattrat_do_sync(req);
3019 return tevent_req_post(req, ev);
3023 * Now allocate all parameters from a memory context that won't go away
3024 * no matter what. These paremeters will get used in threads and we
3025 * can't reliably cancel threads, so all buffers passed to the threads
3026 * must not be freed before all referencing threads terminate.
3029 state->name = talloc_strdup(state, smb_fname->base_name);
3030 if (tevent_req_nomem(state->name, req)) {
3031 return tevent_req_post(req, ev);
3034 state->xattr_name = talloc_strdup(state, xattr_name);
3035 if (tevent_req_nomem(state->xattr_name, req)) {
3036 return tevent_req_post(req, ev);
3040 * This is a hot codepath so at first glance one might think we should
3041 * somehow optimize away the token allocation and do a
3042 * talloc_reference() or similar black magic instead. But due to the
3043 * talloc_stackframe pool per SMB2 request this should be a simple copy
3044 * without a malloc in most cases.
3046 if (geteuid() == sec_initial_uid()) {
3047 state->token = root_unix_token(state);
3049 state->token = copy_unix_token(
3051 dir_fsp->conn->session_info->unix_token);
3053 if (tevent_req_nomem(state->token, req)) {
3054 return tevent_req_post(req, ev);
3057 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3059 subreq = pthreadpool_tevent_job_send(
3062 dir_fsp->conn->sconn->pool,
3063 vfswrap_getxattrat_do_async,
3065 if (tevent_req_nomem(subreq, req)) {
3066 return tevent_req_post(req, ev);
3068 tevent_req_set_callback(subreq, vfswrap_getxattrat_done, req);
3070 talloc_set_destructor(state, vfswrap_getxattrat_state_destructor);
3075 static void vfswrap_getxattrat_do_sync(struct tevent_req *req)
3077 struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3078 req, struct vfswrap_getxattrat_state);
3080 char *tofree = NULL;
3081 char pathbuf[PATH_MAX+1];
3085 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
3086 state->smb_fname->base_name,
3091 if (pathlen == -1) {
3092 tevent_req_error(req, ENOMEM);
3096 state->xattr_size = getxattr(path,
3099 talloc_array_length(state->xattr_value));
3101 TALLOC_FREE(tofree);
3102 if (state->xattr_size == -1) {
3103 tevent_req_error(req, err);
3107 tevent_req_done(req);
3111 static void vfswrap_getxattrat_do_async(void *private_data)
3113 struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3114 private_data, struct vfswrap_getxattrat_state);
3115 struct timespec start_time;
3116 struct timespec end_time;
3119 PROFILE_TIMESTAMP(&start_time);
3120 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
3123 * Here we simulate a getxattrat()
3124 * call using fchdir();getxattr()
3127 per_thread_cwd_activate();
3129 /* Become the correct credential on this thread. */
3130 ret = set_thread_credentials(state->token->uid,
3132 (size_t)state->token->ngroups,
3133 state->token->groups);
3135 state->xattr_size = -1;
3136 state->vfs_aio_state.error = errno;
3140 ret = fchdir(state->dir_fsp->fh->fd);
3142 state->xattr_size = -1;
3143 state->vfs_aio_state.error = errno;
3147 state->xattr_size = getxattr(state->name,
3150 talloc_array_length(state->xattr_value));
3151 if (state->xattr_size == -1) {
3152 state->vfs_aio_state.error = errno;
3156 PROFILE_TIMESTAMP(&end_time);
3157 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
3158 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3161 static void vfswrap_getxattrat_done(struct tevent_req *subreq)
3163 struct tevent_req *req = tevent_req_callback_data(
3164 subreq, struct tevent_req);
3165 struct vfswrap_getxattrat_state *state = tevent_req_data(
3166 req, struct vfswrap_getxattrat_state);
3171 * Make sure we run as the user again
3173 ok = change_to_user_by_fsp(state->dir_fsp);
3176 ret = pthreadpool_tevent_job_recv(subreq);
3177 TALLOC_FREE(subreq);
3178 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
3179 talloc_set_destructor(state, NULL);
3181 if (ret != EAGAIN) {
3182 tevent_req_error(req, ret);
3186 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
3187 * means the lower level pthreadpool failed to create a new
3188 * thread. Fallback to sync processing in that case to allow
3189 * some progress for the client.
3191 vfswrap_getxattrat_do_sync(req);
3195 if (state->xattr_size == -1) {
3196 tevent_req_error(req, state->vfs_aio_state.error);
3200 if (state->xattr_value == NULL) {
3202 * The caller only wanted the size.
3204 tevent_req_done(req);
3209 * shrink the buffer to the returned size.
3210 * (can't fail). It means NULL if size is 0.
3212 state->xattr_value = talloc_realloc(state,
3217 tevent_req_done(req);
3220 static ssize_t vfswrap_getxattrat_recv(struct tevent_req *req,
3221 struct vfs_aio_state *aio_state,
3222 TALLOC_CTX *mem_ctx,
3223 uint8_t **xattr_value)
3225 struct vfswrap_getxattrat_state *state = tevent_req_data(
3226 req, struct vfswrap_getxattrat_state);
3229 if (tevent_req_is_unix_error(req, &aio_state->error)) {
3230 tevent_req_received(req);
3234 *aio_state = state->vfs_aio_state;
3235 xattr_size = state->xattr_size;
3236 if (xattr_value != NULL) {
3237 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
3240 tevent_req_received(req);
3244 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
3246 return fgetxattr(fsp->fh->fd, name, value, size);
3249 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
3250 const struct smb_filename *smb_fname,
3254 return listxattr(smb_fname->base_name, list, size);
3257 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
3259 return flistxattr(fsp->fh->fd, list, size);
3262 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
3263 const struct smb_filename *smb_fname,
3266 return removexattr(smb_fname->base_name, name);
3269 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
3271 return fremovexattr(fsp->fh->fd, name);
3274 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
3275 const struct smb_filename *smb_fname,
3281 return setxattr(smb_fname->base_name, name, value, size, flags);
3284 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
3286 return fsetxattr(fsp->fh->fd, name, value, size, flags);
3289 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
3294 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
3295 const struct smb_filename *fname,
3296 SMB_STRUCT_STAT *sbuf)
3300 bool offline = false;
3302 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
3306 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
3307 #if defined(ENOTSUP)
3313 status = get_full_smb_filename(talloc_tos(), fname, &path);
3314 if (!NT_STATUS_IS_OK(status)) {
3315 errno = map_errno_from_nt_status(status);
3319 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
3326 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
3327 struct files_struct *fsp,
3328 TALLOC_CTX *mem_ctx,
3331 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
3334 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
3335 struct files_struct *fsp,
3336 const DATA_BLOB old_cookie,
3337 TALLOC_CTX *mem_ctx,
3338 DATA_BLOB *new_cookie)
3340 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
3344 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
3345 struct smb_request *smb1req,
3346 struct smbXsrv_open *op,
3347 const DATA_BLOB old_cookie,
3348 TALLOC_CTX *mem_ctx,
3349 struct files_struct **fsp,
3350 DATA_BLOB *new_cookie)
3352 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
3353 old_cookie, mem_ctx,
3357 static struct vfs_fn_pointers vfs_default_fns = {
3358 /* Disk operations */
3360 .connect_fn = vfswrap_connect,
3361 .disconnect_fn = vfswrap_disconnect,
3362 .disk_free_fn = vfswrap_disk_free,
3363 .get_quota_fn = vfswrap_get_quota,
3364 .set_quota_fn = vfswrap_set_quota,
3365 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3366 .statvfs_fn = vfswrap_statvfs,
3367 .fs_capabilities_fn = vfswrap_fs_capabilities,
3368 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3369 .snap_check_path_fn = vfswrap_snap_check_path,
3370 .snap_create_fn = vfswrap_snap_create,
3371 .snap_delete_fn = vfswrap_snap_delete,
3373 /* Directory operations */
3375 .opendir_fn = vfswrap_opendir,
3376 .fdopendir_fn = vfswrap_fdopendir,
3377 .readdir_fn = vfswrap_readdir,
3378 .readdir_attr_fn = vfswrap_readdir_attr,
3379 .seekdir_fn = vfswrap_seekdir,
3380 .telldir_fn = vfswrap_telldir,
3381 .rewind_dir_fn = vfswrap_rewinddir,
3382 .mkdir_fn = vfswrap_mkdir,
3383 .rmdir_fn = vfswrap_rmdir,
3384 .closedir_fn = vfswrap_closedir,
3386 /* File operations */
3388 .open_fn = vfswrap_open,
3389 .create_file_fn = vfswrap_create_file,
3390 .close_fn = vfswrap_close,
3391 .pread_fn = vfswrap_pread,
3392 .pread_send_fn = vfswrap_pread_send,
3393 .pread_recv_fn = vfswrap_pread_recv,
3394 .pwrite_fn = vfswrap_pwrite,
3395 .pwrite_send_fn = vfswrap_pwrite_send,
3396 .pwrite_recv_fn = vfswrap_pwrite_recv,
3397 .lseek_fn = vfswrap_lseek,
3398 .sendfile_fn = vfswrap_sendfile,
3399 .recvfile_fn = vfswrap_recvfile,
3400 .rename_fn = vfswrap_rename,
3401 .fsync_send_fn = vfswrap_fsync_send,
3402 .fsync_recv_fn = vfswrap_fsync_recv,
3403 .stat_fn = vfswrap_stat,
3404 .fstat_fn = vfswrap_fstat,
3405 .lstat_fn = vfswrap_lstat,
3406 .get_alloc_size_fn = vfswrap_get_alloc_size,
3407 .unlink_fn = vfswrap_unlink,
3408 .chmod_fn = vfswrap_chmod,
3409 .fchmod_fn = vfswrap_fchmod,
3410 .chown_fn = vfswrap_chown,
3411 .fchown_fn = vfswrap_fchown,
3412 .lchown_fn = vfswrap_lchown,
3413 .chdir_fn = vfswrap_chdir,
3414 .getwd_fn = vfswrap_getwd,
3415 .ntimes_fn = vfswrap_ntimes,
3416 .ftruncate_fn = vfswrap_ftruncate,
3417 .fallocate_fn = vfswrap_fallocate,
3418 .lock_fn = vfswrap_lock,
3419 .kernel_flock_fn = vfswrap_kernel_flock,
3420 .linux_setlease_fn = vfswrap_linux_setlease,
3421 .getlock_fn = vfswrap_getlock,
3422 .symlink_fn = vfswrap_symlink,
3423 .readlink_fn = vfswrap_readlink,
3424 .link_fn = vfswrap_link,
3425 .mknod_fn = vfswrap_mknod,
3426 .realpath_fn = vfswrap_realpath,
3427 .chflags_fn = vfswrap_chflags,
3428 .file_id_create_fn = vfswrap_file_id_create,
3429 .streaminfo_fn = vfswrap_streaminfo,
3430 .get_real_filename_fn = vfswrap_get_real_filename,
3431 .connectpath_fn = vfswrap_connectpath,
3432 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
3433 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3434 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
3435 .strict_lock_check_fn = vfswrap_strict_lock_check,
3436 .translate_name_fn = vfswrap_translate_name,
3437 .fsctl_fn = vfswrap_fsctl,
3438 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
3439 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
3440 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
3441 .get_dos_attributes_send_fn = vfswrap_get_dos_attributes_send,
3442 .get_dos_attributes_recv_fn = vfswrap_get_dos_attributes_recv,
3443 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
3444 .offload_read_send_fn = vfswrap_offload_read_send,
3445 .offload_read_recv_fn = vfswrap_offload_read_recv,
3446 .offload_write_send_fn = vfswrap_offload_write_send,
3447 .offload_write_recv_fn = vfswrap_offload_write_recv,
3448 .get_compression_fn = vfswrap_get_compression,
3449 .set_compression_fn = vfswrap_set_compression,
3451 /* NT ACL operations. */
3453 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
3454 .get_nt_acl_fn = vfswrap_get_nt_acl,
3455 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
3456 .audit_file_fn = vfswrap_audit_file,
3458 /* POSIX ACL operations. */
3460 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
3461 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3462 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
3463 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3464 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
3465 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3466 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
3468 /* EA operations. */
3469 .getxattr_fn = vfswrap_getxattr,
3470 .getxattrat_send_fn = vfswrap_getxattrat_send,
3471 .getxattrat_recv_fn = vfswrap_getxattrat_recv,
3472 .fgetxattr_fn = vfswrap_fgetxattr,
3473 .listxattr_fn = vfswrap_listxattr,
3474 .flistxattr_fn = vfswrap_flistxattr,
3475 .removexattr_fn = vfswrap_removexattr,
3476 .fremovexattr_fn = vfswrap_fremovexattr,
3477 .setxattr_fn = vfswrap_setxattr,
3478 .fsetxattr_fn = vfswrap_fsetxattr,
3480 /* aio operations */
3481 .aio_force_fn = vfswrap_aio_force,
3483 /* durable handle operations */
3484 .durable_cookie_fn = vfswrap_durable_cookie,
3485 .durable_disconnect_fn = vfswrap_durable_disconnect,
3486 .durable_reconnect_fn = vfswrap_durable_reconnect,
3490 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3493 * Here we need to implement every call!
3495 * As this is the end of the vfs module chain.
3497 smb_vfs_assert_all_fns(&vfs_default_fns, DEFAULT_VFS_MODULE_NAME);
3498 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3499 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);