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);
991 if (tevent_req_error(req, ret)) {
995 tevent_req_done(req);
998 static int vfswrap_fsync_recv(struct tevent_req *req,
999 struct vfs_aio_state *vfs_aio_state)
1001 struct vfswrap_fsync_state *state = tevent_req_data(
1002 req, struct vfswrap_fsync_state);
1004 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1008 *vfs_aio_state = state->vfs_aio_state;
1012 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1016 START_PROFILE(syscall_lseek);
1018 /* Cope with 'stat' file opens. */
1019 if (fsp->fh->fd != -1)
1020 result = lseek(fsp->fh->fd, offset, whence);
1023 * We want to maintain the fiction that we can seek
1024 * on a fifo for file system purposes. This allows
1025 * people to set up UNIX fifo's that feed data to Windows
1026 * applications. JRA.
1029 if((result == -1) && (errno == ESPIPE)) {
1034 END_PROFILE(syscall_lseek);
1038 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1039 off_t offset, size_t n)
1043 START_PROFILE_BYTES(syscall_sendfile, n);
1044 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
1045 END_PROFILE_BYTES(syscall_sendfile);
1049 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1051 files_struct *tofsp,
1057 START_PROFILE_BYTES(syscall_recvfile, n);
1058 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
1059 END_PROFILE_BYTES(syscall_recvfile);
1063 static int vfswrap_rename(vfs_handle_struct *handle,
1064 const struct smb_filename *smb_fname_src,
1065 const struct smb_filename *smb_fname_dst)
1069 START_PROFILE(syscall_rename);
1071 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
1076 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
1079 END_PROFILE(syscall_rename);
1083 static int vfswrap_stat(vfs_handle_struct *handle,
1084 struct smb_filename *smb_fname)
1088 START_PROFILE(syscall_stat);
1090 if (smb_fname->stream_name) {
1095 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1096 lp_fake_directory_create_times(SNUM(handle->conn)));
1098 END_PROFILE(syscall_stat);
1102 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1106 START_PROFILE(syscall_fstat);
1107 result = sys_fstat(fsp->fh->fd,
1108 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1109 END_PROFILE(syscall_fstat);
1113 static int vfswrap_lstat(vfs_handle_struct *handle,
1114 struct smb_filename *smb_fname)
1118 START_PROFILE(syscall_lstat);
1120 if (smb_fname->stream_name) {
1125 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1126 lp_fake_directory_create_times(SNUM(handle->conn)));
1128 END_PROFILE(syscall_lstat);
1132 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1134 enum vfs_translate_direction direction,
1135 TALLOC_CTX *mem_ctx,
1138 return NT_STATUS_NONE_MAPPED;
1142 * Implement the default fsctl operation.
1144 static bool vfswrap_logged_ioctl_message = false;
1146 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1147 struct files_struct *fsp,
1150 uint16_t req_flags, /* Needed for UNICODE ... */
1151 const uint8_t *_in_data,
1153 uint8_t **_out_data,
1154 uint32_t max_out_len,
1157 const char *in_data = (const char *)_in_data;
1158 char **out_data = (char **)_out_data;
1162 case FSCTL_SET_SPARSE:
1164 bool set_sparse = true;
1166 if (in_len >= 1 && in_data[0] == 0) {
1170 status = file_set_sparse(handle->conn, fsp, set_sparse);
1172 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1173 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1174 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1175 nt_errstr(status)));
1180 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1182 unsigned char objid[16];
1183 char *return_data = NULL;
1185 /* This should return the object-id on this file.
1186 * I think I'll make this be the inode+dev. JRA.
1189 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1190 fsp_fnum_dbg(fsp)));
1192 *out_len = MIN(max_out_len, 64);
1194 /* Hmmm, will this cause problems if less data asked for? */
1195 return_data = talloc_array(ctx, char, 64);
1196 if (return_data == NULL) {
1197 return NT_STATUS_NO_MEMORY;
1200 /* For backwards compatibility only store the dev/inode. */
1201 push_file_id_16(return_data, &fsp->file_id);
1202 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1203 push_file_id_16(return_data+32, &fsp->file_id);
1204 memset(return_data+48, 0, 16);
1205 *out_data = return_data;
1206 return NT_STATUS_OK;
1209 case FSCTL_GET_REPARSE_POINT:
1211 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1212 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1213 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1214 return NT_STATUS_NOT_A_REPARSE_POINT;
1217 case FSCTL_SET_REPARSE_POINT:
1219 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1220 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1221 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1222 return NT_STATUS_NOT_A_REPARSE_POINT;
1225 case FSCTL_GET_SHADOW_COPY_DATA:
1228 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1229 * and return their volume names. If max_data_count is 16, then it is just
1230 * asking for the number of volumes and length of the combined names.
1232 * pdata is the data allocated by our caller, but that uses
1233 * total_data_count (which is 0 in our case) rather than max_data_count.
1234 * Allocate the correct amount and return the pointer to let
1235 * it be deallocated when we return.
1237 struct shadow_copy_data *shadow_data = NULL;
1238 bool labels = False;
1239 uint32_t labels_data_count = 0;
1241 char *cur_pdata = NULL;
1243 if (max_out_len < 16) {
1244 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1246 return NT_STATUS_INVALID_PARAMETER;
1249 if (max_out_len > 16) {
1253 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1254 if (shadow_data == NULL) {
1255 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1256 return NT_STATUS_NO_MEMORY;
1260 * Call the VFS routine to actually do the work.
1262 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1265 /* broken module didn't set errno on error */
1266 status = NT_STATUS_UNSUCCESSFUL;
1268 status = map_nt_error_from_unix(errno);
1269 if (NT_STATUS_EQUAL(status,
1270 NT_STATUS_NOT_SUPPORTED)) {
1274 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1275 "connectpath %s, failed - %s.\n",
1276 fsp->conn->connectpath,
1277 nt_errstr(status)));
1278 TALLOC_FREE(shadow_data);
1282 labels_data_count = (shadow_data->num_volumes * 2 *
1283 sizeof(SHADOW_COPY_LABEL)) + 2;
1288 *out_len = 12 + labels_data_count;
1291 if (max_out_len < *out_len) {
1292 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1293 max_out_len, *out_len));
1294 TALLOC_FREE(shadow_data);
1295 return NT_STATUS_BUFFER_TOO_SMALL;
1298 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1299 if (cur_pdata == NULL) {
1300 TALLOC_FREE(shadow_data);
1301 return NT_STATUS_NO_MEMORY;
1304 *out_data = cur_pdata;
1306 /* num_volumes 4 bytes */
1307 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1310 /* num_labels 4 bytes */
1311 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1314 /* needed_data_count 4 bytes */
1315 SIVAL(cur_pdata, 8, labels_data_count);
1319 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1320 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1321 if (labels && shadow_data->labels) {
1322 for (i=0; i<shadow_data->num_volumes; i++) {
1324 status = srvstr_push(cur_pdata, req_flags,
1325 cur_pdata, shadow_data->labels[i],
1326 2 * sizeof(SHADOW_COPY_LABEL),
1327 STR_UNICODE|STR_TERMINATE, &len);
1328 if (!NT_STATUS_IS_OK(status)) {
1329 TALLOC_FREE(*out_data);
1330 TALLOC_FREE(shadow_data);
1333 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1334 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1338 TALLOC_FREE(shadow_data);
1340 return NT_STATUS_OK;
1343 case FSCTL_FIND_FILES_BY_SID:
1345 /* pretend this succeeded -
1347 * we have to send back a list with all files owned by this SID
1349 * but I have to check that --metze
1352 struct dom_sid_buf buf;
1356 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1357 fsp_fnum_dbg(fsp)));
1360 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1361 return NT_STATUS_INVALID_PARAMETER;
1364 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1366 /* unknown 4 bytes: this is not the length of the sid :-( */
1367 /*unknown = IVAL(pdata,0);*/
1369 if (!sid_parse(_in_data + 4, sid_len, &sid)) {
1370 return NT_STATUS_INVALID_PARAMETER;
1372 DEBUGADD(10, ("for SID: %s\n",
1373 dom_sid_str_buf(&sid, &buf)));
1375 if (!sid_to_uid(&sid, &uid)) {
1376 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1377 dom_sid_str_buf(&sid, &buf),
1378 (unsigned long)sid_len));
1382 /* we can take a look at the find source :-)
1384 * find ./ -uid $uid -name '*' is what we need here
1387 * and send 4bytes len and then NULL terminated unicode strings
1390 * but I don't know how to deal with the paged results
1391 * (maybe we can hang the result anywhere in the fsp struct)
1393 * but I don't know how to deal with the paged results
1394 * (maybe we can hang the result anywhere in the fsp struct)
1396 * we don't send all files at once
1397 * and at the next we should *not* start from the beginning,
1398 * so we have to cache the result
1403 /* this works for now... */
1404 return NT_STATUS_OK;
1407 case FSCTL_QUERY_ALLOCATED_RANGES:
1409 /* FIXME: This is just a dummy reply, telling that all of the
1410 * file is allocated. MKS cp needs that.
1411 * Adding the real allocated ranges via FIEMAP on Linux
1412 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1413 * this FSCTL correct for sparse files.
1415 uint64_t offset, length;
1416 char *out_data_tmp = NULL;
1419 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1421 return NT_STATUS_INVALID_PARAMETER;
1424 if (max_out_len < 16) {
1425 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1427 return NT_STATUS_INVALID_PARAMETER;
1430 offset = BVAL(in_data,0);
1431 length = BVAL(in_data,8);
1433 if (offset + length < offset) {
1434 /* No 64-bit integer wrap. */
1435 return NT_STATUS_INVALID_PARAMETER;
1438 /* Shouldn't this be SMB_VFS_STAT ... ? */
1439 status = vfs_stat_fsp(fsp);
1440 if (!NT_STATUS_IS_OK(status)) {
1445 out_data_tmp = talloc_array(ctx, char, *out_len);
1446 if (out_data_tmp == NULL) {
1447 DEBUG(10, ("unable to allocate memory for response\n"));
1448 return NT_STATUS_NO_MEMORY;
1451 if (offset > fsp->fsp_name->st.st_ex_size ||
1452 fsp->fsp_name->st.st_ex_size == 0 ||
1454 memset(out_data_tmp, 0, *out_len);
1456 uint64_t end = offset + length;
1457 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1458 SBVAL(out_data_tmp, 0, 0);
1459 SBVAL(out_data_tmp, 8, end);
1462 *out_data = out_data_tmp;
1464 return NT_STATUS_OK;
1467 case FSCTL_IS_VOLUME_DIRTY:
1469 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1470 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1472 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1473 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1475 return NT_STATUS_INVALID_PARAMETER;
1480 * Only print once ... unfortunately there could be lots of
1481 * different FSCTLs that are called.
1483 if (!vfswrap_logged_ioctl_message) {
1484 vfswrap_logged_ioctl_message = true;
1485 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1486 __func__, function));
1490 return NT_STATUS_NOT_SUPPORTED;
1493 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
1494 const struct smb_filename *fname,
1495 SMB_STRUCT_STAT *sbuf);
1497 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1498 struct smb_filename *smb_fname,
1503 offline = vfswrap_is_offline(handle, smb_fname, &smb_fname->st);
1505 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1508 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1511 struct vfswrap_get_dos_attributes_state {
1512 struct vfs_aio_state aio_state;
1513 connection_struct *conn;
1514 TALLOC_CTX *mem_ctx;
1515 struct tevent_context *ev;
1516 files_struct *dir_fsp;
1517 struct smb_filename *smb_fname;
1522 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq);
1524 static struct tevent_req *vfswrap_get_dos_attributes_send(
1525 TALLOC_CTX *mem_ctx,
1526 struct tevent_context *ev,
1527 struct vfs_handle_struct *handle,
1528 files_struct *dir_fsp,
1529 struct smb_filename *smb_fname)
1531 struct tevent_req *req = NULL;
1532 struct tevent_req *subreq = NULL;
1533 struct vfswrap_get_dos_attributes_state *state = NULL;
1535 req = tevent_req_create(mem_ctx, &state,
1536 struct vfswrap_get_dos_attributes_state);
1541 *state = (struct vfswrap_get_dos_attributes_state) {
1542 .conn = dir_fsp->conn,
1546 .smb_fname = smb_fname,
1549 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1553 SAMBA_XATTR_DOS_ATTRIB,
1555 if (tevent_req_nomem(subreq, req)) {
1556 return tevent_req_post(req, ev);
1558 tevent_req_set_callback(subreq,
1559 vfswrap_get_dos_attributes_getxattr_done,
1565 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq)
1567 struct tevent_req *req =
1568 tevent_req_callback_data(subreq,
1570 struct vfswrap_get_dos_attributes_state *state =
1571 tevent_req_data(req,
1572 struct vfswrap_get_dos_attributes_state);
1574 DATA_BLOB blob = {0};
1577 xattr_size = SMB_VFS_GETXATTRAT_RECV(subreq,
1581 TALLOC_FREE(subreq);
1582 if (xattr_size == -1) {
1583 status = map_nt_error_from_unix(state->aio_state.error);
1585 if (state->as_root) {
1586 tevent_req_nterror(req, status);
1589 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1590 tevent_req_nterror(req, status);
1594 state->as_root = true;
1597 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1601 SAMBA_XATTR_DOS_ATTRIB,
1604 if (tevent_req_nomem(subreq, req)) {
1607 tevent_req_set_callback(subreq,
1608 vfswrap_get_dos_attributes_getxattr_done,
1613 blob.length = xattr_size;
1615 status = parse_dos_attribute_blob(state->smb_fname,
1618 if (!NT_STATUS_IS_OK(status)) {
1619 tevent_req_nterror(req, status);
1623 tevent_req_done(req);
1627 static NTSTATUS vfswrap_get_dos_attributes_recv(struct tevent_req *req,
1628 struct vfs_aio_state *aio_state,
1631 struct vfswrap_get_dos_attributes_state *state =
1632 tevent_req_data(req,
1633 struct vfswrap_get_dos_attributes_state);
1636 if (tevent_req_is_nterror(req, &status)) {
1637 tevent_req_received(req);
1641 *aio_state = state->aio_state;
1642 *dosmode = state->dosmode;
1643 tevent_req_received(req);
1644 return NT_STATUS_OK;
1647 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1648 struct files_struct *fsp,
1653 offline = vfswrap_is_offline(handle, fsp->fsp_name, &fsp->fsp_name->st);
1655 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1658 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1661 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1662 const struct smb_filename *smb_fname,
1665 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1668 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1669 struct files_struct *fsp,
1672 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1675 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1677 struct vfswrap_offload_read_state {
1681 static struct tevent_req *vfswrap_offload_read_send(
1682 TALLOC_CTX *mem_ctx,
1683 struct tevent_context *ev,
1684 struct vfs_handle_struct *handle,
1685 struct files_struct *fsp,
1691 struct tevent_req *req = NULL;
1692 struct vfswrap_offload_read_state *state = NULL;
1695 req = tevent_req_create(mem_ctx, &state,
1696 struct vfswrap_offload_read_state);
1701 status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1702 &vfswrap_offload_ctx);
1703 if (tevent_req_nterror(req, status)) {
1704 return tevent_req_post(req, ev);
1707 if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1708 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1709 return tevent_req_post(req, ev);
1712 status = vfs_offload_token_create_blob(state, fsp, fsctl,
1714 if (tevent_req_nterror(req, status)) {
1715 return tevent_req_post(req, ev);
1718 status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1720 if (tevent_req_nterror(req, status)) {
1721 return tevent_req_post(req, ev);
1724 tevent_req_done(req);
1725 return tevent_req_post(req, ev);
1728 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
1729 struct vfs_handle_struct *handle,
1730 TALLOC_CTX *mem_ctx,
1733 struct vfswrap_offload_read_state *state = tevent_req_data(
1734 req, struct vfswrap_offload_read_state);
1737 if (tevent_req_is_nterror(req, &status)) {
1738 tevent_req_received(req);
1742 token->length = state->token.length;
1743 token->data = talloc_move(mem_ctx, &state->token.data);
1745 tevent_req_received(req);
1746 return NT_STATUS_OK;
1749 struct vfswrap_offload_write_state {
1751 bool read_lck_locked;
1752 bool write_lck_locked;
1754 struct tevent_context *src_ev;
1755 struct files_struct *src_fsp;
1757 struct tevent_context *dst_ev;
1758 struct files_struct *dst_fsp;
1762 size_t next_io_size;
1765 static void vfswrap_offload_write_cleanup(struct tevent_req *req,
1766 enum tevent_req_state req_state)
1768 struct vfswrap_offload_write_state *state = tevent_req_data(
1769 req, struct vfswrap_offload_write_state);
1772 if (state->dst_fsp == NULL) {
1776 ok = change_to_user_by_fsp(state->dst_fsp);
1778 state->dst_fsp = NULL;
1781 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
1783 static struct tevent_req *vfswrap_offload_write_send(
1784 struct vfs_handle_struct *handle,
1785 TALLOC_CTX *mem_ctx,
1786 struct tevent_context *ev,
1789 off_t transfer_offset,
1790 struct files_struct *dest_fsp,
1794 struct tevent_req *req;
1795 struct vfswrap_offload_write_state *state = NULL;
1796 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
1797 files_struct *src_fsp = NULL;
1801 req = tevent_req_create(mem_ctx, &state,
1802 struct vfswrap_offload_write_state);
1807 *state = (struct vfswrap_offload_write_state) {
1809 .src_off = transfer_offset,
1811 .dst_fsp = dest_fsp,
1812 .dst_off = dest_off,
1814 .remaining = to_copy,
1817 tevent_req_set_cleanup_fn(req, vfswrap_offload_write_cleanup);
1820 case FSCTL_SRV_COPYCHUNK:
1821 case FSCTL_SRV_COPYCHUNK_WRITE:
1824 case FSCTL_OFFLOAD_WRITE:
1825 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
1826 return tevent_req_post(req, ev);
1828 case FSCTL_DUP_EXTENTS_TO_FILE:
1829 DBG_DEBUG("COW clones not supported by vfs_default\n");
1830 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1831 return tevent_req_post(req, ev);
1834 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1835 return tevent_req_post(req, ev);
1839 * From here on we assume a copy-chunk fsctl
1843 tevent_req_done(req);
1844 return tevent_req_post(req, ev);
1847 status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
1849 if (tevent_req_nterror(req, status)) {
1850 return tevent_req_post(req, ev);
1853 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
1855 status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
1856 if (!NT_STATUS_IS_OK(status)) {
1857 tevent_req_nterror(req, status);
1858 return tevent_req_post(req, ev);
1861 ok = change_to_user_by_fsp(src_fsp);
1863 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1864 return tevent_req_post(req, ev);
1867 state->src_ev = src_fsp->conn->sconn->ev_ctx;
1868 state->src_fsp = src_fsp;
1870 state->buf = talloc_array(state, uint8_t, num);
1871 if (tevent_req_nomem(state->buf, req)) {
1872 return tevent_req_post(req, ev);
1875 status = vfs_stat_fsp(src_fsp);
1876 if (tevent_req_nterror(req, status)) {
1877 return tevent_req_post(req, ev);
1880 if (src_fsp->fsp_name->st.st_ex_size < state->src_off + num) {
1882 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1883 * If the SourceOffset or SourceOffset + Length extends beyond
1884 * the end of file, the server SHOULD<240> treat this as a
1885 * STATUS_END_OF_FILE error.
1887 * <240> Section 3.3.5.15.6: Windows servers will return
1888 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1890 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1891 return tevent_req_post(req, ev);
1894 status = vfswrap_offload_write_loop(req);
1895 if (!NT_STATUS_IS_OK(status)) {
1896 tevent_req_nterror(req, status);
1897 return tevent_req_post(req, ev);
1903 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
1905 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
1907 struct vfswrap_offload_write_state *state = tevent_req_data(
1908 req, struct vfswrap_offload_write_state);
1909 struct tevent_req *subreq = NULL;
1910 struct lock_struct read_lck;
1914 * This is called under the context of state->src_fsp.
1917 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
1919 init_strict_lock_struct(state->src_fsp,
1920 state->src_fsp->op->global->open_persistent_id,
1922 state->next_io_size,
1926 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
1930 return NT_STATUS_FILE_LOCK_CONFLICT;
1933 subreq = SMB_VFS_PREAD_SEND(state,
1937 state->next_io_size,
1939 if (subreq == NULL) {
1940 return NT_STATUS_NO_MEMORY;
1942 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
1944 return NT_STATUS_OK;
1947 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
1949 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
1951 struct tevent_req *req = tevent_req_callback_data(
1952 subreq, struct tevent_req);
1953 struct vfswrap_offload_write_state *state = tevent_req_data(
1954 req, struct vfswrap_offload_write_state);
1955 struct vfs_aio_state aio_state;
1956 struct lock_struct write_lck;
1960 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
1961 TALLOC_FREE(subreq);
1963 DBG_ERR("read failed: %s\n", strerror(errno));
1964 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1967 if (nread != state->next_io_size) {
1968 DBG_ERR("Short read, only %zd of %zu\n",
1969 nread, state->next_io_size);
1970 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1974 state->src_off += nread;
1976 ok = change_to_user_by_fsp(state->dst_fsp);
1978 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1982 init_strict_lock_struct(state->dst_fsp,
1983 state->dst_fsp->op->global->open_persistent_id,
1985 state->next_io_size,
1989 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
1993 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1997 subreq = SMB_VFS_PWRITE_SEND(state,
2001 state->next_io_size,
2003 if (subreq == NULL) {
2004 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2007 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
2010 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
2012 struct tevent_req *req = tevent_req_callback_data(
2013 subreq, struct tevent_req);
2014 struct vfswrap_offload_write_state *state = tevent_req_data(
2015 req, struct vfswrap_offload_write_state);
2016 struct vfs_aio_state aio_state;
2021 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
2022 TALLOC_FREE(subreq);
2023 if (nwritten == -1) {
2024 DBG_ERR("write failed: %s\n", strerror(errno));
2025 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2028 if (nwritten != state->next_io_size) {
2029 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
2030 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2034 state->dst_off += nwritten;
2036 if (state->remaining < nwritten) {
2037 /* Paranoia check */
2038 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2041 state->remaining -= nwritten;
2042 if (state->remaining == 0) {
2043 tevent_req_done(req);
2047 ok = change_to_user_by_fsp(state->src_fsp);
2049 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2053 status = vfswrap_offload_write_loop(req);
2054 if (!NT_STATUS_IS_OK(status)) {
2055 tevent_req_nterror(req, status);
2062 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
2063 struct tevent_req *req,
2066 struct vfswrap_offload_write_state *state = tevent_req_data(
2067 req, struct vfswrap_offload_write_state);
2070 if (tevent_req_is_nterror(req, &status)) {
2071 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
2073 tevent_req_received(req);
2077 *copied = state->to_copy;
2078 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
2079 tevent_req_received(req);
2081 return NT_STATUS_OK;
2084 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
2085 TALLOC_CTX *mem_ctx,
2086 struct files_struct *fsp,
2087 struct smb_filename *smb_fname,
2088 uint16_t *_compression_fmt)
2090 return NT_STATUS_INVALID_DEVICE_REQUEST;
2093 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
2094 TALLOC_CTX *mem_ctx,
2095 struct files_struct *fsp,
2096 uint16_t compression_fmt)
2098 return NT_STATUS_INVALID_DEVICE_REQUEST;
2101 /********************************************************************
2102 Given a stat buffer return the allocated size on disk, taking into
2103 account sparse files.
2104 ********************************************************************/
2105 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
2106 struct files_struct *fsp,
2107 const SMB_STRUCT_STAT *sbuf)
2111 START_PROFILE(syscall_get_alloc_size);
2113 if(S_ISDIR(sbuf->st_ex_mode)) {
2118 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2119 /* The type of st_blocksize is blkcnt_t which *MUST* be
2120 signed (according to POSIX) and can be less than 64-bits.
2121 Ensure when we're converting to 64 bits wide we don't
2123 #if defined(SIZEOF_BLKCNT_T_8)
2124 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2125 #elif defined(SIZEOF_BLKCNT_T_4)
2127 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2128 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2131 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2135 * Some file systems do not allocate a block for very
2136 * small files. But for non-empty file should report a
2140 uint64_t filesize = get_file_size_stat(sbuf);
2142 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2146 result = get_file_size_stat(sbuf);
2149 if (fsp && fsp->initial_allocation_size)
2150 result = MAX(result,fsp->initial_allocation_size);
2152 result = smb_roundup(handle->conn, result);
2155 END_PROFILE(syscall_get_alloc_size);
2159 static int vfswrap_unlink(vfs_handle_struct *handle,
2160 const struct smb_filename *smb_fname)
2164 START_PROFILE(syscall_unlink);
2166 if (smb_fname->stream_name) {
2170 result = unlink(smb_fname->base_name);
2173 END_PROFILE(syscall_unlink);
2177 static int vfswrap_chmod(vfs_handle_struct *handle,
2178 const struct smb_filename *smb_fname,
2183 START_PROFILE(syscall_chmod);
2184 result = chmod(smb_fname->base_name, mode);
2185 END_PROFILE(syscall_chmod);
2189 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2193 START_PROFILE(syscall_fchmod);
2194 #if defined(HAVE_FCHMOD)
2195 result = fchmod(fsp->fh->fd, mode);
2201 END_PROFILE(syscall_fchmod);
2205 static int vfswrap_chown(vfs_handle_struct *handle,
2206 const struct smb_filename *smb_fname,
2212 START_PROFILE(syscall_chown);
2213 result = chown(smb_fname->base_name, uid, gid);
2214 END_PROFILE(syscall_chown);
2218 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2223 START_PROFILE(syscall_fchown);
2224 result = fchown(fsp->fh->fd, uid, gid);
2225 END_PROFILE(syscall_fchown);
2233 static int vfswrap_lchown(vfs_handle_struct *handle,
2234 const struct smb_filename *smb_fname,
2240 START_PROFILE(syscall_lchown);
2241 result = lchown(smb_fname->base_name, uid, gid);
2242 END_PROFILE(syscall_lchown);
2246 static int vfswrap_chdir(vfs_handle_struct *handle,
2247 const struct smb_filename *smb_fname)
2251 START_PROFILE(syscall_chdir);
2252 result = chdir(smb_fname->base_name);
2253 END_PROFILE(syscall_chdir);
2257 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2261 struct smb_filename *smb_fname = NULL;
2263 START_PROFILE(syscall_getwd);
2264 result = sys_getwd();
2265 END_PROFILE(syscall_getwd);
2267 if (result == NULL) {
2270 smb_fname = synthetic_smb_fname(ctx,
2276 * sys_getwd() *always* returns malloced memory.
2277 * We must free here to avoid leaks:
2278 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2284 /*********************************************************************
2285 nsec timestamp resolution call. Convert down to whatever the underlying
2286 system will support.
2287 **********************************************************************/
2289 static int vfswrap_ntimes(vfs_handle_struct *handle,
2290 const struct smb_filename *smb_fname,
2291 struct smb_file_time *ft)
2295 START_PROFILE(syscall_ntimes);
2297 if (smb_fname->stream_name) {
2303 if (null_timespec(ft->atime)) {
2304 ft->atime= smb_fname->st.st_ex_atime;
2307 if (null_timespec(ft->mtime)) {
2308 ft->mtime = smb_fname->st.st_ex_mtime;
2311 if (!null_timespec(ft->create_time)) {
2312 set_create_timespec_ea(handle->conn,
2317 if ((timespec_compare(&ft->atime,
2318 &smb_fname->st.st_ex_atime) == 0) &&
2319 (timespec_compare(&ft->mtime,
2320 &smb_fname->st.st_ex_mtime) == 0)) {
2325 #if defined(HAVE_UTIMENSAT)
2327 struct timespec ts[2];
2330 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2332 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2334 if (!((result == -1) && (errno == ENOSYS))) {
2338 #if defined(HAVE_UTIMES)
2340 struct timeval tv[2];
2341 tv[0] = convert_timespec_to_timeval(ft->atime);
2342 tv[1] = convert_timespec_to_timeval(ft->mtime);
2343 result = utimes(smb_fname->base_name, tv);
2345 result = utimes(smb_fname->base_name, NULL);
2347 if (!((result == -1) && (errno == ENOSYS))) {
2351 #if defined(HAVE_UTIME)
2353 struct utimbuf times;
2354 times.actime = convert_timespec_to_time_t(ft->atime);
2355 times.modtime = convert_timespec_to_time_t(ft->mtime);
2356 result = utime(smb_fname->base_name, ×);
2358 result = utime(smb_fname->base_name, NULL);
2360 if (!((result == -1) && (errno == ENOSYS))) {
2368 END_PROFILE(syscall_ntimes);
2372 /*********************************************************************
2373 A version of ftruncate that will write the space on disk if strict
2375 **********************************************************************/
2377 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2379 off_t space_to_write;
2380 uint64_t space_avail;
2381 uint64_t bsize,dfree,dsize;
2384 SMB_STRUCT_STAT *pst;
2386 status = vfs_stat_fsp(fsp);
2387 if (!NT_STATUS_IS_OK(status)) {
2390 pst = &fsp->fsp_name->st;
2393 if (S_ISFIFO(pst->st_ex_mode))
2397 if (pst->st_ex_size == len)
2400 /* Shrink - just ftruncate. */
2401 if (pst->st_ex_size > len)
2402 return ftruncate(fsp->fh->fd, len);
2404 space_to_write = len - pst->st_ex_size;
2406 /* for allocation try fallocate first. This can fail on some
2407 platforms e.g. when the filesystem doesn't support it and no
2408 emulation is being done by the libc (like on AIX with JFS1). In that
2409 case we do our own emulation. fallocate implementations can
2410 return ENOTSUP or EINVAL in cases like that. */
2411 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2412 if (ret == -1 && errno == ENOSPC) {
2418 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2419 "error %d. Falling back to slow manual allocation\n", errno));
2421 /* available disk space is enough or not? */
2423 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2424 /* space_avail is 1k blocks */
2425 if (space_avail == (uint64_t)-1 ||
2426 ((uint64_t)space_to_write/1024 > space_avail) ) {
2431 /* Write out the real space on disk. */
2432 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2440 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2443 SMB_STRUCT_STAT *pst;
2447 START_PROFILE(syscall_ftruncate);
2449 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2450 result = strict_allocate_ftruncate(handle, fsp, len);
2451 END_PROFILE(syscall_ftruncate);
2455 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2456 ftruncate if the system supports it. Then I discovered that
2457 you can have some filesystems that support ftruncate
2458 expansion and some that don't! On Linux fat can't do
2459 ftruncate extend but ext2 can. */
2461 result = ftruncate(fsp->fh->fd, len);
2463 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2464 extend a file with ftruncate. Provide alternate implementation
2467 /* Do an fstat to see if the file is longer than the requested
2468 size in which case the ftruncate above should have
2469 succeeded or shorter, in which case seek to len - 1 and
2470 write 1 byte of zero */
2471 status = vfs_stat_fsp(fsp);
2472 if (!NT_STATUS_IS_OK(status)) {
2476 /* We need to update the files_struct after successful ftruncate */
2481 pst = &fsp->fsp_name->st;
2484 if (S_ISFIFO(pst->st_ex_mode)) {
2490 if (pst->st_ex_size == len) {
2495 if (pst->st_ex_size > len) {
2496 /* the ftruncate should have worked */
2500 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2508 END_PROFILE(syscall_ftruncate);
2512 static int vfswrap_fallocate(vfs_handle_struct *handle,
2520 START_PROFILE(syscall_fallocate);
2522 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2524 * posix_fallocate returns 0 on success, errno on error
2525 * and doesn't set errno. Make it behave like fallocate()
2526 * which returns -1, and sets errno on failure.
2533 /* sys_fallocate handles filtering of unsupported mode flags */
2534 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2536 END_PROFILE(syscall_fallocate);
2540 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2544 START_PROFILE(syscall_fcntl_lock);
2546 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2548 "force process locks",
2550 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2553 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2554 END_PROFILE(syscall_fcntl_lock);
2558 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2559 uint32_t share_mode, uint32_t access_mask)
2561 START_PROFILE(syscall_kernel_flock);
2562 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2563 END_PROFILE(syscall_kernel_flock);
2567 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2572 START_PROFILE(syscall_fcntl_getlock);
2574 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2576 "force process locks",
2578 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2581 result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2582 END_PROFILE(syscall_fcntl_getlock);
2586 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2591 START_PROFILE(syscall_linux_setlease);
2593 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2594 result = linux_setlease(fsp->fh->fd, leasetype);
2598 END_PROFILE(syscall_linux_setlease);
2602 static int vfswrap_symlink(vfs_handle_struct *handle,
2603 const char *link_target,
2604 const struct smb_filename *new_smb_fname)
2608 START_PROFILE(syscall_symlink);
2609 result = symlink(link_target, new_smb_fname->base_name);
2610 END_PROFILE(syscall_symlink);
2614 static int vfswrap_readlink(vfs_handle_struct *handle,
2615 const struct smb_filename *smb_fname,
2621 START_PROFILE(syscall_readlink);
2622 result = readlink(smb_fname->base_name, buf, bufsiz);
2623 END_PROFILE(syscall_readlink);
2627 static int vfswrap_link(vfs_handle_struct *handle,
2628 const struct smb_filename *old_smb_fname,
2629 const struct smb_filename *new_smb_fname)
2633 START_PROFILE(syscall_link);
2634 result = link(old_smb_fname->base_name, new_smb_fname->base_name);
2635 END_PROFILE(syscall_link);
2639 static int vfswrap_mknod(vfs_handle_struct *handle,
2640 const struct smb_filename *smb_fname,
2646 START_PROFILE(syscall_mknod);
2647 result = sys_mknod(smb_fname->base_name, mode, dev);
2648 END_PROFILE(syscall_mknod);
2652 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2654 const struct smb_filename *smb_fname)
2657 struct smb_filename *result_fname = NULL;
2659 START_PROFILE(syscall_realpath);
2660 result = sys_realpath(smb_fname->base_name);
2661 END_PROFILE(syscall_realpath);
2663 result_fname = synthetic_smb_fname(ctx, result, NULL, NULL, 0);
2666 return result_fname;
2669 static int vfswrap_chflags(vfs_handle_struct *handle,
2670 const struct smb_filename *smb_fname,
2674 return chflags(smb_fname->base_name, flags);
2681 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2682 const SMB_STRUCT_STAT *sbuf)
2686 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2690 key.devid = sbuf->st_ex_dev;
2691 key.inode = sbuf->st_ex_ino;
2692 /* key.extid is unused by default. */
2697 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2698 struct files_struct *fsp,
2699 const struct smb_filename *smb_fname,
2700 TALLOC_CTX *mem_ctx,
2701 unsigned int *pnum_streams,
2702 struct stream_struct **pstreams)
2704 SMB_STRUCT_STAT sbuf;
2705 struct stream_struct *tmp_streams = NULL;
2708 if ((fsp != NULL) && (fsp->is_directory)) {
2710 * No default streams on directories
2715 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2716 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2719 struct smb_filename smb_fname_cp;
2721 ZERO_STRUCT(smb_fname_cp);
2722 smb_fname_cp.base_name = discard_const_p(char,
2723 smb_fname->base_name);
2724 smb_fname_cp.flags = smb_fname->flags;
2726 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
2727 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2729 ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2731 sbuf = smb_fname_cp.st;
2735 return map_nt_error_from_unix(errno);
2738 if (S_ISDIR(sbuf.st_ex_mode)) {
2742 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2743 (*pnum_streams) + 1);
2744 if (tmp_streams == NULL) {
2745 return NT_STATUS_NO_MEMORY;
2747 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2748 if (tmp_streams[*pnum_streams].name == NULL) {
2749 return NT_STATUS_NO_MEMORY;
2751 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2752 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2755 *pstreams = tmp_streams;
2757 return NT_STATUS_OK;
2760 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2763 TALLOC_CTX *mem_ctx,
2767 * Don't fall back to get_real_filename so callers can differentiate
2768 * between a full directory scan and an actual case-insensitive stat.
2774 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2775 const struct smb_filename *smb_fname)
2777 return handle->conn->connectpath;
2780 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2781 struct byte_range_lock *br_lck,
2782 struct lock_struct *plock,
2785 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2787 /* Note: blr is not used in the default implementation. */
2788 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2791 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2792 struct messaging_context *msg_ctx,
2793 struct byte_range_lock *br_lck,
2794 const struct lock_struct *plock)
2796 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2798 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2801 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2802 struct byte_range_lock *br_lck,
2803 struct lock_struct *plock)
2805 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2807 /* Note: blr is not used in the default implementation. */
2808 return brl_lock_cancel_default(br_lck, plock);
2811 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
2813 struct lock_struct *plock)
2815 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2816 plock->lock_type == WRITE_LOCK);
2818 return strict_lock_check_default(fsp, plock);
2821 /* NT ACL operations. */
2823 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2825 uint32_t security_info,
2826 TALLOC_CTX *mem_ctx,
2827 struct security_descriptor **ppdesc)
2831 START_PROFILE(fget_nt_acl);
2832 result = posix_fget_nt_acl(fsp, security_info,
2834 END_PROFILE(fget_nt_acl);
2838 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2839 const struct smb_filename *smb_fname,
2840 uint32_t security_info,
2841 TALLOC_CTX *mem_ctx,
2842 struct security_descriptor **ppdesc)
2846 START_PROFILE(get_nt_acl);
2847 result = posix_get_nt_acl(handle->conn,
2852 END_PROFILE(get_nt_acl);
2856 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2860 START_PROFILE(fset_nt_acl);
2861 result = set_nt_acl(fsp, security_info_sent, psd);
2862 END_PROFILE(fset_nt_acl);
2866 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2867 struct smb_filename *file,
2868 struct security_acl *sacl,
2869 uint32_t access_requested,
2870 uint32_t access_denied)
2872 return NT_STATUS_OK; /* Nothing to do here ... */
2875 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2876 const struct smb_filename *smb_fname,
2877 SMB_ACL_TYPE_T type,
2878 TALLOC_CTX *mem_ctx)
2880 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
2883 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2885 TALLOC_CTX *mem_ctx)
2887 return sys_acl_get_fd(handle, fsp, mem_ctx);
2890 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
2891 const struct smb_filename *smb_fname,
2892 SMB_ACL_TYPE_T acltype,
2895 return sys_acl_set_file(handle, smb_fname, acltype, theacl);
2898 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2900 return sys_acl_set_fd(handle, fsp, theacl);
2903 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
2904 const struct smb_filename *smb_fname)
2906 return sys_acl_delete_def_file(handle, smb_fname);
2909 /****************************************************************
2910 Extended attribute operations.
2911 *****************************************************************/
2913 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
2914 const struct smb_filename *smb_fname,
2919 return getxattr(smb_fname->base_name, name, value, size);
2922 struct vfswrap_getxattrat_state {
2923 struct tevent_context *ev;
2924 files_struct *dir_fsp;
2925 const struct smb_filename *smb_fname;
2926 struct tevent_req *req;
2929 * The following variables are talloced off "state" which is protected
2930 * by a destructor and thus are guaranteed to be safe to be used in the
2931 * job function in the worker thread.
2934 const char *xattr_name;
2935 uint8_t *xattr_value;
2936 struct security_unix_token *token;
2939 struct vfs_aio_state vfs_aio_state;
2940 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
2943 static int vfswrap_getxattrat_state_destructor(
2944 struct vfswrap_getxattrat_state *state)
2949 static void vfswrap_getxattrat_do_sync(struct tevent_req *req);
2950 static void vfswrap_getxattrat_do_async(void *private_data);
2951 static void vfswrap_getxattrat_done(struct tevent_req *subreq);
2953 static struct tevent_req *vfswrap_getxattrat_send(
2954 TALLOC_CTX *mem_ctx,
2955 struct tevent_context *ev,
2956 struct vfs_handle_struct *handle,
2957 files_struct *dir_fsp,
2958 const struct smb_filename *smb_fname,
2959 const char *xattr_name,
2962 struct tevent_req *req = NULL;
2963 struct tevent_req *subreq = NULL;
2964 struct vfswrap_getxattrat_state *state = NULL;
2965 size_t max_threads = 0;
2966 bool have_per_thread_cwd = false;
2967 bool have_per_thread_creds = false;
2968 bool do_async = false;
2970 req = tevent_req_create(mem_ctx, &state,
2971 struct vfswrap_getxattrat_state);
2975 *state = (struct vfswrap_getxattrat_state) {
2978 .smb_fname = smb_fname,
2982 max_threads = pthreadpool_tevent_max_threads(dir_fsp->conn->sconn->pool);
2983 if (max_threads >= 1) {
2985 * We need a non sync threadpool!
2987 have_per_thread_cwd = per_thread_cwd_supported();
2989 #ifdef HAVE_LINUX_THREAD_CREDENTIALS
2990 have_per_thread_creds = true;
2992 if (have_per_thread_cwd && have_per_thread_creds) {
2996 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat, profile_p,
2997 state->profile_bytes, 0);
2999 if (dir_fsp->fh->fd == -1) {
3000 DBG_ERR("Need a valid directory fd\n");
3001 tevent_req_error(req, EINVAL);
3002 return tevent_req_post(req, ev);
3005 if (alloc_hint > 0) {
3006 state->xattr_value = talloc_zero_array(state,
3009 if (tevent_req_nomem(state->xattr_value, req)) {
3010 return tevent_req_post(req, ev);
3015 vfswrap_getxattrat_do_sync(req);
3016 return tevent_req_post(req, ev);
3020 * Now allocate all parameters from a memory context that won't go away
3021 * no matter what. These paremeters will get used in threads and we
3022 * can't reliably cancel threads, so all buffers passed to the threads
3023 * must not be freed before all referencing threads terminate.
3026 state->name = talloc_strdup(state, smb_fname->base_name);
3027 if (tevent_req_nomem(state->name, req)) {
3028 return tevent_req_post(req, ev);
3031 state->xattr_name = talloc_strdup(state, xattr_name);
3032 if (tevent_req_nomem(state->xattr_name, req)) {
3033 return tevent_req_post(req, ev);
3037 * This is a hot codepath so at first glance one might think we should
3038 * somehow optimize away the token allocation and do a
3039 * talloc_reference() or similar black magic instead. But due to the
3040 * talloc_stackframe pool per SMB2 request this should be a simple copy
3041 * without a malloc in most cases.
3043 if (geteuid() == sec_initial_uid()) {
3044 state->token = root_unix_token(state);
3046 state->token = copy_unix_token(
3048 dir_fsp->conn->session_info->unix_token);
3050 if (tevent_req_nomem(state->token, req)) {
3051 return tevent_req_post(req, ev);
3054 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3056 subreq = pthreadpool_tevent_job_send(
3059 dir_fsp->conn->sconn->pool,
3060 vfswrap_getxattrat_do_async,
3062 if (tevent_req_nomem(subreq, req)) {
3063 return tevent_req_post(req, ev);
3065 tevent_req_set_callback(subreq, vfswrap_getxattrat_done, req);
3067 talloc_set_destructor(state, vfswrap_getxattrat_state_destructor);
3072 static void vfswrap_getxattrat_do_sync(struct tevent_req *req)
3074 struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3075 req, struct vfswrap_getxattrat_state);
3077 char *tofree = NULL;
3078 char pathbuf[PATH_MAX+1];
3082 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
3083 state->smb_fname->base_name,
3088 if (pathlen == -1) {
3089 tevent_req_error(req, ENOMEM);
3093 state->xattr_size = getxattr(path,
3096 talloc_array_length(state->xattr_value));
3098 TALLOC_FREE(tofree);
3099 if (state->xattr_size == -1) {
3100 tevent_req_error(req, err);
3104 tevent_req_done(req);
3108 static void vfswrap_getxattrat_do_async(void *private_data)
3110 struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3111 private_data, struct vfswrap_getxattrat_state);
3112 struct timespec start_time;
3113 struct timespec end_time;
3116 PROFILE_TIMESTAMP(&start_time);
3117 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
3120 * Here we simulate a getxattrat()
3121 * call using fchdir();getxattr()
3124 per_thread_cwd_activate();
3126 /* Become the correct credential on this thread. */
3127 ret = set_thread_credentials(state->token->uid,
3129 (size_t)state->token->ngroups,
3130 state->token->groups);
3132 state->xattr_size = -1;
3133 state->vfs_aio_state.error = errno;
3137 ret = fchdir(state->dir_fsp->fh->fd);
3139 state->xattr_size = -1;
3140 state->vfs_aio_state.error = errno;
3144 state->xattr_size = getxattr(state->name,
3147 talloc_array_length(state->xattr_value));
3148 if (state->xattr_size == -1) {
3149 state->vfs_aio_state.error = errno;
3153 PROFILE_TIMESTAMP(&end_time);
3154 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
3155 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3158 static void vfswrap_getxattrat_done(struct tevent_req *subreq)
3160 struct tevent_req *req = tevent_req_callback_data(
3161 subreq, struct tevent_req);
3162 struct vfswrap_getxattrat_state *state = tevent_req_data(
3163 req, struct vfswrap_getxattrat_state);
3168 * Make sure we run as the user again
3170 ok = change_to_user(state->dir_fsp->conn,
3171 state->dir_fsp->vuid);
3173 smb_panic("Can't change to user");
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);