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 /* Cope with 'stat' file opens. */
1029 if (fsp->fh->fd != -1)
1030 result = lseek(fsp->fh->fd, offset, whence);
1033 * We want to maintain the fiction that we can seek
1034 * on a fifo for file system purposes. This allows
1035 * people to set up UNIX fifo's that feed data to Windows
1036 * applications. JRA.
1039 if((result == -1) && (errno == ESPIPE)) {
1044 END_PROFILE(syscall_lseek);
1048 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1049 off_t offset, size_t n)
1053 START_PROFILE_BYTES(syscall_sendfile, n);
1054 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
1055 END_PROFILE_BYTES(syscall_sendfile);
1059 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1061 files_struct *tofsp,
1067 START_PROFILE_BYTES(syscall_recvfile, n);
1068 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
1069 END_PROFILE_BYTES(syscall_recvfile);
1073 static int vfswrap_rename(vfs_handle_struct *handle,
1074 const struct smb_filename *smb_fname_src,
1075 const struct smb_filename *smb_fname_dst)
1079 START_PROFILE(syscall_rename);
1081 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
1086 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
1089 END_PROFILE(syscall_rename);
1093 static int vfswrap_stat(vfs_handle_struct *handle,
1094 struct smb_filename *smb_fname)
1098 START_PROFILE(syscall_stat);
1100 if (smb_fname->stream_name) {
1105 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1106 lp_fake_directory_create_times(SNUM(handle->conn)));
1108 END_PROFILE(syscall_stat);
1112 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1116 START_PROFILE(syscall_fstat);
1117 result = sys_fstat(fsp->fh->fd,
1118 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1119 END_PROFILE(syscall_fstat);
1123 static int vfswrap_lstat(vfs_handle_struct *handle,
1124 struct smb_filename *smb_fname)
1128 START_PROFILE(syscall_lstat);
1130 if (smb_fname->stream_name) {
1135 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1136 lp_fake_directory_create_times(SNUM(handle->conn)));
1138 END_PROFILE(syscall_lstat);
1142 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1144 enum vfs_translate_direction direction,
1145 TALLOC_CTX *mem_ctx,
1148 return NT_STATUS_NONE_MAPPED;
1152 * Implement the default fsctl operation.
1154 static bool vfswrap_logged_ioctl_message = false;
1156 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1157 struct files_struct *fsp,
1160 uint16_t req_flags, /* Needed for UNICODE ... */
1161 const uint8_t *_in_data,
1163 uint8_t **_out_data,
1164 uint32_t max_out_len,
1167 const char *in_data = (const char *)_in_data;
1168 char **out_data = (char **)_out_data;
1172 case FSCTL_SET_SPARSE:
1174 bool set_sparse = true;
1176 if (in_len >= 1 && in_data[0] == 0) {
1180 status = file_set_sparse(handle->conn, fsp, set_sparse);
1182 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1183 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1184 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1185 nt_errstr(status)));
1190 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1192 unsigned char objid[16];
1193 char *return_data = NULL;
1195 /* This should return the object-id on this file.
1196 * I think I'll make this be the inode+dev. JRA.
1199 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1200 fsp_fnum_dbg(fsp)));
1202 *out_len = MIN(max_out_len, 64);
1204 /* Hmmm, will this cause problems if less data asked for? */
1205 return_data = talloc_array(ctx, char, 64);
1206 if (return_data == NULL) {
1207 return NT_STATUS_NO_MEMORY;
1210 /* For backwards compatibility only store the dev/inode. */
1211 push_file_id_16(return_data, &fsp->file_id);
1212 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1213 push_file_id_16(return_data+32, &fsp->file_id);
1214 memset(return_data+48, 0, 16);
1215 *out_data = return_data;
1216 return NT_STATUS_OK;
1219 case FSCTL_GET_REPARSE_POINT:
1221 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1222 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1223 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1224 return NT_STATUS_NOT_A_REPARSE_POINT;
1227 case FSCTL_SET_REPARSE_POINT:
1229 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1230 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1231 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1232 return NT_STATUS_NOT_A_REPARSE_POINT;
1235 case FSCTL_GET_SHADOW_COPY_DATA:
1238 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1239 * and return their volume names. If max_data_count is 16, then it is just
1240 * asking for the number of volumes and length of the combined names.
1242 * pdata is the data allocated by our caller, but that uses
1243 * total_data_count (which is 0 in our case) rather than max_data_count.
1244 * Allocate the correct amount and return the pointer to let
1245 * it be deallocated when we return.
1247 struct shadow_copy_data *shadow_data = NULL;
1248 bool labels = False;
1249 uint32_t labels_data_count = 0;
1251 char *cur_pdata = NULL;
1253 if (max_out_len < 16) {
1254 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1256 return NT_STATUS_INVALID_PARAMETER;
1259 if (max_out_len > 16) {
1263 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1264 if (shadow_data == NULL) {
1265 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1266 return NT_STATUS_NO_MEMORY;
1270 * Call the VFS routine to actually do the work.
1272 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1275 /* broken module didn't set errno on error */
1276 status = NT_STATUS_UNSUCCESSFUL;
1278 status = map_nt_error_from_unix(errno);
1279 if (NT_STATUS_EQUAL(status,
1280 NT_STATUS_NOT_SUPPORTED)) {
1284 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1285 "connectpath %s, failed - %s.\n",
1286 fsp->conn->connectpath,
1287 nt_errstr(status)));
1288 TALLOC_FREE(shadow_data);
1292 labels_data_count = (shadow_data->num_volumes * 2 *
1293 sizeof(SHADOW_COPY_LABEL)) + 2;
1298 *out_len = 12 + labels_data_count;
1301 if (max_out_len < *out_len) {
1302 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1303 max_out_len, *out_len));
1304 TALLOC_FREE(shadow_data);
1305 return NT_STATUS_BUFFER_TOO_SMALL;
1308 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1309 if (cur_pdata == NULL) {
1310 TALLOC_FREE(shadow_data);
1311 return NT_STATUS_NO_MEMORY;
1314 *out_data = cur_pdata;
1316 /* num_volumes 4 bytes */
1317 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1320 /* num_labels 4 bytes */
1321 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1324 /* needed_data_count 4 bytes */
1325 SIVAL(cur_pdata, 8, labels_data_count);
1329 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1330 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1331 if (labels && shadow_data->labels) {
1332 for (i=0; i<shadow_data->num_volumes; i++) {
1334 status = srvstr_push(cur_pdata, req_flags,
1335 cur_pdata, shadow_data->labels[i],
1336 2 * sizeof(SHADOW_COPY_LABEL),
1337 STR_UNICODE|STR_TERMINATE, &len);
1338 if (!NT_STATUS_IS_OK(status)) {
1339 TALLOC_FREE(*out_data);
1340 TALLOC_FREE(shadow_data);
1343 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1344 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1348 TALLOC_FREE(shadow_data);
1350 return NT_STATUS_OK;
1353 case FSCTL_FIND_FILES_BY_SID:
1355 /* pretend this succeeded -
1357 * we have to send back a list with all files owned by this SID
1359 * but I have to check that --metze
1362 struct dom_sid_buf buf;
1366 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1367 fsp_fnum_dbg(fsp)));
1370 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1371 return NT_STATUS_INVALID_PARAMETER;
1374 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1376 /* unknown 4 bytes: this is not the length of the sid :-( */
1377 /*unknown = IVAL(pdata,0);*/
1379 if (!sid_parse(_in_data + 4, sid_len, &sid)) {
1380 return NT_STATUS_INVALID_PARAMETER;
1382 DEBUGADD(10, ("for SID: %s\n",
1383 dom_sid_str_buf(&sid, &buf)));
1385 if (!sid_to_uid(&sid, &uid)) {
1386 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1387 dom_sid_str_buf(&sid, &buf),
1388 (unsigned long)sid_len));
1392 /* we can take a look at the find source :-)
1394 * find ./ -uid $uid -name '*' is what we need here
1397 * and send 4bytes len and then NULL terminated unicode strings
1400 * but I don't know how to deal with the paged results
1401 * (maybe we can hang the result anywhere in the fsp struct)
1403 * but I don't know how to deal with the paged results
1404 * (maybe we can hang the result anywhere in the fsp struct)
1406 * we don't send all files at once
1407 * and at the next we should *not* start from the beginning,
1408 * so we have to cache the result
1413 /* this works for now... */
1414 return NT_STATUS_OK;
1417 case FSCTL_QUERY_ALLOCATED_RANGES:
1419 /* FIXME: This is just a dummy reply, telling that all of the
1420 * file is allocated. MKS cp needs that.
1421 * Adding the real allocated ranges via FIEMAP on Linux
1422 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1423 * this FSCTL correct for sparse files.
1425 uint64_t offset, length;
1426 char *out_data_tmp = NULL;
1429 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1431 return NT_STATUS_INVALID_PARAMETER;
1434 if (max_out_len < 16) {
1435 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1437 return NT_STATUS_INVALID_PARAMETER;
1440 offset = BVAL(in_data,0);
1441 length = BVAL(in_data,8);
1443 if (offset + length < offset) {
1444 /* No 64-bit integer wrap. */
1445 return NT_STATUS_INVALID_PARAMETER;
1448 /* Shouldn't this be SMB_VFS_STAT ... ? */
1449 status = vfs_stat_fsp(fsp);
1450 if (!NT_STATUS_IS_OK(status)) {
1455 out_data_tmp = talloc_array(ctx, char, *out_len);
1456 if (out_data_tmp == NULL) {
1457 DEBUG(10, ("unable to allocate memory for response\n"));
1458 return NT_STATUS_NO_MEMORY;
1461 if (offset > fsp->fsp_name->st.st_ex_size ||
1462 fsp->fsp_name->st.st_ex_size == 0 ||
1464 memset(out_data_tmp, 0, *out_len);
1466 uint64_t end = offset + length;
1467 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1468 SBVAL(out_data_tmp, 0, 0);
1469 SBVAL(out_data_tmp, 8, end);
1472 *out_data = out_data_tmp;
1474 return NT_STATUS_OK;
1477 case FSCTL_IS_VOLUME_DIRTY:
1479 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1480 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1482 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1483 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1485 return NT_STATUS_INVALID_PARAMETER;
1490 * Only print once ... unfortunately there could be lots of
1491 * different FSCTLs that are called.
1493 if (!vfswrap_logged_ioctl_message) {
1494 vfswrap_logged_ioctl_message = true;
1495 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1496 __func__, function));
1500 return NT_STATUS_NOT_SUPPORTED;
1503 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
1504 const struct smb_filename *fname,
1505 SMB_STRUCT_STAT *sbuf);
1507 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1508 struct smb_filename *smb_fname,
1513 offline = vfswrap_is_offline(handle, smb_fname, &smb_fname->st);
1515 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1518 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1521 struct vfswrap_get_dos_attributes_state {
1522 struct vfs_aio_state aio_state;
1523 connection_struct *conn;
1524 TALLOC_CTX *mem_ctx;
1525 struct tevent_context *ev;
1526 files_struct *dir_fsp;
1527 struct smb_filename *smb_fname;
1532 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq);
1534 static struct tevent_req *vfswrap_get_dos_attributes_send(
1535 TALLOC_CTX *mem_ctx,
1536 struct tevent_context *ev,
1537 struct vfs_handle_struct *handle,
1538 files_struct *dir_fsp,
1539 struct smb_filename *smb_fname)
1541 struct tevent_req *req = NULL;
1542 struct tevent_req *subreq = NULL;
1543 struct vfswrap_get_dos_attributes_state *state = NULL;
1545 req = tevent_req_create(mem_ctx, &state,
1546 struct vfswrap_get_dos_attributes_state);
1551 *state = (struct vfswrap_get_dos_attributes_state) {
1552 .conn = dir_fsp->conn,
1556 .smb_fname = smb_fname,
1559 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1563 SAMBA_XATTR_DOS_ATTRIB,
1565 if (tevent_req_nomem(subreq, req)) {
1566 return tevent_req_post(req, ev);
1568 tevent_req_set_callback(subreq,
1569 vfswrap_get_dos_attributes_getxattr_done,
1575 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq)
1577 struct tevent_req *req =
1578 tevent_req_callback_data(subreq,
1580 struct vfswrap_get_dos_attributes_state *state =
1581 tevent_req_data(req,
1582 struct vfswrap_get_dos_attributes_state);
1584 DATA_BLOB blob = {0};
1587 xattr_size = SMB_VFS_GETXATTRAT_RECV(subreq,
1591 TALLOC_FREE(subreq);
1592 if (xattr_size == -1) {
1593 status = map_nt_error_from_unix(state->aio_state.error);
1595 if (state->as_root) {
1596 tevent_req_nterror(req, status);
1599 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1600 tevent_req_nterror(req, status);
1604 state->as_root = true;
1607 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1611 SAMBA_XATTR_DOS_ATTRIB,
1614 if (tevent_req_nomem(subreq, req)) {
1617 tevent_req_set_callback(subreq,
1618 vfswrap_get_dos_attributes_getxattr_done,
1623 blob.length = xattr_size;
1625 status = parse_dos_attribute_blob(state->smb_fname,
1628 if (!NT_STATUS_IS_OK(status)) {
1629 tevent_req_nterror(req, status);
1633 tevent_req_done(req);
1637 static NTSTATUS vfswrap_get_dos_attributes_recv(struct tevent_req *req,
1638 struct vfs_aio_state *aio_state,
1641 struct vfswrap_get_dos_attributes_state *state =
1642 tevent_req_data(req,
1643 struct vfswrap_get_dos_attributes_state);
1646 if (tevent_req_is_nterror(req, &status)) {
1647 tevent_req_received(req);
1651 *aio_state = state->aio_state;
1652 *dosmode = state->dosmode;
1653 tevent_req_received(req);
1654 return NT_STATUS_OK;
1657 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1658 struct files_struct *fsp,
1663 offline = vfswrap_is_offline(handle, fsp->fsp_name, &fsp->fsp_name->st);
1665 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1668 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1671 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1672 const struct smb_filename *smb_fname,
1675 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1678 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1679 struct files_struct *fsp,
1682 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1685 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1687 struct vfswrap_offload_read_state {
1691 static struct tevent_req *vfswrap_offload_read_send(
1692 TALLOC_CTX *mem_ctx,
1693 struct tevent_context *ev,
1694 struct vfs_handle_struct *handle,
1695 struct files_struct *fsp,
1701 struct tevent_req *req = NULL;
1702 struct vfswrap_offload_read_state *state = NULL;
1705 req = tevent_req_create(mem_ctx, &state,
1706 struct vfswrap_offload_read_state);
1711 status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1712 &vfswrap_offload_ctx);
1713 if (tevent_req_nterror(req, status)) {
1714 return tevent_req_post(req, ev);
1717 if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1718 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1719 return tevent_req_post(req, ev);
1722 status = vfs_offload_token_create_blob(state, fsp, fsctl,
1724 if (tevent_req_nterror(req, status)) {
1725 return tevent_req_post(req, ev);
1728 status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1730 if (tevent_req_nterror(req, status)) {
1731 return tevent_req_post(req, ev);
1734 tevent_req_done(req);
1735 return tevent_req_post(req, ev);
1738 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
1739 struct vfs_handle_struct *handle,
1740 TALLOC_CTX *mem_ctx,
1743 struct vfswrap_offload_read_state *state = tevent_req_data(
1744 req, struct vfswrap_offload_read_state);
1747 if (tevent_req_is_nterror(req, &status)) {
1748 tevent_req_received(req);
1752 token->length = state->token.length;
1753 token->data = talloc_move(mem_ctx, &state->token.data);
1755 tevent_req_received(req);
1756 return NT_STATUS_OK;
1759 struct vfswrap_offload_write_state {
1761 bool read_lck_locked;
1762 bool write_lck_locked;
1764 struct tevent_context *src_ev;
1765 struct files_struct *src_fsp;
1767 struct tevent_context *dst_ev;
1768 struct files_struct *dst_fsp;
1772 size_t next_io_size;
1775 static void vfswrap_offload_write_cleanup(struct tevent_req *req,
1776 enum tevent_req_state req_state)
1778 struct vfswrap_offload_write_state *state = tevent_req_data(
1779 req, struct vfswrap_offload_write_state);
1782 if (state->dst_fsp == NULL) {
1786 ok = change_to_user_by_fsp(state->dst_fsp);
1788 state->dst_fsp = NULL;
1791 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
1793 static struct tevent_req *vfswrap_offload_write_send(
1794 struct vfs_handle_struct *handle,
1795 TALLOC_CTX *mem_ctx,
1796 struct tevent_context *ev,
1799 off_t transfer_offset,
1800 struct files_struct *dest_fsp,
1804 struct tevent_req *req;
1805 struct vfswrap_offload_write_state *state = NULL;
1806 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
1807 files_struct *src_fsp = NULL;
1811 req = tevent_req_create(mem_ctx, &state,
1812 struct vfswrap_offload_write_state);
1817 *state = (struct vfswrap_offload_write_state) {
1819 .src_off = transfer_offset,
1821 .dst_fsp = dest_fsp,
1822 .dst_off = dest_off,
1824 .remaining = to_copy,
1827 tevent_req_set_cleanup_fn(req, vfswrap_offload_write_cleanup);
1830 case FSCTL_SRV_COPYCHUNK:
1831 case FSCTL_SRV_COPYCHUNK_WRITE:
1834 case FSCTL_OFFLOAD_WRITE:
1835 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
1836 return tevent_req_post(req, ev);
1838 case FSCTL_DUP_EXTENTS_TO_FILE:
1839 DBG_DEBUG("COW clones not supported by vfs_default\n");
1840 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1841 return tevent_req_post(req, ev);
1844 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1845 return tevent_req_post(req, ev);
1849 * From here on we assume a copy-chunk fsctl
1853 tevent_req_done(req);
1854 return tevent_req_post(req, ev);
1857 status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
1859 if (tevent_req_nterror(req, status)) {
1860 return tevent_req_post(req, ev);
1863 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
1865 status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
1866 if (!NT_STATUS_IS_OK(status)) {
1867 tevent_req_nterror(req, status);
1868 return tevent_req_post(req, ev);
1871 ok = change_to_user_by_fsp(src_fsp);
1873 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1874 return tevent_req_post(req, ev);
1877 state->src_ev = src_fsp->conn->sconn->ev_ctx;
1878 state->src_fsp = src_fsp;
1880 state->buf = talloc_array(state, uint8_t, num);
1881 if (tevent_req_nomem(state->buf, req)) {
1882 return tevent_req_post(req, ev);
1885 status = vfs_stat_fsp(src_fsp);
1886 if (tevent_req_nterror(req, status)) {
1887 return tevent_req_post(req, ev);
1890 if (src_fsp->fsp_name->st.st_ex_size < state->src_off + num) {
1892 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1893 * If the SourceOffset or SourceOffset + Length extends beyond
1894 * the end of file, the server SHOULD<240> treat this as a
1895 * STATUS_END_OF_FILE error.
1897 * <240> Section 3.3.5.15.6: Windows servers will return
1898 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1900 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1901 return tevent_req_post(req, ev);
1904 status = vfswrap_offload_write_loop(req);
1905 if (!NT_STATUS_IS_OK(status)) {
1906 tevent_req_nterror(req, status);
1907 return tevent_req_post(req, ev);
1913 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
1915 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
1917 struct vfswrap_offload_write_state *state = tevent_req_data(
1918 req, struct vfswrap_offload_write_state);
1919 struct tevent_req *subreq = NULL;
1920 struct lock_struct read_lck;
1924 * This is called under the context of state->src_fsp.
1927 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
1929 init_strict_lock_struct(state->src_fsp,
1930 state->src_fsp->op->global->open_persistent_id,
1932 state->next_io_size,
1936 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
1940 return NT_STATUS_FILE_LOCK_CONFLICT;
1943 subreq = SMB_VFS_PREAD_SEND(state,
1947 state->next_io_size,
1949 if (subreq == NULL) {
1950 return NT_STATUS_NO_MEMORY;
1952 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
1954 return NT_STATUS_OK;
1957 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
1959 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
1961 struct tevent_req *req = tevent_req_callback_data(
1962 subreq, struct tevent_req);
1963 struct vfswrap_offload_write_state *state = tevent_req_data(
1964 req, struct vfswrap_offload_write_state);
1965 struct vfs_aio_state aio_state;
1966 struct lock_struct write_lck;
1970 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
1971 TALLOC_FREE(subreq);
1973 DBG_ERR("read failed: %s\n", strerror(errno));
1974 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1977 if (nread != state->next_io_size) {
1978 DBG_ERR("Short read, only %zd of %zu\n",
1979 nread, state->next_io_size);
1980 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1984 state->src_off += nread;
1986 ok = change_to_user_by_fsp(state->dst_fsp);
1988 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1992 init_strict_lock_struct(state->dst_fsp,
1993 state->dst_fsp->op->global->open_persistent_id,
1995 state->next_io_size,
1999 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
2003 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
2007 subreq = SMB_VFS_PWRITE_SEND(state,
2011 state->next_io_size,
2013 if (subreq == NULL) {
2014 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2017 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
2020 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
2022 struct tevent_req *req = tevent_req_callback_data(
2023 subreq, struct tevent_req);
2024 struct vfswrap_offload_write_state *state = tevent_req_data(
2025 req, struct vfswrap_offload_write_state);
2026 struct vfs_aio_state aio_state;
2031 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
2032 TALLOC_FREE(subreq);
2033 if (nwritten == -1) {
2034 DBG_ERR("write failed: %s\n", strerror(errno));
2035 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2038 if (nwritten != state->next_io_size) {
2039 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
2040 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2044 state->dst_off += nwritten;
2046 if (state->remaining < nwritten) {
2047 /* Paranoia check */
2048 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2051 state->remaining -= nwritten;
2052 if (state->remaining == 0) {
2053 tevent_req_done(req);
2057 ok = change_to_user_by_fsp(state->src_fsp);
2059 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2063 status = vfswrap_offload_write_loop(req);
2064 if (!NT_STATUS_IS_OK(status)) {
2065 tevent_req_nterror(req, status);
2072 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
2073 struct tevent_req *req,
2076 struct vfswrap_offload_write_state *state = tevent_req_data(
2077 req, struct vfswrap_offload_write_state);
2080 if (tevent_req_is_nterror(req, &status)) {
2081 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
2083 tevent_req_received(req);
2087 *copied = state->to_copy;
2088 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
2089 tevent_req_received(req);
2091 return NT_STATUS_OK;
2094 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
2095 TALLOC_CTX *mem_ctx,
2096 struct files_struct *fsp,
2097 struct smb_filename *smb_fname,
2098 uint16_t *_compression_fmt)
2100 return NT_STATUS_INVALID_DEVICE_REQUEST;
2103 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
2104 TALLOC_CTX *mem_ctx,
2105 struct files_struct *fsp,
2106 uint16_t compression_fmt)
2108 return NT_STATUS_INVALID_DEVICE_REQUEST;
2111 /********************************************************************
2112 Given a stat buffer return the allocated size on disk, taking into
2113 account sparse files.
2114 ********************************************************************/
2115 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
2116 struct files_struct *fsp,
2117 const SMB_STRUCT_STAT *sbuf)
2121 START_PROFILE(syscall_get_alloc_size);
2123 if(S_ISDIR(sbuf->st_ex_mode)) {
2128 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2129 /* The type of st_blocksize is blkcnt_t which *MUST* be
2130 signed (according to POSIX) and can be less than 64-bits.
2131 Ensure when we're converting to 64 bits wide we don't
2133 #if defined(SIZEOF_BLKCNT_T_8)
2134 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2135 #elif defined(SIZEOF_BLKCNT_T_4)
2137 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2138 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2141 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2145 * Some file systems do not allocate a block for very
2146 * small files. But for non-empty file should report a
2150 uint64_t filesize = get_file_size_stat(sbuf);
2152 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2156 result = get_file_size_stat(sbuf);
2159 if (fsp && fsp->initial_allocation_size)
2160 result = MAX(result,fsp->initial_allocation_size);
2162 result = smb_roundup(handle->conn, result);
2165 END_PROFILE(syscall_get_alloc_size);
2169 static int vfswrap_unlink(vfs_handle_struct *handle,
2170 const struct smb_filename *smb_fname)
2174 START_PROFILE(syscall_unlink);
2176 if (smb_fname->stream_name) {
2180 result = unlink(smb_fname->base_name);
2183 END_PROFILE(syscall_unlink);
2187 static int vfswrap_chmod(vfs_handle_struct *handle,
2188 const struct smb_filename *smb_fname,
2193 START_PROFILE(syscall_chmod);
2194 result = chmod(smb_fname->base_name, mode);
2195 END_PROFILE(syscall_chmod);
2199 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2203 START_PROFILE(syscall_fchmod);
2204 #if defined(HAVE_FCHMOD)
2205 result = fchmod(fsp->fh->fd, mode);
2211 END_PROFILE(syscall_fchmod);
2215 static int vfswrap_chown(vfs_handle_struct *handle,
2216 const struct smb_filename *smb_fname,
2222 START_PROFILE(syscall_chown);
2223 result = chown(smb_fname->base_name, uid, gid);
2224 END_PROFILE(syscall_chown);
2228 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2233 START_PROFILE(syscall_fchown);
2234 result = fchown(fsp->fh->fd, uid, gid);
2235 END_PROFILE(syscall_fchown);
2243 static int vfswrap_lchown(vfs_handle_struct *handle,
2244 const struct smb_filename *smb_fname,
2250 START_PROFILE(syscall_lchown);
2251 result = lchown(smb_fname->base_name, uid, gid);
2252 END_PROFILE(syscall_lchown);
2256 static int vfswrap_chdir(vfs_handle_struct *handle,
2257 const struct smb_filename *smb_fname)
2261 START_PROFILE(syscall_chdir);
2262 result = chdir(smb_fname->base_name);
2263 END_PROFILE(syscall_chdir);
2267 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2271 struct smb_filename *smb_fname = NULL;
2273 START_PROFILE(syscall_getwd);
2274 result = sys_getwd();
2275 END_PROFILE(syscall_getwd);
2277 if (result == NULL) {
2280 smb_fname = synthetic_smb_fname(ctx,
2286 * sys_getwd() *always* returns malloced memory.
2287 * We must free here to avoid leaks:
2288 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2294 /*********************************************************************
2295 nsec timestamp resolution call. Convert down to whatever the underlying
2296 system will support.
2297 **********************************************************************/
2299 static int vfswrap_ntimes(vfs_handle_struct *handle,
2300 const struct smb_filename *smb_fname,
2301 struct smb_file_time *ft)
2305 START_PROFILE(syscall_ntimes);
2307 if (smb_fname->stream_name) {
2313 if (null_timespec(ft->atime)) {
2314 ft->atime= smb_fname->st.st_ex_atime;
2317 if (null_timespec(ft->mtime)) {
2318 ft->mtime = smb_fname->st.st_ex_mtime;
2321 if (!null_timespec(ft->create_time)) {
2322 set_create_timespec_ea(handle->conn,
2327 if ((timespec_compare(&ft->atime,
2328 &smb_fname->st.st_ex_atime) == 0) &&
2329 (timespec_compare(&ft->mtime,
2330 &smb_fname->st.st_ex_mtime) == 0)) {
2335 #if defined(HAVE_UTIMENSAT)
2337 struct timespec ts[2];
2340 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2342 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2344 if (!((result == -1) && (errno == ENOSYS))) {
2348 #if defined(HAVE_UTIMES)
2350 struct timeval tv[2];
2351 tv[0] = convert_timespec_to_timeval(ft->atime);
2352 tv[1] = convert_timespec_to_timeval(ft->mtime);
2353 result = utimes(smb_fname->base_name, tv);
2355 result = utimes(smb_fname->base_name, NULL);
2357 if (!((result == -1) && (errno == ENOSYS))) {
2361 #if defined(HAVE_UTIME)
2363 struct utimbuf times;
2364 times.actime = convert_timespec_to_time_t(ft->atime);
2365 times.modtime = convert_timespec_to_time_t(ft->mtime);
2366 result = utime(smb_fname->base_name, ×);
2368 result = utime(smb_fname->base_name, NULL);
2370 if (!((result == -1) && (errno == ENOSYS))) {
2378 END_PROFILE(syscall_ntimes);
2382 /*********************************************************************
2383 A version of ftruncate that will write the space on disk if strict
2385 **********************************************************************/
2387 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2389 off_t space_to_write;
2390 uint64_t space_avail;
2391 uint64_t bsize,dfree,dsize;
2394 SMB_STRUCT_STAT *pst;
2396 status = vfs_stat_fsp(fsp);
2397 if (!NT_STATUS_IS_OK(status)) {
2400 pst = &fsp->fsp_name->st;
2403 if (S_ISFIFO(pst->st_ex_mode))
2407 if (pst->st_ex_size == len)
2410 /* Shrink - just ftruncate. */
2411 if (pst->st_ex_size > len)
2412 return ftruncate(fsp->fh->fd, len);
2414 space_to_write = len - pst->st_ex_size;
2416 /* for allocation try fallocate first. This can fail on some
2417 platforms e.g. when the filesystem doesn't support it and no
2418 emulation is being done by the libc (like on AIX with JFS1). In that
2419 case we do our own emulation. fallocate implementations can
2420 return ENOTSUP or EINVAL in cases like that. */
2421 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2422 if (ret == -1 && errno == ENOSPC) {
2428 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2429 "error %d. Falling back to slow manual allocation\n", errno));
2431 /* available disk space is enough or not? */
2433 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2434 /* space_avail is 1k blocks */
2435 if (space_avail == (uint64_t)-1 ||
2436 ((uint64_t)space_to_write/1024 > space_avail) ) {
2441 /* Write out the real space on disk. */
2442 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2450 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2453 SMB_STRUCT_STAT *pst;
2457 START_PROFILE(syscall_ftruncate);
2459 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2460 result = strict_allocate_ftruncate(handle, fsp, len);
2461 END_PROFILE(syscall_ftruncate);
2465 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2466 ftruncate if the system supports it. Then I discovered that
2467 you can have some filesystems that support ftruncate
2468 expansion and some that don't! On Linux fat can't do
2469 ftruncate extend but ext2 can. */
2471 result = ftruncate(fsp->fh->fd, len);
2473 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2474 extend a file with ftruncate. Provide alternate implementation
2477 /* Do an fstat to see if the file is longer than the requested
2478 size in which case the ftruncate above should have
2479 succeeded or shorter, in which case seek to len - 1 and
2480 write 1 byte of zero */
2481 status = vfs_stat_fsp(fsp);
2482 if (!NT_STATUS_IS_OK(status)) {
2486 /* We need to update the files_struct after successful ftruncate */
2491 pst = &fsp->fsp_name->st;
2494 if (S_ISFIFO(pst->st_ex_mode)) {
2500 if (pst->st_ex_size == len) {
2505 if (pst->st_ex_size > len) {
2506 /* the ftruncate should have worked */
2510 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2518 END_PROFILE(syscall_ftruncate);
2522 static int vfswrap_fallocate(vfs_handle_struct *handle,
2530 START_PROFILE(syscall_fallocate);
2532 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2534 * posix_fallocate returns 0 on success, errno on error
2535 * and doesn't set errno. Make it behave like fallocate()
2536 * which returns -1, and sets errno on failure.
2543 /* sys_fallocate handles filtering of unsupported mode flags */
2544 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2546 END_PROFILE(syscall_fallocate);
2550 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2554 START_PROFILE(syscall_fcntl_lock);
2556 if (fsp->use_ofd_locks) {
2557 op = map_process_lock_to_ofd_lock(op);
2560 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2561 END_PROFILE(syscall_fcntl_lock);
2565 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2566 uint32_t share_mode, uint32_t access_mask)
2568 START_PROFILE(syscall_kernel_flock);
2569 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2570 END_PROFILE(syscall_kernel_flock);
2574 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2579 START_PROFILE(syscall_fcntl_getlock);
2581 if (fsp->use_ofd_locks) {
2582 op = map_process_lock_to_ofd_lock(op);
2585 result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2586 END_PROFILE(syscall_fcntl_getlock);
2590 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2595 START_PROFILE(syscall_linux_setlease);
2597 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2598 result = linux_setlease(fsp->fh->fd, leasetype);
2602 END_PROFILE(syscall_linux_setlease);
2606 static int vfswrap_symlink(vfs_handle_struct *handle,
2607 const char *link_target,
2608 const struct smb_filename *new_smb_fname)
2612 START_PROFILE(syscall_symlink);
2613 result = symlink(link_target, new_smb_fname->base_name);
2614 END_PROFILE(syscall_symlink);
2618 static int vfswrap_readlink(vfs_handle_struct *handle,
2619 const struct smb_filename *smb_fname,
2625 START_PROFILE(syscall_readlink);
2626 result = readlink(smb_fname->base_name, buf, bufsiz);
2627 END_PROFILE(syscall_readlink);
2631 static int vfswrap_link(vfs_handle_struct *handle,
2632 const struct smb_filename *old_smb_fname,
2633 const struct smb_filename *new_smb_fname)
2637 START_PROFILE(syscall_link);
2638 result = link(old_smb_fname->base_name, new_smb_fname->base_name);
2639 END_PROFILE(syscall_link);
2643 static int vfswrap_mknod(vfs_handle_struct *handle,
2644 const struct smb_filename *smb_fname,
2650 START_PROFILE(syscall_mknod);
2651 result = sys_mknod(smb_fname->base_name, mode, dev);
2652 END_PROFILE(syscall_mknod);
2656 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2658 const struct smb_filename *smb_fname)
2661 struct smb_filename *result_fname = NULL;
2663 START_PROFILE(syscall_realpath);
2664 result = sys_realpath(smb_fname->base_name);
2665 END_PROFILE(syscall_realpath);
2667 result_fname = synthetic_smb_fname(ctx, result, NULL, NULL, 0);
2670 return result_fname;
2673 static int vfswrap_chflags(vfs_handle_struct *handle,
2674 const struct smb_filename *smb_fname,
2678 return chflags(smb_fname->base_name, flags);
2685 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2686 const SMB_STRUCT_STAT *sbuf)
2690 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2694 key.devid = sbuf->st_ex_dev;
2695 key.inode = sbuf->st_ex_ino;
2696 /* key.extid is unused by default. */
2701 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2702 struct files_struct *fsp,
2703 const struct smb_filename *smb_fname,
2704 TALLOC_CTX *mem_ctx,
2705 unsigned int *pnum_streams,
2706 struct stream_struct **pstreams)
2708 SMB_STRUCT_STAT sbuf;
2709 struct stream_struct *tmp_streams = NULL;
2712 if ((fsp != NULL) && (fsp->is_directory)) {
2714 * No default streams on directories
2719 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2720 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2723 struct smb_filename smb_fname_cp;
2725 ZERO_STRUCT(smb_fname_cp);
2726 smb_fname_cp.base_name = discard_const_p(char,
2727 smb_fname->base_name);
2728 smb_fname_cp.flags = smb_fname->flags;
2730 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
2731 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2733 ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2735 sbuf = smb_fname_cp.st;
2739 return map_nt_error_from_unix(errno);
2742 if (S_ISDIR(sbuf.st_ex_mode)) {
2746 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2747 (*pnum_streams) + 1);
2748 if (tmp_streams == NULL) {
2749 return NT_STATUS_NO_MEMORY;
2751 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2752 if (tmp_streams[*pnum_streams].name == NULL) {
2753 return NT_STATUS_NO_MEMORY;
2755 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2756 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2759 *pstreams = tmp_streams;
2761 return NT_STATUS_OK;
2764 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2767 TALLOC_CTX *mem_ctx,
2771 * Don't fall back to get_real_filename so callers can differentiate
2772 * between a full directory scan and an actual case-insensitive stat.
2778 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2779 const struct smb_filename *smb_fname)
2781 return handle->conn->connectpath;
2784 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2785 struct byte_range_lock *br_lck,
2786 struct lock_struct *plock,
2789 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2791 /* Note: blr is not used in the default implementation. */
2792 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2795 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2796 struct messaging_context *msg_ctx,
2797 struct byte_range_lock *br_lck,
2798 const struct lock_struct *plock)
2800 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2802 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2805 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2806 struct byte_range_lock *br_lck,
2807 struct lock_struct *plock)
2809 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2811 /* Note: blr is not used in the default implementation. */
2812 return brl_lock_cancel_default(br_lck, plock);
2815 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
2817 struct lock_struct *plock)
2819 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2820 plock->lock_type == WRITE_LOCK);
2822 return strict_lock_check_default(fsp, plock);
2825 /* NT ACL operations. */
2827 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2829 uint32_t security_info,
2830 TALLOC_CTX *mem_ctx,
2831 struct security_descriptor **ppdesc)
2835 START_PROFILE(fget_nt_acl);
2836 result = posix_fget_nt_acl(fsp, security_info,
2838 END_PROFILE(fget_nt_acl);
2842 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2843 const struct smb_filename *smb_fname,
2844 uint32_t security_info,
2845 TALLOC_CTX *mem_ctx,
2846 struct security_descriptor **ppdesc)
2850 START_PROFILE(get_nt_acl);
2851 result = posix_get_nt_acl(handle->conn,
2856 END_PROFILE(get_nt_acl);
2860 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2864 START_PROFILE(fset_nt_acl);
2865 result = set_nt_acl(fsp, security_info_sent, psd);
2866 END_PROFILE(fset_nt_acl);
2870 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2871 struct smb_filename *file,
2872 struct security_acl *sacl,
2873 uint32_t access_requested,
2874 uint32_t access_denied)
2876 return NT_STATUS_OK; /* Nothing to do here ... */
2879 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2880 const struct smb_filename *smb_fname,
2881 SMB_ACL_TYPE_T type,
2882 TALLOC_CTX *mem_ctx)
2884 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
2887 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2889 TALLOC_CTX *mem_ctx)
2891 return sys_acl_get_fd(handle, fsp, mem_ctx);
2894 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
2895 const struct smb_filename *smb_fname,
2896 SMB_ACL_TYPE_T acltype,
2899 return sys_acl_set_file(handle, smb_fname, acltype, theacl);
2902 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2904 return sys_acl_set_fd(handle, fsp, theacl);
2907 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
2908 const struct smb_filename *smb_fname)
2910 return sys_acl_delete_def_file(handle, smb_fname);
2913 /****************************************************************
2914 Extended attribute operations.
2915 *****************************************************************/
2917 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
2918 const struct smb_filename *smb_fname,
2923 return getxattr(smb_fname->base_name, name, value, size);
2926 struct vfswrap_getxattrat_state {
2927 struct tevent_context *ev;
2928 files_struct *dir_fsp;
2929 const struct smb_filename *smb_fname;
2930 struct tevent_req *req;
2933 * The following variables are talloced off "state" which is protected
2934 * by a destructor and thus are guaranteed to be safe to be used in the
2935 * job function in the worker thread.
2938 const char *xattr_name;
2939 uint8_t *xattr_value;
2940 struct security_unix_token *token;
2943 struct vfs_aio_state vfs_aio_state;
2944 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
2947 static int vfswrap_getxattrat_state_destructor(
2948 struct vfswrap_getxattrat_state *state)
2953 static void vfswrap_getxattrat_do_sync(struct tevent_req *req);
2954 static void vfswrap_getxattrat_do_async(void *private_data);
2955 static void vfswrap_getxattrat_done(struct tevent_req *subreq);
2957 static struct tevent_req *vfswrap_getxattrat_send(
2958 TALLOC_CTX *mem_ctx,
2959 struct tevent_context *ev,
2960 struct vfs_handle_struct *handle,
2961 files_struct *dir_fsp,
2962 const struct smb_filename *smb_fname,
2963 const char *xattr_name,
2966 struct tevent_req *req = NULL;
2967 struct tevent_req *subreq = NULL;
2968 struct vfswrap_getxattrat_state *state = NULL;
2969 size_t max_threads = 0;
2970 bool have_per_thread_cwd = false;
2971 bool have_per_thread_creds = false;
2972 bool do_async = false;
2974 req = tevent_req_create(mem_ctx, &state,
2975 struct vfswrap_getxattrat_state);
2979 *state = (struct vfswrap_getxattrat_state) {
2982 .smb_fname = smb_fname,
2986 max_threads = pthreadpool_tevent_max_threads(dir_fsp->conn->sconn->pool);
2987 if (max_threads >= 1) {
2989 * We need a non sync threadpool!
2991 have_per_thread_cwd = per_thread_cwd_supported();
2993 #ifdef HAVE_LINUX_THREAD_CREDENTIALS
2994 have_per_thread_creds = true;
2996 if (have_per_thread_cwd && have_per_thread_creds) {
3000 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat, profile_p,
3001 state->profile_bytes, 0);
3003 if (dir_fsp->fh->fd == -1) {
3004 DBG_ERR("Need a valid directory fd\n");
3005 tevent_req_error(req, EINVAL);
3006 return tevent_req_post(req, ev);
3009 if (alloc_hint > 0) {
3010 state->xattr_value = talloc_zero_array(state,
3013 if (tevent_req_nomem(state->xattr_value, req)) {
3014 return tevent_req_post(req, ev);
3019 vfswrap_getxattrat_do_sync(req);
3020 return tevent_req_post(req, ev);
3024 * Now allocate all parameters from a memory context that won't go away
3025 * no matter what. These paremeters will get used in threads and we
3026 * can't reliably cancel threads, so all buffers passed to the threads
3027 * must not be freed before all referencing threads terminate.
3030 state->name = talloc_strdup(state, smb_fname->base_name);
3031 if (tevent_req_nomem(state->name, req)) {
3032 return tevent_req_post(req, ev);
3035 state->xattr_name = talloc_strdup(state, xattr_name);
3036 if (tevent_req_nomem(state->xattr_name, req)) {
3037 return tevent_req_post(req, ev);
3041 * This is a hot codepath so at first glance one might think we should
3042 * somehow optimize away the token allocation and do a
3043 * talloc_reference() or similar black magic instead. But due to the
3044 * talloc_stackframe pool per SMB2 request this should be a simple copy
3045 * without a malloc in most cases.
3047 if (geteuid() == sec_initial_uid()) {
3048 state->token = root_unix_token(state);
3050 state->token = copy_unix_token(
3052 dir_fsp->conn->session_info->unix_token);
3054 if (tevent_req_nomem(state->token, req)) {
3055 return tevent_req_post(req, ev);
3058 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3060 subreq = pthreadpool_tevent_job_send(
3063 dir_fsp->conn->sconn->pool,
3064 vfswrap_getxattrat_do_async,
3066 if (tevent_req_nomem(subreq, req)) {
3067 return tevent_req_post(req, ev);
3069 tevent_req_set_callback(subreq, vfswrap_getxattrat_done, req);
3071 talloc_set_destructor(state, vfswrap_getxattrat_state_destructor);
3076 static void vfswrap_getxattrat_do_sync(struct tevent_req *req)
3078 struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3079 req, struct vfswrap_getxattrat_state);
3081 char *tofree = NULL;
3082 char pathbuf[PATH_MAX+1];
3086 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
3087 state->smb_fname->base_name,
3092 if (pathlen == -1) {
3093 tevent_req_error(req, ENOMEM);
3097 state->xattr_size = getxattr(path,
3100 talloc_array_length(state->xattr_value));
3102 TALLOC_FREE(tofree);
3103 if (state->xattr_size == -1) {
3104 tevent_req_error(req, err);
3108 tevent_req_done(req);
3112 static void vfswrap_getxattrat_do_async(void *private_data)
3114 struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3115 private_data, struct vfswrap_getxattrat_state);
3116 struct timespec start_time;
3117 struct timespec end_time;
3120 PROFILE_TIMESTAMP(&start_time);
3121 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
3124 * Here we simulate a getxattrat()
3125 * call using fchdir();getxattr()
3128 per_thread_cwd_activate();
3130 /* Become the correct credential on this thread. */
3131 ret = set_thread_credentials(state->token->uid,
3133 (size_t)state->token->ngroups,
3134 state->token->groups);
3136 state->xattr_size = -1;
3137 state->vfs_aio_state.error = errno;
3141 ret = fchdir(state->dir_fsp->fh->fd);
3143 state->xattr_size = -1;
3144 state->vfs_aio_state.error = errno;
3148 state->xattr_size = getxattr(state->name,
3151 talloc_array_length(state->xattr_value));
3152 if (state->xattr_size == -1) {
3153 state->vfs_aio_state.error = errno;
3157 PROFILE_TIMESTAMP(&end_time);
3158 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
3159 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3162 static void vfswrap_getxattrat_done(struct tevent_req *subreq)
3164 struct tevent_req *req = tevent_req_callback_data(
3165 subreq, struct tevent_req);
3166 struct vfswrap_getxattrat_state *state = tevent_req_data(
3167 req, struct vfswrap_getxattrat_state);
3172 * Make sure we run as the user again
3174 ok = change_to_user_by_fsp(state->dir_fsp);
3177 ret = pthreadpool_tevent_job_recv(subreq);
3178 TALLOC_FREE(subreq);
3179 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
3180 talloc_set_destructor(state, NULL);
3182 if (ret != EAGAIN) {
3183 tevent_req_error(req, ret);
3187 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
3188 * means the lower level pthreadpool failed to create a new
3189 * thread. Fallback to sync processing in that case to allow
3190 * some progress for the client.
3192 vfswrap_getxattrat_do_sync(req);
3196 if (state->xattr_size == -1) {
3197 tevent_req_error(req, state->vfs_aio_state.error);
3201 if (state->xattr_value == NULL) {
3203 * The caller only wanted the size.
3205 tevent_req_done(req);
3210 * shrink the buffer to the returned size.
3211 * (can't fail). It means NULL if size is 0.
3213 state->xattr_value = talloc_realloc(state,
3218 tevent_req_done(req);
3221 static ssize_t vfswrap_getxattrat_recv(struct tevent_req *req,
3222 struct vfs_aio_state *aio_state,
3223 TALLOC_CTX *mem_ctx,
3224 uint8_t **xattr_value)
3226 struct vfswrap_getxattrat_state *state = tevent_req_data(
3227 req, struct vfswrap_getxattrat_state);
3230 if (tevent_req_is_unix_error(req, &aio_state->error)) {
3231 tevent_req_received(req);
3235 *aio_state = state->vfs_aio_state;
3236 xattr_size = state->xattr_size;
3237 if (xattr_value != NULL) {
3238 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
3241 tevent_req_received(req);
3245 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
3247 return fgetxattr(fsp->fh->fd, name, value, size);
3250 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
3251 const struct smb_filename *smb_fname,
3255 return listxattr(smb_fname->base_name, list, size);
3258 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
3260 return flistxattr(fsp->fh->fd, list, size);
3263 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
3264 const struct smb_filename *smb_fname,
3267 return removexattr(smb_fname->base_name, name);
3270 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
3272 return fremovexattr(fsp->fh->fd, name);
3275 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
3276 const struct smb_filename *smb_fname,
3282 return setxattr(smb_fname->base_name, name, value, size, flags);
3285 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
3287 return fsetxattr(fsp->fh->fd, name, value, size, flags);
3290 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
3295 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
3296 const struct smb_filename *fname,
3297 SMB_STRUCT_STAT *sbuf)
3301 bool offline = false;
3303 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
3307 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
3308 #if defined(ENOTSUP)
3314 status = get_full_smb_filename(talloc_tos(), fname, &path);
3315 if (!NT_STATUS_IS_OK(status)) {
3316 errno = map_errno_from_nt_status(status);
3320 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
3327 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
3328 struct files_struct *fsp,
3329 TALLOC_CTX *mem_ctx,
3332 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
3335 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
3336 struct files_struct *fsp,
3337 const DATA_BLOB old_cookie,
3338 TALLOC_CTX *mem_ctx,
3339 DATA_BLOB *new_cookie)
3341 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
3345 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
3346 struct smb_request *smb1req,
3347 struct smbXsrv_open *op,
3348 const DATA_BLOB old_cookie,
3349 TALLOC_CTX *mem_ctx,
3350 struct files_struct **fsp,
3351 DATA_BLOB *new_cookie)
3353 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
3354 old_cookie, mem_ctx,
3358 static struct vfs_fn_pointers vfs_default_fns = {
3359 /* Disk operations */
3361 .connect_fn = vfswrap_connect,
3362 .disconnect_fn = vfswrap_disconnect,
3363 .disk_free_fn = vfswrap_disk_free,
3364 .get_quota_fn = vfswrap_get_quota,
3365 .set_quota_fn = vfswrap_set_quota,
3366 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3367 .statvfs_fn = vfswrap_statvfs,
3368 .fs_capabilities_fn = vfswrap_fs_capabilities,
3369 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3370 .snap_check_path_fn = vfswrap_snap_check_path,
3371 .snap_create_fn = vfswrap_snap_create,
3372 .snap_delete_fn = vfswrap_snap_delete,
3374 /* Directory operations */
3376 .opendir_fn = vfswrap_opendir,
3377 .fdopendir_fn = vfswrap_fdopendir,
3378 .readdir_fn = vfswrap_readdir,
3379 .readdir_attr_fn = vfswrap_readdir_attr,
3380 .seekdir_fn = vfswrap_seekdir,
3381 .telldir_fn = vfswrap_telldir,
3382 .rewind_dir_fn = vfswrap_rewinddir,
3383 .mkdir_fn = vfswrap_mkdir,
3384 .rmdir_fn = vfswrap_rmdir,
3385 .closedir_fn = vfswrap_closedir,
3387 /* File operations */
3389 .open_fn = vfswrap_open,
3390 .create_file_fn = vfswrap_create_file,
3391 .close_fn = vfswrap_close,
3392 .pread_fn = vfswrap_pread,
3393 .pread_send_fn = vfswrap_pread_send,
3394 .pread_recv_fn = vfswrap_pread_recv,
3395 .pwrite_fn = vfswrap_pwrite,
3396 .pwrite_send_fn = vfswrap_pwrite_send,
3397 .pwrite_recv_fn = vfswrap_pwrite_recv,
3398 .lseek_fn = vfswrap_lseek,
3399 .sendfile_fn = vfswrap_sendfile,
3400 .recvfile_fn = vfswrap_recvfile,
3401 .rename_fn = vfswrap_rename,
3402 .fsync_send_fn = vfswrap_fsync_send,
3403 .fsync_recv_fn = vfswrap_fsync_recv,
3404 .stat_fn = vfswrap_stat,
3405 .fstat_fn = vfswrap_fstat,
3406 .lstat_fn = vfswrap_lstat,
3407 .get_alloc_size_fn = vfswrap_get_alloc_size,
3408 .unlink_fn = vfswrap_unlink,
3409 .chmod_fn = vfswrap_chmod,
3410 .fchmod_fn = vfswrap_fchmod,
3411 .chown_fn = vfswrap_chown,
3412 .fchown_fn = vfswrap_fchown,
3413 .lchown_fn = vfswrap_lchown,
3414 .chdir_fn = vfswrap_chdir,
3415 .getwd_fn = vfswrap_getwd,
3416 .ntimes_fn = vfswrap_ntimes,
3417 .ftruncate_fn = vfswrap_ftruncate,
3418 .fallocate_fn = vfswrap_fallocate,
3419 .lock_fn = vfswrap_lock,
3420 .kernel_flock_fn = vfswrap_kernel_flock,
3421 .linux_setlease_fn = vfswrap_linux_setlease,
3422 .getlock_fn = vfswrap_getlock,
3423 .symlink_fn = vfswrap_symlink,
3424 .readlink_fn = vfswrap_readlink,
3425 .link_fn = vfswrap_link,
3426 .mknod_fn = vfswrap_mknod,
3427 .realpath_fn = vfswrap_realpath,
3428 .chflags_fn = vfswrap_chflags,
3429 .file_id_create_fn = vfswrap_file_id_create,
3430 .streaminfo_fn = vfswrap_streaminfo,
3431 .get_real_filename_fn = vfswrap_get_real_filename,
3432 .connectpath_fn = vfswrap_connectpath,
3433 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
3434 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3435 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
3436 .strict_lock_check_fn = vfswrap_strict_lock_check,
3437 .translate_name_fn = vfswrap_translate_name,
3438 .fsctl_fn = vfswrap_fsctl,
3439 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
3440 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
3441 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
3442 .get_dos_attributes_send_fn = vfswrap_get_dos_attributes_send,
3443 .get_dos_attributes_recv_fn = vfswrap_get_dos_attributes_recv,
3444 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
3445 .offload_read_send_fn = vfswrap_offload_read_send,
3446 .offload_read_recv_fn = vfswrap_offload_read_recv,
3447 .offload_write_send_fn = vfswrap_offload_write_send,
3448 .offload_write_recv_fn = vfswrap_offload_write_recv,
3449 .get_compression_fn = vfswrap_get_compression,
3450 .set_compression_fn = vfswrap_set_compression,
3452 /* NT ACL operations. */
3454 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
3455 .get_nt_acl_fn = vfswrap_get_nt_acl,
3456 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
3457 .audit_file_fn = vfswrap_audit_file,
3459 /* POSIX ACL operations. */
3461 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
3462 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3463 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
3464 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3465 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
3466 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3467 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
3469 /* EA operations. */
3470 .getxattr_fn = vfswrap_getxattr,
3471 .getxattrat_send_fn = vfswrap_getxattrat_send,
3472 .getxattrat_recv_fn = vfswrap_getxattrat_recv,
3473 .fgetxattr_fn = vfswrap_fgetxattr,
3474 .listxattr_fn = vfswrap_listxattr,
3475 .flistxattr_fn = vfswrap_flistxattr,
3476 .removexattr_fn = vfswrap_removexattr,
3477 .fremovexattr_fn = vfswrap_fremovexattr,
3478 .setxattr_fn = vfswrap_setxattr,
3479 .fsetxattr_fn = vfswrap_fsetxattr,
3481 /* aio operations */
3482 .aio_force_fn = vfswrap_aio_force,
3484 /* durable handle operations */
3485 .durable_cookie_fn = vfswrap_durable_cookie,
3486 .durable_disconnect_fn = vfswrap_durable_disconnect,
3487 .durable_reconnect_fn = vfswrap_durable_reconnect,
3491 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3494 * Here we need to implement every call!
3496 * As this is the end of the vfs module chain.
3498 smb_vfs_assert_all_fns(&vfs_default_fns, DEFAULT_VFS_MODULE_NAME);
3499 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3500 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);