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->raw_thread_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);
745 if (tevent_req_error(req, ret)) {
749 tevent_req_done(req);
752 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
753 struct vfs_aio_state *vfs_aio_state)
755 struct vfswrap_pread_state *state = tevent_req_data(
756 req, struct vfswrap_pread_state);
758 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
762 *vfs_aio_state = state->vfs_aio_state;
766 struct vfswrap_pwrite_state {
773 struct vfs_aio_state vfs_aio_state;
774 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
777 static void vfs_pwrite_do(void *private_data);
778 static void vfs_pwrite_done(struct tevent_req *subreq);
779 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state);
781 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
783 struct tevent_context *ev,
784 struct files_struct *fsp,
786 size_t n, off_t offset)
788 struct tevent_req *req, *subreq;
789 struct vfswrap_pwrite_state *state;
791 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
797 state->fd = fsp->fh->fd;
800 state->offset = offset;
802 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
803 state->profile_bytes, n);
804 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
806 subreq = pthreadpool_tevent_job_send(
807 state, ev, handle->conn->sconn->raw_thread_pool,
808 vfs_pwrite_do, state);
809 if (tevent_req_nomem(subreq, req)) {
810 return tevent_req_post(req, ev);
812 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
814 talloc_set_destructor(state, vfs_pwrite_state_destructor);
819 static void vfs_pwrite_do(void *private_data)
821 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
822 private_data, struct vfswrap_pwrite_state);
823 struct timespec start_time;
824 struct timespec end_time;
826 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
828 PROFILE_TIMESTAMP(&start_time);
831 state->ret = pwrite(state->fd, state->buf, state->count,
833 } while ((state->ret == -1) && (errno == EINTR));
835 if (state->ret == -1) {
836 state->vfs_aio_state.error = errno;
839 PROFILE_TIMESTAMP(&end_time);
841 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
843 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
846 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state)
851 static void vfs_pwrite_done(struct tevent_req *subreq)
853 struct tevent_req *req = tevent_req_callback_data(
854 subreq, struct tevent_req);
855 struct vfswrap_pwrite_state *state = tevent_req_data(
856 req, struct vfswrap_pwrite_state);
859 ret = pthreadpool_tevent_job_recv(subreq);
861 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
862 talloc_set_destructor(state, NULL);
863 if (tevent_req_error(req, ret)) {
867 tevent_req_done(req);
870 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
871 struct vfs_aio_state *vfs_aio_state)
873 struct vfswrap_pwrite_state *state = tevent_req_data(
874 req, struct vfswrap_pwrite_state);
876 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
880 *vfs_aio_state = state->vfs_aio_state;
884 struct vfswrap_fsync_state {
888 struct vfs_aio_state vfs_aio_state;
889 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
892 static void vfs_fsync_do(void *private_data);
893 static void vfs_fsync_done(struct tevent_req *subreq);
894 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state);
896 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
898 struct tevent_context *ev,
899 struct files_struct *fsp)
901 struct tevent_req *req, *subreq;
902 struct vfswrap_fsync_state *state;
904 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
910 state->fd = fsp->fh->fd;
912 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_fsync, profile_p,
913 state->profile_bytes, 0);
914 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
916 subreq = pthreadpool_tevent_job_send(
917 state, ev, handle->conn->sconn->raw_thread_pool,
918 vfs_fsync_do, state);
919 if (tevent_req_nomem(subreq, req)) {
920 return tevent_req_post(req, ev);
922 tevent_req_set_callback(subreq, vfs_fsync_done, req);
924 talloc_set_destructor(state, vfs_fsync_state_destructor);
929 static void vfs_fsync_do(void *private_data)
931 struct vfswrap_fsync_state *state = talloc_get_type_abort(
932 private_data, struct vfswrap_fsync_state);
933 struct timespec start_time;
934 struct timespec end_time;
936 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
938 PROFILE_TIMESTAMP(&start_time);
941 state->ret = fsync(state->fd);
942 } while ((state->ret == -1) && (errno == EINTR));
944 if (state->ret == -1) {
945 state->vfs_aio_state.error = errno;
948 PROFILE_TIMESTAMP(&end_time);
950 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
952 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
955 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state)
960 static void vfs_fsync_done(struct tevent_req *subreq)
962 struct tevent_req *req = tevent_req_callback_data(
963 subreq, struct tevent_req);
964 struct vfswrap_fsync_state *state = tevent_req_data(
965 req, struct vfswrap_fsync_state);
968 ret = pthreadpool_tevent_job_recv(subreq);
970 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
971 talloc_set_destructor(state, NULL);
972 if (tevent_req_error(req, ret)) {
976 tevent_req_done(req);
979 static int vfswrap_fsync_recv(struct tevent_req *req,
980 struct vfs_aio_state *vfs_aio_state)
982 struct vfswrap_fsync_state *state = tevent_req_data(
983 req, struct vfswrap_fsync_state);
985 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
989 *vfs_aio_state = state->vfs_aio_state;
993 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
997 START_PROFILE(syscall_lseek);
999 /* Cope with 'stat' file opens. */
1000 if (fsp->fh->fd != -1)
1001 result = lseek(fsp->fh->fd, offset, whence);
1004 * We want to maintain the fiction that we can seek
1005 * on a fifo for file system purposes. This allows
1006 * people to set up UNIX fifo's that feed data to Windows
1007 * applications. JRA.
1010 if((result == -1) && (errno == ESPIPE)) {
1015 END_PROFILE(syscall_lseek);
1019 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1020 off_t offset, size_t n)
1024 START_PROFILE_BYTES(syscall_sendfile, n);
1025 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
1026 END_PROFILE_BYTES(syscall_sendfile);
1030 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1032 files_struct *tofsp,
1038 START_PROFILE_BYTES(syscall_recvfile, n);
1039 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
1040 END_PROFILE_BYTES(syscall_recvfile);
1044 static int vfswrap_rename(vfs_handle_struct *handle,
1045 const struct smb_filename *smb_fname_src,
1046 const struct smb_filename *smb_fname_dst)
1050 START_PROFILE(syscall_rename);
1052 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
1057 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
1060 END_PROFILE(syscall_rename);
1064 static int vfswrap_stat(vfs_handle_struct *handle,
1065 struct smb_filename *smb_fname)
1069 START_PROFILE(syscall_stat);
1071 if (smb_fname->stream_name) {
1076 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1077 lp_fake_directory_create_times(SNUM(handle->conn)));
1079 END_PROFILE(syscall_stat);
1083 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1087 START_PROFILE(syscall_fstat);
1088 result = sys_fstat(fsp->fh->fd,
1089 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1090 END_PROFILE(syscall_fstat);
1094 static int vfswrap_lstat(vfs_handle_struct *handle,
1095 struct smb_filename *smb_fname)
1099 START_PROFILE(syscall_lstat);
1101 if (smb_fname->stream_name) {
1106 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1107 lp_fake_directory_create_times(SNUM(handle->conn)));
1109 END_PROFILE(syscall_lstat);
1113 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1115 enum vfs_translate_direction direction,
1116 TALLOC_CTX *mem_ctx,
1119 return NT_STATUS_NONE_MAPPED;
1123 * Implement the default fsctl operation.
1125 static bool vfswrap_logged_ioctl_message = false;
1127 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1128 struct files_struct *fsp,
1131 uint16_t req_flags, /* Needed for UNICODE ... */
1132 const uint8_t *_in_data,
1134 uint8_t **_out_data,
1135 uint32_t max_out_len,
1138 const char *in_data = (const char *)_in_data;
1139 char **out_data = (char **)_out_data;
1143 case FSCTL_SET_SPARSE:
1145 bool set_sparse = true;
1147 if (in_len >= 1 && in_data[0] == 0) {
1151 status = file_set_sparse(handle->conn, fsp, set_sparse);
1153 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1154 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1155 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1156 nt_errstr(status)));
1161 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1163 unsigned char objid[16];
1164 char *return_data = NULL;
1166 /* This should return the object-id on this file.
1167 * I think I'll make this be the inode+dev. JRA.
1170 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1171 fsp_fnum_dbg(fsp)));
1173 *out_len = MIN(max_out_len, 64);
1175 /* Hmmm, will this cause problems if less data asked for? */
1176 return_data = talloc_array(ctx, char, 64);
1177 if (return_data == NULL) {
1178 return NT_STATUS_NO_MEMORY;
1181 /* For backwards compatibility only store the dev/inode. */
1182 push_file_id_16(return_data, &fsp->file_id);
1183 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1184 push_file_id_16(return_data+32, &fsp->file_id);
1185 memset(return_data+48, 0, 16);
1186 *out_data = return_data;
1187 return NT_STATUS_OK;
1190 case FSCTL_GET_REPARSE_POINT:
1192 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1193 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1194 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1195 return NT_STATUS_NOT_A_REPARSE_POINT;
1198 case FSCTL_SET_REPARSE_POINT:
1200 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1201 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1202 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1203 return NT_STATUS_NOT_A_REPARSE_POINT;
1206 case FSCTL_GET_SHADOW_COPY_DATA:
1209 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1210 * and return their volume names. If max_data_count is 16, then it is just
1211 * asking for the number of volumes and length of the combined names.
1213 * pdata is the data allocated by our caller, but that uses
1214 * total_data_count (which is 0 in our case) rather than max_data_count.
1215 * Allocate the correct amount and return the pointer to let
1216 * it be deallocated when we return.
1218 struct shadow_copy_data *shadow_data = NULL;
1219 bool labels = False;
1220 uint32_t labels_data_count = 0;
1222 char *cur_pdata = NULL;
1224 if (max_out_len < 16) {
1225 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1227 return NT_STATUS_INVALID_PARAMETER;
1230 if (max_out_len > 16) {
1234 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1235 if (shadow_data == NULL) {
1236 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1237 return NT_STATUS_NO_MEMORY;
1241 * Call the VFS routine to actually do the work.
1243 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1246 /* broken module didn't set errno on error */
1247 status = NT_STATUS_UNSUCCESSFUL;
1249 status = map_nt_error_from_unix(errno);
1250 if (NT_STATUS_EQUAL(status,
1251 NT_STATUS_NOT_SUPPORTED)) {
1255 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1256 "connectpath %s, failed - %s.\n",
1257 fsp->conn->connectpath,
1258 nt_errstr(status)));
1259 TALLOC_FREE(shadow_data);
1263 labels_data_count = (shadow_data->num_volumes * 2 *
1264 sizeof(SHADOW_COPY_LABEL)) + 2;
1269 *out_len = 12 + labels_data_count;
1272 if (max_out_len < *out_len) {
1273 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1274 max_out_len, *out_len));
1275 TALLOC_FREE(shadow_data);
1276 return NT_STATUS_BUFFER_TOO_SMALL;
1279 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1280 if (cur_pdata == NULL) {
1281 TALLOC_FREE(shadow_data);
1282 return NT_STATUS_NO_MEMORY;
1285 *out_data = cur_pdata;
1287 /* num_volumes 4 bytes */
1288 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1291 /* num_labels 4 bytes */
1292 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1295 /* needed_data_count 4 bytes */
1296 SIVAL(cur_pdata, 8, labels_data_count);
1300 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1301 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1302 if (labels && shadow_data->labels) {
1303 for (i=0; i<shadow_data->num_volumes; i++) {
1305 status = srvstr_push(cur_pdata, req_flags,
1306 cur_pdata, shadow_data->labels[i],
1307 2 * sizeof(SHADOW_COPY_LABEL),
1308 STR_UNICODE|STR_TERMINATE, &len);
1309 if (!NT_STATUS_IS_OK(status)) {
1310 TALLOC_FREE(*out_data);
1311 TALLOC_FREE(shadow_data);
1314 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1315 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1319 TALLOC_FREE(shadow_data);
1321 return NT_STATUS_OK;
1324 case FSCTL_FIND_FILES_BY_SID:
1326 /* pretend this succeeded -
1328 * we have to send back a list with all files owned by this SID
1330 * but I have to check that --metze
1333 struct dom_sid_buf buf;
1337 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1338 fsp_fnum_dbg(fsp)));
1341 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1342 return NT_STATUS_INVALID_PARAMETER;
1345 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1347 /* unknown 4 bytes: this is not the length of the sid :-( */
1348 /*unknown = IVAL(pdata,0);*/
1350 if (!sid_parse(_in_data + 4, sid_len, &sid)) {
1351 return NT_STATUS_INVALID_PARAMETER;
1353 DEBUGADD(10, ("for SID: %s\n",
1354 dom_sid_str_buf(&sid, &buf)));
1356 if (!sid_to_uid(&sid, &uid)) {
1357 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1358 dom_sid_str_buf(&sid, &buf),
1359 (unsigned long)sid_len));
1363 /* we can take a look at the find source :-)
1365 * find ./ -uid $uid -name '*' is what we need here
1368 * and send 4bytes len and then NULL terminated unicode strings
1371 * but I don't know how to deal with the paged results
1372 * (maybe we can hang the result anywhere in the fsp struct)
1374 * but I don't know how to deal with the paged results
1375 * (maybe we can hang the result anywhere in the fsp struct)
1377 * we don't send all files at once
1378 * and at the next we should *not* start from the beginning,
1379 * so we have to cache the result
1384 /* this works for now... */
1385 return NT_STATUS_OK;
1388 case FSCTL_QUERY_ALLOCATED_RANGES:
1390 /* FIXME: This is just a dummy reply, telling that all of the
1391 * file is allocated. MKS cp needs that.
1392 * Adding the real allocated ranges via FIEMAP on Linux
1393 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1394 * this FSCTL correct for sparse files.
1396 uint64_t offset, length;
1397 char *out_data_tmp = NULL;
1400 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1402 return NT_STATUS_INVALID_PARAMETER;
1405 if (max_out_len < 16) {
1406 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1408 return NT_STATUS_INVALID_PARAMETER;
1411 offset = BVAL(in_data,0);
1412 length = BVAL(in_data,8);
1414 if (offset + length < offset) {
1415 /* No 64-bit integer wrap. */
1416 return NT_STATUS_INVALID_PARAMETER;
1419 /* Shouldn't this be SMB_VFS_STAT ... ? */
1420 status = vfs_stat_fsp(fsp);
1421 if (!NT_STATUS_IS_OK(status)) {
1426 out_data_tmp = talloc_array(ctx, char, *out_len);
1427 if (out_data_tmp == NULL) {
1428 DEBUG(10, ("unable to allocate memory for response\n"));
1429 return NT_STATUS_NO_MEMORY;
1432 if (offset > fsp->fsp_name->st.st_ex_size ||
1433 fsp->fsp_name->st.st_ex_size == 0 ||
1435 memset(out_data_tmp, 0, *out_len);
1437 uint64_t end = offset + length;
1438 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1439 SBVAL(out_data_tmp, 0, 0);
1440 SBVAL(out_data_tmp, 8, end);
1443 *out_data = out_data_tmp;
1445 return NT_STATUS_OK;
1448 case FSCTL_IS_VOLUME_DIRTY:
1450 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1451 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1453 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1454 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1456 return NT_STATUS_INVALID_PARAMETER;
1461 * Only print once ... unfortunately there could be lots of
1462 * different FSCTLs that are called.
1464 if (!vfswrap_logged_ioctl_message) {
1465 vfswrap_logged_ioctl_message = true;
1466 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1467 __func__, function));
1471 return NT_STATUS_NOT_SUPPORTED;
1474 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
1475 const struct smb_filename *fname,
1476 SMB_STRUCT_STAT *sbuf);
1478 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1479 struct smb_filename *smb_fname,
1484 offline = vfswrap_is_offline(handle, smb_fname, &smb_fname->st);
1486 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1489 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1492 struct vfswrap_get_dos_attributes_state {
1493 struct vfs_aio_state aio_state;
1494 connection_struct *conn;
1495 TALLOC_CTX *mem_ctx;
1496 struct tevent_context *ev;
1497 files_struct *dir_fsp;
1498 struct smb_filename *smb_fname;
1503 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq);
1505 static struct tevent_req *vfswrap_get_dos_attributes_send(
1506 TALLOC_CTX *mem_ctx,
1507 struct tevent_context *ev,
1508 struct vfs_handle_struct *handle,
1509 files_struct *dir_fsp,
1510 struct smb_filename *smb_fname)
1512 struct tevent_req *req = NULL;
1513 struct tevent_req *subreq = NULL;
1514 struct vfswrap_get_dos_attributes_state *state = NULL;
1516 req = tevent_req_create(mem_ctx, &state,
1517 struct vfswrap_get_dos_attributes_state);
1522 *state = (struct vfswrap_get_dos_attributes_state) {
1523 .conn = dir_fsp->conn,
1527 .smb_fname = smb_fname,
1530 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1534 SAMBA_XATTR_DOS_ATTRIB,
1536 if (tevent_req_nomem(subreq, req)) {
1537 return tevent_req_post(req, ev);
1539 tevent_req_set_callback(subreq,
1540 vfswrap_get_dos_attributes_getxattr_done,
1546 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq)
1548 struct tevent_req *req =
1549 tevent_req_callback_data(subreq,
1551 struct vfswrap_get_dos_attributes_state *state =
1552 tevent_req_data(req,
1553 struct vfswrap_get_dos_attributes_state);
1555 DATA_BLOB blob = {0};
1558 xattr_size = SMB_VFS_GETXATTRAT_RECV(subreq,
1562 TALLOC_FREE(subreq);
1563 if (xattr_size == -1) {
1564 status = map_nt_error_from_unix(state->aio_state.error);
1566 if (state->as_root) {
1567 tevent_req_nterror(req, status);
1570 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1571 tevent_req_nterror(req, status);
1575 state->as_root = true;
1578 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1582 SAMBA_XATTR_DOS_ATTRIB,
1585 if (tevent_req_nomem(subreq, req)) {
1588 tevent_req_set_callback(subreq,
1589 vfswrap_get_dos_attributes_getxattr_done,
1594 blob.length = xattr_size;
1596 status = parse_dos_attribute_blob(state->smb_fname,
1599 if (!NT_STATUS_IS_OK(status)) {
1600 tevent_req_nterror(req, status);
1604 tevent_req_done(req);
1608 static NTSTATUS vfswrap_get_dos_attributes_recv(struct tevent_req *req,
1609 struct vfs_aio_state *aio_state,
1612 struct vfswrap_get_dos_attributes_state *state =
1613 tevent_req_data(req,
1614 struct vfswrap_get_dos_attributes_state);
1617 if (tevent_req_is_nterror(req, &status)) {
1618 tevent_req_received(req);
1622 *aio_state = state->aio_state;
1623 *dosmode = state->dosmode;
1624 tevent_req_received(req);
1625 return NT_STATUS_OK;
1628 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1629 struct files_struct *fsp,
1634 offline = vfswrap_is_offline(handle, fsp->fsp_name, &fsp->fsp_name->st);
1636 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1639 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1642 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1643 const struct smb_filename *smb_fname,
1646 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1649 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1650 struct files_struct *fsp,
1653 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1656 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1658 struct vfswrap_offload_read_state {
1662 static struct tevent_req *vfswrap_offload_read_send(
1663 TALLOC_CTX *mem_ctx,
1664 struct tevent_context *ev,
1665 struct vfs_handle_struct *handle,
1666 struct files_struct *fsp,
1672 struct tevent_req *req = NULL;
1673 struct vfswrap_offload_read_state *state = NULL;
1676 req = tevent_req_create(mem_ctx, &state,
1677 struct vfswrap_offload_read_state);
1682 status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1683 &vfswrap_offload_ctx);
1684 if (tevent_req_nterror(req, status)) {
1685 return tevent_req_post(req, ev);
1688 if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1689 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1690 return tevent_req_post(req, ev);
1693 status = vfs_offload_token_create_blob(state, fsp, fsctl,
1695 if (tevent_req_nterror(req, status)) {
1696 return tevent_req_post(req, ev);
1699 status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1701 if (tevent_req_nterror(req, status)) {
1702 return tevent_req_post(req, ev);
1705 tevent_req_done(req);
1706 return tevent_req_post(req, ev);
1709 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
1710 struct vfs_handle_struct *handle,
1711 TALLOC_CTX *mem_ctx,
1714 struct vfswrap_offload_read_state *state = tevent_req_data(
1715 req, struct vfswrap_offload_read_state);
1718 if (tevent_req_is_nterror(req, &status)) {
1719 tevent_req_received(req);
1723 token->length = state->token.length;
1724 token->data = talloc_move(mem_ctx, &state->token.data);
1726 tevent_req_received(req);
1727 return NT_STATUS_OK;
1730 struct vfswrap_offload_write_state {
1732 bool read_lck_locked;
1733 bool write_lck_locked;
1735 struct tevent_context *src_ev;
1736 struct files_struct *src_fsp;
1738 struct tevent_context *dst_ev;
1739 struct files_struct *dst_fsp;
1743 size_t next_io_size;
1746 static void vfswrap_offload_write_cleanup(struct tevent_req *req,
1747 enum tevent_req_state req_state)
1749 struct vfswrap_offload_write_state *state = tevent_req_data(
1750 req, struct vfswrap_offload_write_state);
1753 if (state->dst_fsp == NULL) {
1757 ok = change_to_user_by_fsp(state->dst_fsp);
1759 state->dst_fsp = NULL;
1762 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
1764 static struct tevent_req *vfswrap_offload_write_send(
1765 struct vfs_handle_struct *handle,
1766 TALLOC_CTX *mem_ctx,
1767 struct tevent_context *ev,
1770 off_t transfer_offset,
1771 struct files_struct *dest_fsp,
1775 struct tevent_req *req;
1776 struct vfswrap_offload_write_state *state = NULL;
1777 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
1778 files_struct *src_fsp = NULL;
1782 req = tevent_req_create(mem_ctx, &state,
1783 struct vfswrap_offload_write_state);
1788 *state = (struct vfswrap_offload_write_state) {
1790 .src_off = transfer_offset,
1792 .dst_fsp = dest_fsp,
1793 .dst_off = dest_off,
1795 .remaining = to_copy,
1798 tevent_req_set_cleanup_fn(req, vfswrap_offload_write_cleanup);
1801 case FSCTL_SRV_COPYCHUNK:
1802 case FSCTL_SRV_COPYCHUNK_WRITE:
1805 case FSCTL_OFFLOAD_WRITE:
1806 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
1807 return tevent_req_post(req, ev);
1809 case FSCTL_DUP_EXTENTS_TO_FILE:
1810 DBG_DEBUG("COW clones not supported by vfs_default\n");
1811 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1812 return tevent_req_post(req, ev);
1815 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1816 return tevent_req_post(req, ev);
1820 * From here on we assume a copy-chunk fsctl
1824 tevent_req_done(req);
1825 return tevent_req_post(req, ev);
1828 status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
1830 if (tevent_req_nterror(req, status)) {
1831 return tevent_req_post(req, ev);
1834 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
1836 status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
1837 if (!NT_STATUS_IS_OK(status)) {
1838 tevent_req_nterror(req, status);
1839 return tevent_req_post(req, ev);
1842 ok = change_to_user_by_fsp(src_fsp);
1844 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1845 return tevent_req_post(req, ev);
1848 state->src_ev = src_fsp->conn->user_ev_ctx;
1849 state->src_fsp = src_fsp;
1851 state->buf = talloc_array(state, uint8_t, num);
1852 if (tevent_req_nomem(state->buf, req)) {
1853 return tevent_req_post(req, ev);
1856 status = vfs_stat_fsp(src_fsp);
1857 if (tevent_req_nterror(req, status)) {
1858 return tevent_req_post(req, ev);
1861 if (src_fsp->fsp_name->st.st_ex_size < state->src_off + num) {
1863 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1864 * If the SourceOffset or SourceOffset + Length extends beyond
1865 * the end of file, the server SHOULD<240> treat this as a
1866 * STATUS_END_OF_FILE error.
1868 * <240> Section 3.3.5.15.6: Windows servers will return
1869 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1871 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1872 return tevent_req_post(req, ev);
1875 status = vfswrap_offload_write_loop(req);
1876 if (!NT_STATUS_IS_OK(status)) {
1877 tevent_req_nterror(req, status);
1878 return tevent_req_post(req, ev);
1884 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
1886 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
1888 struct vfswrap_offload_write_state *state = tevent_req_data(
1889 req, struct vfswrap_offload_write_state);
1890 struct tevent_req *subreq = NULL;
1891 struct lock_struct read_lck;
1895 * This is called under the context of state->src_fsp.
1898 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
1900 init_strict_lock_struct(state->src_fsp,
1901 state->src_fsp->op->global->open_persistent_id,
1903 state->next_io_size,
1907 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
1911 return NT_STATUS_FILE_LOCK_CONFLICT;
1914 subreq = SMB_VFS_PREAD_SEND(state,
1918 state->next_io_size,
1920 if (subreq == NULL) {
1921 return NT_STATUS_NO_MEMORY;
1923 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
1925 return NT_STATUS_OK;
1928 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
1930 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
1932 struct tevent_req *req = tevent_req_callback_data(
1933 subreq, struct tevent_req);
1934 struct vfswrap_offload_write_state *state = tevent_req_data(
1935 req, struct vfswrap_offload_write_state);
1936 struct vfs_aio_state aio_state;
1937 struct lock_struct write_lck;
1941 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
1942 TALLOC_FREE(subreq);
1944 DBG_ERR("read failed: %s\n", strerror(errno));
1945 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1948 if (nread != state->next_io_size) {
1949 DBG_ERR("Short read, only %zd of %zu\n",
1950 nread, state->next_io_size);
1951 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1955 state->src_off += nread;
1957 ok = change_to_user_by_fsp(state->dst_fsp);
1959 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1963 init_strict_lock_struct(state->dst_fsp,
1964 state->dst_fsp->op->global->open_persistent_id,
1966 state->next_io_size,
1970 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
1974 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1978 subreq = SMB_VFS_PWRITE_SEND(state,
1982 state->next_io_size,
1984 if (subreq == NULL) {
1985 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1988 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
1991 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
1993 struct tevent_req *req = tevent_req_callback_data(
1994 subreq, struct tevent_req);
1995 struct vfswrap_offload_write_state *state = tevent_req_data(
1996 req, struct vfswrap_offload_write_state);
1997 struct vfs_aio_state aio_state;
2002 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
2003 TALLOC_FREE(subreq);
2004 if (nwritten == -1) {
2005 DBG_ERR("write failed: %s\n", strerror(errno));
2006 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2009 if (nwritten != state->next_io_size) {
2010 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
2011 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2015 state->dst_off += nwritten;
2017 if (state->remaining < nwritten) {
2018 /* Paranoia check */
2019 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2022 state->remaining -= nwritten;
2023 if (state->remaining == 0) {
2024 tevent_req_done(req);
2028 ok = change_to_user_by_fsp(state->src_fsp);
2030 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2034 status = vfswrap_offload_write_loop(req);
2035 if (!NT_STATUS_IS_OK(status)) {
2036 tevent_req_nterror(req, status);
2043 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
2044 struct tevent_req *req,
2047 struct vfswrap_offload_write_state *state = tevent_req_data(
2048 req, struct vfswrap_offload_write_state);
2051 if (tevent_req_is_nterror(req, &status)) {
2052 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
2054 tevent_req_received(req);
2058 *copied = state->to_copy;
2059 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
2060 tevent_req_received(req);
2062 return NT_STATUS_OK;
2065 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
2066 TALLOC_CTX *mem_ctx,
2067 struct files_struct *fsp,
2068 struct smb_filename *smb_fname,
2069 uint16_t *_compression_fmt)
2071 return NT_STATUS_INVALID_DEVICE_REQUEST;
2074 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
2075 TALLOC_CTX *mem_ctx,
2076 struct files_struct *fsp,
2077 uint16_t compression_fmt)
2079 return NT_STATUS_INVALID_DEVICE_REQUEST;
2082 /********************************************************************
2083 Given a stat buffer return the allocated size on disk, taking into
2084 account sparse files.
2085 ********************************************************************/
2086 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
2087 struct files_struct *fsp,
2088 const SMB_STRUCT_STAT *sbuf)
2092 START_PROFILE(syscall_get_alloc_size);
2094 if(S_ISDIR(sbuf->st_ex_mode)) {
2099 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2100 /* The type of st_blocksize is blkcnt_t which *MUST* be
2101 signed (according to POSIX) and can be less than 64-bits.
2102 Ensure when we're converting to 64 bits wide we don't
2104 #if defined(SIZEOF_BLKCNT_T_8)
2105 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2106 #elif defined(SIZEOF_BLKCNT_T_4)
2108 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2109 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2112 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2116 * Some file systems do not allocate a block for very
2117 * small files. But for non-empty file should report a
2121 uint64_t filesize = get_file_size_stat(sbuf);
2123 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2127 result = get_file_size_stat(sbuf);
2130 if (fsp && fsp->initial_allocation_size)
2131 result = MAX(result,fsp->initial_allocation_size);
2133 result = smb_roundup(handle->conn, result);
2136 END_PROFILE(syscall_get_alloc_size);
2140 static int vfswrap_unlink(vfs_handle_struct *handle,
2141 const struct smb_filename *smb_fname)
2145 START_PROFILE(syscall_unlink);
2147 if (smb_fname->stream_name) {
2151 result = unlink(smb_fname->base_name);
2154 END_PROFILE(syscall_unlink);
2158 static int vfswrap_chmod(vfs_handle_struct *handle,
2159 const struct smb_filename *smb_fname,
2164 START_PROFILE(syscall_chmod);
2165 result = chmod(smb_fname->base_name, mode);
2166 END_PROFILE(syscall_chmod);
2170 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2174 START_PROFILE(syscall_fchmod);
2175 #if defined(HAVE_FCHMOD)
2176 result = fchmod(fsp->fh->fd, mode);
2182 END_PROFILE(syscall_fchmod);
2186 static int vfswrap_chown(vfs_handle_struct *handle,
2187 const struct smb_filename *smb_fname,
2193 START_PROFILE(syscall_chown);
2194 result = chown(smb_fname->base_name, uid, gid);
2195 END_PROFILE(syscall_chown);
2199 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2204 START_PROFILE(syscall_fchown);
2205 result = fchown(fsp->fh->fd, uid, gid);
2206 END_PROFILE(syscall_fchown);
2214 static int vfswrap_lchown(vfs_handle_struct *handle,
2215 const struct smb_filename *smb_fname,
2221 START_PROFILE(syscall_lchown);
2222 result = lchown(smb_fname->base_name, uid, gid);
2223 END_PROFILE(syscall_lchown);
2227 static int vfswrap_chdir(vfs_handle_struct *handle,
2228 const struct smb_filename *smb_fname)
2232 START_PROFILE(syscall_chdir);
2233 result = chdir(smb_fname->base_name);
2234 END_PROFILE(syscall_chdir);
2238 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2242 struct smb_filename *smb_fname = NULL;
2244 START_PROFILE(syscall_getwd);
2245 result = sys_getwd();
2246 END_PROFILE(syscall_getwd);
2248 if (result == NULL) {
2251 smb_fname = synthetic_smb_fname(ctx,
2257 * sys_getwd() *always* returns malloced memory.
2258 * We must free here to avoid leaks:
2259 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2265 /*********************************************************************
2266 nsec timestamp resolution call. Convert down to whatever the underlying
2267 system will support.
2268 **********************************************************************/
2270 static int vfswrap_ntimes(vfs_handle_struct *handle,
2271 const struct smb_filename *smb_fname,
2272 struct smb_file_time *ft)
2276 START_PROFILE(syscall_ntimes);
2278 if (smb_fname->stream_name) {
2284 if (null_timespec(ft->atime)) {
2285 ft->atime= smb_fname->st.st_ex_atime;
2288 if (null_timespec(ft->mtime)) {
2289 ft->mtime = smb_fname->st.st_ex_mtime;
2292 if (!null_timespec(ft->create_time)) {
2293 set_create_timespec_ea(handle->conn,
2298 if ((timespec_compare(&ft->atime,
2299 &smb_fname->st.st_ex_atime) == 0) &&
2300 (timespec_compare(&ft->mtime,
2301 &smb_fname->st.st_ex_mtime) == 0)) {
2306 #if defined(HAVE_UTIMENSAT)
2308 struct timespec ts[2];
2311 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2313 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2315 if (!((result == -1) && (errno == ENOSYS))) {
2319 #if defined(HAVE_UTIMES)
2321 struct timeval tv[2];
2322 tv[0] = convert_timespec_to_timeval(ft->atime);
2323 tv[1] = convert_timespec_to_timeval(ft->mtime);
2324 result = utimes(smb_fname->base_name, tv);
2326 result = utimes(smb_fname->base_name, NULL);
2328 if (!((result == -1) && (errno == ENOSYS))) {
2332 #if defined(HAVE_UTIME)
2334 struct utimbuf times;
2335 times.actime = convert_timespec_to_time_t(ft->atime);
2336 times.modtime = convert_timespec_to_time_t(ft->mtime);
2337 result = utime(smb_fname->base_name, ×);
2339 result = utime(smb_fname->base_name, NULL);
2341 if (!((result == -1) && (errno == ENOSYS))) {
2349 END_PROFILE(syscall_ntimes);
2353 /*********************************************************************
2354 A version of ftruncate that will write the space on disk if strict
2356 **********************************************************************/
2358 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2360 off_t space_to_write;
2361 uint64_t space_avail;
2362 uint64_t bsize,dfree,dsize;
2365 SMB_STRUCT_STAT *pst;
2367 status = vfs_stat_fsp(fsp);
2368 if (!NT_STATUS_IS_OK(status)) {
2371 pst = &fsp->fsp_name->st;
2374 if (S_ISFIFO(pst->st_ex_mode))
2378 if (pst->st_ex_size == len)
2381 /* Shrink - just ftruncate. */
2382 if (pst->st_ex_size > len)
2383 return ftruncate(fsp->fh->fd, len);
2385 space_to_write = len - pst->st_ex_size;
2387 /* for allocation try fallocate first. This can fail on some
2388 platforms e.g. when the filesystem doesn't support it and no
2389 emulation is being done by the libc (like on AIX with JFS1). In that
2390 case we do our own emulation. fallocate implementations can
2391 return ENOTSUP or EINVAL in cases like that. */
2392 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2393 if (ret == -1 && errno == ENOSPC) {
2399 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2400 "error %d. Falling back to slow manual allocation\n", errno));
2402 /* available disk space is enough or not? */
2404 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2405 /* space_avail is 1k blocks */
2406 if (space_avail == (uint64_t)-1 ||
2407 ((uint64_t)space_to_write/1024 > space_avail) ) {
2412 /* Write out the real space on disk. */
2413 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2421 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2424 SMB_STRUCT_STAT *pst;
2428 START_PROFILE(syscall_ftruncate);
2430 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2431 result = strict_allocate_ftruncate(handle, fsp, len);
2432 END_PROFILE(syscall_ftruncate);
2436 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2437 ftruncate if the system supports it. Then I discovered that
2438 you can have some filesystems that support ftruncate
2439 expansion and some that don't! On Linux fat can't do
2440 ftruncate extend but ext2 can. */
2442 result = ftruncate(fsp->fh->fd, len);
2444 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2445 extend a file with ftruncate. Provide alternate implementation
2448 /* Do an fstat to see if the file is longer than the requested
2449 size in which case the ftruncate above should have
2450 succeeded or shorter, in which case seek to len - 1 and
2451 write 1 byte of zero */
2452 status = vfs_stat_fsp(fsp);
2453 if (!NT_STATUS_IS_OK(status)) {
2457 /* We need to update the files_struct after successful ftruncate */
2462 pst = &fsp->fsp_name->st;
2465 if (S_ISFIFO(pst->st_ex_mode)) {
2471 if (pst->st_ex_size == len) {
2476 if (pst->st_ex_size > len) {
2477 /* the ftruncate should have worked */
2481 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2489 END_PROFILE(syscall_ftruncate);
2493 static int vfswrap_fallocate(vfs_handle_struct *handle,
2501 START_PROFILE(syscall_fallocate);
2503 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2505 * posix_fallocate returns 0 on success, errno on error
2506 * and doesn't set errno. Make it behave like fallocate()
2507 * which returns -1, and sets errno on failure.
2514 /* sys_fallocate handles filtering of unsupported mode flags */
2515 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2517 END_PROFILE(syscall_fallocate);
2521 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2525 START_PROFILE(syscall_fcntl_lock);
2527 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2529 "force process locks",
2531 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2534 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2535 END_PROFILE(syscall_fcntl_lock);
2539 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2540 uint32_t share_mode, uint32_t access_mask)
2542 START_PROFILE(syscall_kernel_flock);
2543 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2544 END_PROFILE(syscall_kernel_flock);
2548 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2553 START_PROFILE(syscall_fcntl_getlock);
2555 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2557 "force process locks",
2559 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2562 result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2563 END_PROFILE(syscall_fcntl_getlock);
2567 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2572 START_PROFILE(syscall_linux_setlease);
2574 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2575 result = linux_setlease(fsp->fh->fd, leasetype);
2579 END_PROFILE(syscall_linux_setlease);
2583 static int vfswrap_symlink(vfs_handle_struct *handle,
2584 const char *link_target,
2585 const struct smb_filename *new_smb_fname)
2589 START_PROFILE(syscall_symlink);
2590 result = symlink(link_target, new_smb_fname->base_name);
2591 END_PROFILE(syscall_symlink);
2595 static int vfswrap_readlink(vfs_handle_struct *handle,
2596 const struct smb_filename *smb_fname,
2602 START_PROFILE(syscall_readlink);
2603 result = readlink(smb_fname->base_name, buf, bufsiz);
2604 END_PROFILE(syscall_readlink);
2608 static int vfswrap_link(vfs_handle_struct *handle,
2609 const struct smb_filename *old_smb_fname,
2610 const struct smb_filename *new_smb_fname)
2614 START_PROFILE(syscall_link);
2615 result = link(old_smb_fname->base_name, new_smb_fname->base_name);
2616 END_PROFILE(syscall_link);
2620 static int vfswrap_mknod(vfs_handle_struct *handle,
2621 const struct smb_filename *smb_fname,
2627 START_PROFILE(syscall_mknod);
2628 result = sys_mknod(smb_fname->base_name, mode, dev);
2629 END_PROFILE(syscall_mknod);
2633 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2635 const struct smb_filename *smb_fname)
2638 struct smb_filename *result_fname = NULL;
2640 START_PROFILE(syscall_realpath);
2641 result = sys_realpath(smb_fname->base_name);
2642 END_PROFILE(syscall_realpath);
2644 result_fname = synthetic_smb_fname(ctx, result, NULL, NULL, 0);
2647 return result_fname;
2650 static int vfswrap_chflags(vfs_handle_struct *handle,
2651 const struct smb_filename *smb_fname,
2655 return chflags(smb_fname->base_name, flags);
2662 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2663 const SMB_STRUCT_STAT *sbuf)
2667 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2671 key.devid = sbuf->st_ex_dev;
2672 key.inode = sbuf->st_ex_ino;
2673 /* key.extid is unused by default. */
2678 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2679 struct files_struct *fsp,
2680 const struct smb_filename *smb_fname,
2681 TALLOC_CTX *mem_ctx,
2682 unsigned int *pnum_streams,
2683 struct stream_struct **pstreams)
2685 SMB_STRUCT_STAT sbuf;
2686 struct stream_struct *tmp_streams = NULL;
2689 if ((fsp != NULL) && (fsp->is_directory)) {
2691 * No default streams on directories
2696 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2697 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2700 struct smb_filename smb_fname_cp;
2702 ZERO_STRUCT(smb_fname_cp);
2703 smb_fname_cp.base_name = discard_const_p(char,
2704 smb_fname->base_name);
2705 smb_fname_cp.flags = smb_fname->flags;
2707 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
2708 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2710 ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2712 sbuf = smb_fname_cp.st;
2716 return map_nt_error_from_unix(errno);
2719 if (S_ISDIR(sbuf.st_ex_mode)) {
2723 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2724 (*pnum_streams) + 1);
2725 if (tmp_streams == NULL) {
2726 return NT_STATUS_NO_MEMORY;
2728 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2729 if (tmp_streams[*pnum_streams].name == NULL) {
2730 return NT_STATUS_NO_MEMORY;
2732 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2733 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2736 *pstreams = tmp_streams;
2738 return NT_STATUS_OK;
2741 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2744 TALLOC_CTX *mem_ctx,
2748 * Don't fall back to get_real_filename so callers can differentiate
2749 * between a full directory scan and an actual case-insensitive stat.
2755 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2756 const struct smb_filename *smb_fname)
2758 return handle->conn->connectpath;
2761 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2762 struct byte_range_lock *br_lck,
2763 struct lock_struct *plock,
2766 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2768 /* Note: blr is not used in the default implementation. */
2769 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2772 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2773 struct messaging_context *msg_ctx,
2774 struct byte_range_lock *br_lck,
2775 const struct lock_struct *plock)
2777 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2779 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2782 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2783 struct byte_range_lock *br_lck,
2784 struct lock_struct *plock)
2786 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2788 /* Note: blr is not used in the default implementation. */
2789 return brl_lock_cancel_default(br_lck, plock);
2792 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
2794 struct lock_struct *plock)
2796 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2797 plock->lock_type == WRITE_LOCK);
2799 return strict_lock_check_default(fsp, plock);
2802 /* NT ACL operations. */
2804 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2806 uint32_t security_info,
2807 TALLOC_CTX *mem_ctx,
2808 struct security_descriptor **ppdesc)
2812 START_PROFILE(fget_nt_acl);
2813 result = posix_fget_nt_acl(fsp, security_info,
2815 END_PROFILE(fget_nt_acl);
2819 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2820 const struct smb_filename *smb_fname,
2821 uint32_t security_info,
2822 TALLOC_CTX *mem_ctx,
2823 struct security_descriptor **ppdesc)
2827 START_PROFILE(get_nt_acl);
2828 result = posix_get_nt_acl(handle->conn,
2833 END_PROFILE(get_nt_acl);
2837 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2841 START_PROFILE(fset_nt_acl);
2842 result = set_nt_acl(fsp, security_info_sent, psd);
2843 END_PROFILE(fset_nt_acl);
2847 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2848 struct smb_filename *file,
2849 struct security_acl *sacl,
2850 uint32_t access_requested,
2851 uint32_t access_denied)
2853 return NT_STATUS_OK; /* Nothing to do here ... */
2856 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2857 const struct smb_filename *smb_fname,
2858 SMB_ACL_TYPE_T type,
2859 TALLOC_CTX *mem_ctx)
2861 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
2864 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2866 TALLOC_CTX *mem_ctx)
2868 return sys_acl_get_fd(handle, fsp, mem_ctx);
2871 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
2872 const struct smb_filename *smb_fname,
2873 SMB_ACL_TYPE_T acltype,
2876 return sys_acl_set_file(handle, smb_fname, acltype, theacl);
2879 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2881 return sys_acl_set_fd(handle, fsp, theacl);
2884 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
2885 const struct smb_filename *smb_fname)
2887 return sys_acl_delete_def_file(handle, smb_fname);
2890 /****************************************************************
2891 Extended attribute operations.
2892 *****************************************************************/
2894 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
2895 const struct smb_filename *smb_fname,
2900 return getxattr(smb_fname->base_name, name, value, size);
2903 struct vfswrap_getxattrat_state {
2904 struct tevent_context *ev;
2905 files_struct *dir_fsp;
2906 const struct smb_filename *smb_fname;
2907 struct tevent_req *req;
2910 * The following variables are talloced off "state" which is protected
2911 * by a destructor and thus are guaranteed to be safe to be used in the
2912 * job function in the worker thread.
2915 const char *xattr_name;
2916 uint8_t *xattr_value;
2917 struct security_unix_token *token;
2920 struct vfs_aio_state vfs_aio_state;
2921 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
2924 static int vfswrap_getxattrat_state_destructor(
2925 struct vfswrap_getxattrat_state *state)
2930 static void vfswrap_getxattrat_do_sync(struct tevent_req *req);
2931 static void vfswrap_getxattrat_do_async(void *private_data);
2932 static void vfswrap_getxattrat_done(struct tevent_req *subreq);
2934 static struct tevent_req *vfswrap_getxattrat_send(
2935 TALLOC_CTX *mem_ctx,
2936 struct tevent_context *ev,
2937 struct vfs_handle_struct *handle,
2938 files_struct *dir_fsp,
2939 const struct smb_filename *smb_fname,
2940 const char *xattr_name,
2943 struct tevent_req *req = NULL;
2944 struct tevent_req *subreq = NULL;
2945 struct vfswrap_getxattrat_state *state = NULL;
2946 size_t max_threads = 0;
2947 bool have_per_thread_cwd = false;
2948 bool have_per_thread_creds = false;
2949 bool do_async = false;
2951 req = tevent_req_create(mem_ctx, &state,
2952 struct vfswrap_getxattrat_state);
2956 *state = (struct vfswrap_getxattrat_state) {
2959 .smb_fname = smb_fname,
2963 max_threads = pthreadpool_tevent_max_threads(dir_fsp->conn->sconn->pool);
2964 if (max_threads >= 1) {
2966 * We need a non sync threadpool!
2968 have_per_thread_cwd = per_thread_cwd_supported();
2970 #ifdef HAVE_LINUX_THREAD_CREDENTIALS
2971 have_per_thread_creds = true;
2973 if (have_per_thread_cwd && have_per_thread_creds) {
2977 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat, profile_p,
2978 state->profile_bytes, 0);
2980 if (dir_fsp->fh->fd == -1) {
2981 DBG_ERR("Need a valid directory fd\n");
2982 tevent_req_error(req, EINVAL);
2983 return tevent_req_post(req, ev);
2986 if (alloc_hint > 0) {
2987 state->xattr_value = talloc_zero_array(state,
2990 if (tevent_req_nomem(state->xattr_value, req)) {
2991 return tevent_req_post(req, ev);
2996 vfswrap_getxattrat_do_sync(req);
2997 return tevent_req_post(req, ev);
3001 * Now allocate all parameters from a memory context that won't go away
3002 * no matter what. These paremeters will get used in threads and we
3003 * can't reliably cancel threads, so all buffers passed to the threads
3004 * must not be freed before all referencing threads terminate.
3007 state->name = talloc_strdup(state, smb_fname->base_name);
3008 if (tevent_req_nomem(state->name, req)) {
3009 return tevent_req_post(req, ev);
3012 state->xattr_name = talloc_strdup(state, xattr_name);
3013 if (tevent_req_nomem(state->xattr_name, req)) {
3014 return tevent_req_post(req, ev);
3018 * This is a hot codepath so at first glance one might think we should
3019 * somehow optimize away the token allocation and do a
3020 * talloc_reference() or similar black magic instead. But due to the
3021 * talloc_stackframe pool per SMB2 request this should be a simple copy
3022 * without a malloc in most cases.
3024 if (geteuid() == sec_initial_uid()) {
3025 state->token = root_unix_token(state);
3027 state->token = copy_unix_token(
3029 dir_fsp->conn->session_info->unix_token);
3031 if (tevent_req_nomem(state->token, req)) {
3032 return tevent_req_post(req, ev);
3035 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3037 subreq = pthreadpool_tevent_job_send(
3040 dir_fsp->conn->sconn->raw_thread_pool,
3041 vfswrap_getxattrat_do_async,
3043 if (tevent_req_nomem(subreq, req)) {
3044 return tevent_req_post(req, ev);
3046 tevent_req_set_callback(subreq, vfswrap_getxattrat_done, req);
3048 talloc_set_destructor(state, vfswrap_getxattrat_state_destructor);
3053 static void vfswrap_getxattrat_do_sync(struct tevent_req *req)
3055 struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3056 req, struct vfswrap_getxattrat_state);
3058 char *tofree = NULL;
3059 char pathbuf[PATH_MAX+1];
3063 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
3064 state->smb_fname->base_name,
3069 if (pathlen == -1) {
3070 tevent_req_error(req, ENOMEM);
3074 state->xattr_size = getxattr(path,
3077 talloc_array_length(state->xattr_value));
3079 TALLOC_FREE(tofree);
3080 if (state->xattr_size == -1) {
3081 tevent_req_error(req, err);
3085 tevent_req_done(req);
3089 static void vfswrap_getxattrat_do_async(void *private_data)
3091 struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3092 private_data, struct vfswrap_getxattrat_state);
3093 struct timespec start_time;
3094 struct timespec end_time;
3097 PROFILE_TIMESTAMP(&start_time);
3098 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
3101 * Here we simulate a getxattrat()
3102 * call using fchdir();getxattr()
3105 per_thread_cwd_activate();
3107 /* Become the correct credential on this thread. */
3108 ret = set_thread_credentials(state->token->uid,
3110 (size_t)state->token->ngroups,
3111 state->token->groups);
3113 state->xattr_size = -1;
3114 state->vfs_aio_state.error = errno;
3118 ret = fchdir(state->dir_fsp->fh->fd);
3120 state->xattr_size = -1;
3121 state->vfs_aio_state.error = errno;
3125 state->xattr_size = getxattr(state->name,
3128 talloc_array_length(state->xattr_value));
3129 if (state->xattr_size == -1) {
3130 state->vfs_aio_state.error = errno;
3134 PROFILE_TIMESTAMP(&end_time);
3135 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
3136 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3139 static void vfswrap_getxattrat_done(struct tevent_req *subreq)
3141 struct tevent_req *req = tevent_req_callback_data(
3142 subreq, struct tevent_req);
3143 struct vfswrap_getxattrat_state *state = tevent_req_data(
3144 req, struct vfswrap_getxattrat_state);
3149 * Make sure we run as the user again
3151 ok = change_to_user(state->dir_fsp->conn,
3152 state->dir_fsp->vuid);
3154 smb_panic("Can't change to user");
3158 ret = pthreadpool_tevent_job_recv(subreq);
3159 TALLOC_FREE(subreq);
3160 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
3161 talloc_set_destructor(state, NULL);
3163 if (ret != EAGAIN) {
3164 tevent_req_error(req, ret);
3168 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
3169 * means the lower level pthreadpool failed to create a new
3170 * thread. Fallback to sync processing in that case to allow
3171 * some progress for the client.
3173 vfswrap_getxattrat_do_sync(req);
3177 if (state->xattr_size == -1) {
3178 tevent_req_error(req, state->vfs_aio_state.error);
3182 if (state->xattr_value == NULL) {
3184 * The caller only wanted the size.
3186 tevent_req_done(req);
3191 * shrink the buffer to the returned size.
3192 * (can't fail). It means NULL if size is 0.
3194 state->xattr_value = talloc_realloc(state,
3199 tevent_req_done(req);
3202 static ssize_t vfswrap_getxattrat_recv(struct tevent_req *req,
3203 struct vfs_aio_state *aio_state,
3204 TALLOC_CTX *mem_ctx,
3205 uint8_t **xattr_value)
3207 struct vfswrap_getxattrat_state *state = tevent_req_data(
3208 req, struct vfswrap_getxattrat_state);
3211 if (tevent_req_is_unix_error(req, &aio_state->error)) {
3212 tevent_req_received(req);
3216 *aio_state = state->vfs_aio_state;
3217 xattr_size = state->xattr_size;
3218 if (xattr_value != NULL) {
3219 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
3222 tevent_req_received(req);
3226 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
3228 return fgetxattr(fsp->fh->fd, name, value, size);
3231 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
3232 const struct smb_filename *smb_fname,
3236 return listxattr(smb_fname->base_name, list, size);
3239 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
3241 return flistxattr(fsp->fh->fd, list, size);
3244 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
3245 const struct smb_filename *smb_fname,
3248 return removexattr(smb_fname->base_name, name);
3251 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
3253 return fremovexattr(fsp->fh->fd, name);
3256 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
3257 const struct smb_filename *smb_fname,
3263 return setxattr(smb_fname->base_name, name, value, size, flags);
3266 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
3268 return fsetxattr(fsp->fh->fd, name, value, size, flags);
3271 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
3276 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
3277 const struct smb_filename *fname,
3278 SMB_STRUCT_STAT *sbuf)
3282 bool offline = false;
3284 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
3288 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
3289 #if defined(ENOTSUP)
3295 status = get_full_smb_filename(talloc_tos(), fname, &path);
3296 if (!NT_STATUS_IS_OK(status)) {
3297 errno = map_errno_from_nt_status(status);
3301 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
3308 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
3309 struct files_struct *fsp,
3310 TALLOC_CTX *mem_ctx,
3313 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
3316 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
3317 struct files_struct *fsp,
3318 const DATA_BLOB old_cookie,
3319 TALLOC_CTX *mem_ctx,
3320 DATA_BLOB *new_cookie)
3322 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
3326 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
3327 struct smb_request *smb1req,
3328 struct smbXsrv_open *op,
3329 const DATA_BLOB old_cookie,
3330 TALLOC_CTX *mem_ctx,
3331 struct files_struct **fsp,
3332 DATA_BLOB *new_cookie)
3334 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
3335 old_cookie, mem_ctx,
3339 static struct vfs_fn_pointers vfs_default_fns = {
3340 /* Disk operations */
3342 .connect_fn = vfswrap_connect,
3343 .disconnect_fn = vfswrap_disconnect,
3344 .disk_free_fn = vfswrap_disk_free,
3345 .get_quota_fn = vfswrap_get_quota,
3346 .set_quota_fn = vfswrap_set_quota,
3347 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3348 .statvfs_fn = vfswrap_statvfs,
3349 .fs_capabilities_fn = vfswrap_fs_capabilities,
3350 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3351 .snap_check_path_fn = vfswrap_snap_check_path,
3352 .snap_create_fn = vfswrap_snap_create,
3353 .snap_delete_fn = vfswrap_snap_delete,
3355 /* Directory operations */
3357 .opendir_fn = vfswrap_opendir,
3358 .fdopendir_fn = vfswrap_fdopendir,
3359 .readdir_fn = vfswrap_readdir,
3360 .readdir_attr_fn = vfswrap_readdir_attr,
3361 .seekdir_fn = vfswrap_seekdir,
3362 .telldir_fn = vfswrap_telldir,
3363 .rewind_dir_fn = vfswrap_rewinddir,
3364 .mkdir_fn = vfswrap_mkdir,
3365 .rmdir_fn = vfswrap_rmdir,
3366 .closedir_fn = vfswrap_closedir,
3368 /* File operations */
3370 .open_fn = vfswrap_open,
3371 .create_file_fn = vfswrap_create_file,
3372 .close_fn = vfswrap_close,
3373 .pread_fn = vfswrap_pread,
3374 .pread_send_fn = vfswrap_pread_send,
3375 .pread_recv_fn = vfswrap_pread_recv,
3376 .pwrite_fn = vfswrap_pwrite,
3377 .pwrite_send_fn = vfswrap_pwrite_send,
3378 .pwrite_recv_fn = vfswrap_pwrite_recv,
3379 .lseek_fn = vfswrap_lseek,
3380 .sendfile_fn = vfswrap_sendfile,
3381 .recvfile_fn = vfswrap_recvfile,
3382 .rename_fn = vfswrap_rename,
3383 .fsync_send_fn = vfswrap_fsync_send,
3384 .fsync_recv_fn = vfswrap_fsync_recv,
3385 .stat_fn = vfswrap_stat,
3386 .fstat_fn = vfswrap_fstat,
3387 .lstat_fn = vfswrap_lstat,
3388 .get_alloc_size_fn = vfswrap_get_alloc_size,
3389 .unlink_fn = vfswrap_unlink,
3390 .chmod_fn = vfswrap_chmod,
3391 .fchmod_fn = vfswrap_fchmod,
3392 .chown_fn = vfswrap_chown,
3393 .fchown_fn = vfswrap_fchown,
3394 .lchown_fn = vfswrap_lchown,
3395 .chdir_fn = vfswrap_chdir,
3396 .getwd_fn = vfswrap_getwd,
3397 .ntimes_fn = vfswrap_ntimes,
3398 .ftruncate_fn = vfswrap_ftruncate,
3399 .fallocate_fn = vfswrap_fallocate,
3400 .lock_fn = vfswrap_lock,
3401 .kernel_flock_fn = vfswrap_kernel_flock,
3402 .linux_setlease_fn = vfswrap_linux_setlease,
3403 .getlock_fn = vfswrap_getlock,
3404 .symlink_fn = vfswrap_symlink,
3405 .readlink_fn = vfswrap_readlink,
3406 .link_fn = vfswrap_link,
3407 .mknod_fn = vfswrap_mknod,
3408 .realpath_fn = vfswrap_realpath,
3409 .chflags_fn = vfswrap_chflags,
3410 .file_id_create_fn = vfswrap_file_id_create,
3411 .streaminfo_fn = vfswrap_streaminfo,
3412 .get_real_filename_fn = vfswrap_get_real_filename,
3413 .connectpath_fn = vfswrap_connectpath,
3414 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
3415 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3416 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
3417 .strict_lock_check_fn = vfswrap_strict_lock_check,
3418 .translate_name_fn = vfswrap_translate_name,
3419 .fsctl_fn = vfswrap_fsctl,
3420 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
3421 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
3422 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
3423 .get_dos_attributes_send_fn = vfswrap_get_dos_attributes_send,
3424 .get_dos_attributes_recv_fn = vfswrap_get_dos_attributes_recv,
3425 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
3426 .offload_read_send_fn = vfswrap_offload_read_send,
3427 .offload_read_recv_fn = vfswrap_offload_read_recv,
3428 .offload_write_send_fn = vfswrap_offload_write_send,
3429 .offload_write_recv_fn = vfswrap_offload_write_recv,
3430 .get_compression_fn = vfswrap_get_compression,
3431 .set_compression_fn = vfswrap_set_compression,
3433 /* NT ACL operations. */
3435 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
3436 .get_nt_acl_fn = vfswrap_get_nt_acl,
3437 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
3438 .audit_file_fn = vfswrap_audit_file,
3440 /* POSIX ACL operations. */
3442 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
3443 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3444 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
3445 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3446 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
3447 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3448 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
3450 /* EA operations. */
3451 .getxattr_fn = vfswrap_getxattr,
3452 .getxattrat_send_fn = vfswrap_getxattrat_send,
3453 .getxattrat_recv_fn = vfswrap_getxattrat_recv,
3454 .fgetxattr_fn = vfswrap_fgetxattr,
3455 .listxattr_fn = vfswrap_listxattr,
3456 .flistxattr_fn = vfswrap_flistxattr,
3457 .removexattr_fn = vfswrap_removexattr,
3458 .fremovexattr_fn = vfswrap_fremovexattr,
3459 .setxattr_fn = vfswrap_setxattr,
3460 .fsetxattr_fn = vfswrap_fsetxattr,
3462 /* aio operations */
3463 .aio_force_fn = vfswrap_aio_force,
3465 /* durable handle operations */
3466 .durable_cookie_fn = vfswrap_durable_cookie,
3467 .durable_disconnect_fn = vfswrap_durable_disconnect,
3468 .durable_reconnect_fn = vfswrap_durable_reconnect,
3472 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3475 * Here we need to implement every call!
3477 * As this is the end of the vfs module chain.
3479 smb_vfs_assert_all_fns(&vfs_default_fns, DEFAULT_VFS_MODULE_NAME);
3480 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3481 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);