2 Unix SMB/CIFS implementation.
3 Wrap disk only vfs functions to sidestep dodgy compilers.
4 Copyright (C) Tim Potter 1998
5 Copyright (C) Jeremy Allison 2007
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "system/time.h"
23 #include "system/filesys.h"
24 #include "smbd/smbd.h"
25 #include "smbd/globals.h"
27 #include "smbprofile.h"
28 #include "../libcli/security/security.h"
29 #include "passdb/lookup_sid.h"
30 #include "source3/include/msdfs.h"
31 #include "librpc/gen_ndr/ndr_dfsblobs.h"
32 #include "lib/util/tevent_unix.h"
33 #include "lib/util/tevent_ntstatus.h"
34 #include "lib/util/sys_rw.h"
35 #include "lib/pthreadpool/pthreadpool_tevent.h"
36 #include "librpc/gen_ndr/ndr_ioctl.h"
37 #include "offload_token.h"
40 #define DBGC_CLASS DBGC_VFS
42 /* Check for NULL pointer parameters in vfswrap_* functions */
44 /* We don't want to have NULL function pointers lying around. Someone
45 is sure to try and execute them. These stubs are used to prevent
48 static int vfswrap_connect(vfs_handle_struct *handle, const char *service, const char *user)
50 return 0; /* Return >= 0 for success */
53 static void vfswrap_disconnect(vfs_handle_struct *handle)
59 static uint64_t vfswrap_disk_free(vfs_handle_struct *handle,
60 const struct smb_filename *smb_fname,
65 if (sys_fsusage(smb_fname->base_name, dfree, dsize) != 0) {
73 static int vfswrap_get_quota(struct vfs_handle_struct *handle,
74 const struct smb_filename *smb_fname,
75 enum SMB_QUOTA_TYPE qtype,
79 #ifdef HAVE_SYS_QUOTAS
82 START_PROFILE(syscall_get_quota);
83 result = sys_get_quota(smb_fname->base_name, qtype, id, qt);
84 END_PROFILE(syscall_get_quota);
92 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
94 #ifdef HAVE_SYS_QUOTAS
97 START_PROFILE(syscall_set_quota);
98 result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
99 END_PROFILE(syscall_set_quota);
107 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
108 struct files_struct *fsp,
109 struct shadow_copy_data *shadow_copy_data,
113 return -1; /* Not implemented. */
116 static int vfswrap_statvfs(struct vfs_handle_struct *handle,
117 const struct smb_filename *smb_fname,
118 vfs_statvfs_struct *statbuf)
120 return sys_statvfs(smb_fname->base_name, statbuf);
123 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
124 enum timestamp_set_resolution *p_ts_res)
126 connection_struct *conn = handle->conn;
127 uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
128 struct smb_filename *smb_fname_cpath = NULL;
129 struct vfs_statvfs_struct statbuf;
132 smb_fname_cpath = synthetic_smb_fname(talloc_tos(), conn->connectpath,
134 if (smb_fname_cpath == NULL) {
138 ZERO_STRUCT(statbuf);
139 ret = SMB_VFS_STATVFS(conn, smb_fname_cpath, &statbuf);
141 caps = statbuf.FsCapabilities;
144 *p_ts_res = TIMESTAMP_SET_SECONDS;
146 /* Work out what timestamp resolution we can
147 * use when setting a timestamp. */
149 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
151 TALLOC_FREE(smb_fname_cpath);
155 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
156 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
157 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
158 /* If any of the normal UNIX directory timestamps
159 * have a non-zero tv_nsec component assume
160 * we might be able to set sub-second timestamps.
161 * See what filetime set primitives we have.
163 #if defined(HAVE_UTIMENSAT)
164 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
165 #elif defined(HAVE_UTIMES)
166 /* utimes allows msec timestamps to be set. */
167 *p_ts_res = TIMESTAMP_SET_MSEC;
168 #elif defined(HAVE_UTIME)
169 /* utime only allows sec timestamps to be set. */
170 *p_ts_res = TIMESTAMP_SET_SECONDS;
173 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
175 "available on share %s, directory %s\n",
176 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
177 lp_servicename(talloc_tos(), conn->params->service),
178 conn->connectpath ));
180 TALLOC_FREE(smb_fname_cpath);
184 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
185 struct dfs_GetDFSReferral *r)
187 struct junction_map *junction = NULL;
189 bool self_referral = false;
190 char *pathnamep = NULL;
191 char *local_dfs_path = NULL;
194 uint16_t max_referral_level = r->in.req.max_referral_level;
197 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
200 /* get the junction entry */
201 if (r->in.req.servername == NULL) {
202 return NT_STATUS_NOT_FOUND;
206 * Trim pathname sent by client so it begins with only one backslash.
207 * Two backslashes confuse some dfs clients
210 local_dfs_path = talloc_strdup(r, r->in.req.servername);
211 if (local_dfs_path == NULL) {
212 return NT_STATUS_NO_MEMORY;
214 pathnamep = local_dfs_path;
215 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
216 IS_DIRECTORY_SEP(pathnamep[1])) {
220 junction = talloc_zero(r, struct junction_map);
221 if (junction == NULL) {
222 return NT_STATUS_NO_MEMORY;
225 /* The following call can change cwd. */
226 status = get_referred_path(r, pathnamep,
227 handle->conn->sconn->remote_address,
228 handle->conn->sconn->local_address,
229 !handle->conn->sconn->using_smb2,
230 junction, &consumedcnt, &self_referral);
231 if (!NT_STATUS_IS_OK(status)) {
232 struct smb_filename connectpath_fname = {
233 .base_name = handle->conn->connectpath
235 vfs_ChDir(handle->conn, &connectpath_fname);
239 struct smb_filename connectpath_fname = {
240 .base_name = handle->conn->connectpath
242 vfs_ChDir(handle->conn, &connectpath_fname);
245 if (!self_referral) {
246 pathnamep[consumedcnt] = '\0';
249 dbgtext("Path %s to alternate path(s):",
251 for (i=0; i < junction->referral_count; i++) {
253 junction->referral_list[i].alternate_path);
259 if (r->in.req.max_referral_level <= 2) {
260 max_referral_level = 2;
262 if (r->in.req.max_referral_level >= 3) {
263 max_referral_level = 3;
266 r->out.resp = talloc_zero(r, struct dfs_referral_resp);
267 if (r->out.resp == NULL) {
268 return NT_STATUS_NO_MEMORY;
271 r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
272 r->out.resp->nb_referrals = junction->referral_count;
274 r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
276 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
279 r->out.resp->referral_entries = talloc_zero_array(r,
280 struct dfs_referral_type,
281 r->out.resp->nb_referrals);
282 if (r->out.resp->referral_entries == NULL) {
283 return NT_STATUS_NO_MEMORY;
286 switch (max_referral_level) {
288 for(i=0; i < junction->referral_count; i++) {
289 struct referral *ref = &junction->referral_list[i];
290 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
291 struct dfs_referral_type *t =
292 &r->out.resp->referral_entries[i];
293 struct dfs_referral_v2 *v2 = &t->referral.v2;
296 v2->size = VERSION2_REFERRAL_SIZE;
298 v2->server_type = DFS_SERVER_ROOT;
300 v2->server_type = DFS_SERVER_NON_ROOT;
303 v2->proximity = ref->proximity;
305 v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
306 if (v2->DFS_path == NULL) {
307 return NT_STATUS_NO_MEMORY;
309 v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
310 if (v2->DFS_alt_path == NULL) {
311 return NT_STATUS_NO_MEMORY;
313 v2->netw_address = talloc_strdup(mem_ctx,
314 ref->alternate_path);
315 if (v2->netw_address == NULL) {
316 return NT_STATUS_NO_MEMORY;
322 for(i=0; i < junction->referral_count; i++) {
323 struct referral *ref = &junction->referral_list[i];
324 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
325 struct dfs_referral_type *t =
326 &r->out.resp->referral_entries[i];
327 struct dfs_referral_v3 *v3 = &t->referral.v3;
328 struct dfs_normal_referral *r1 = &v3->referrals.r1;
331 v3->size = VERSION3_REFERRAL_SIZE;
333 v3->server_type = DFS_SERVER_ROOT;
335 v3->server_type = DFS_SERVER_NON_ROOT;
339 r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
340 if (r1->DFS_path == NULL) {
341 return NT_STATUS_NO_MEMORY;
343 r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
344 if (r1->DFS_alt_path == NULL) {
345 return NT_STATUS_NO_MEMORY;
347 r1->netw_address = talloc_strdup(mem_ctx,
348 ref->alternate_path);
349 if (r1->netw_address == NULL) {
350 return NT_STATUS_NO_MEMORY;
355 DEBUG(0,("Invalid dfs referral version: %d\n",
356 max_referral_level));
357 return NT_STATUS_INVALID_LEVEL;
361 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
367 static NTSTATUS vfswrap_snap_check_path(struct vfs_handle_struct *handle,
369 const char *service_path,
372 return NT_STATUS_NOT_SUPPORTED;
375 static NTSTATUS vfswrap_snap_create(struct vfs_handle_struct *handle,
377 const char *base_volume,
383 return NT_STATUS_NOT_SUPPORTED;
386 static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle,
391 return NT_STATUS_NOT_SUPPORTED;
394 /* Directory operations */
396 static DIR *vfswrap_opendir(vfs_handle_struct *handle,
397 const struct smb_filename *smb_fname,
403 START_PROFILE(syscall_opendir);
404 result = opendir(smb_fname->base_name);
405 END_PROFILE(syscall_opendir);
409 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
416 START_PROFILE(syscall_fdopendir);
417 result = sys_fdopendir(fsp->fh->fd);
418 END_PROFILE(syscall_fdopendir);
423 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
425 SMB_STRUCT_STAT *sbuf)
427 struct dirent *result;
429 START_PROFILE(syscall_readdir);
430 result = readdir(dirp);
431 END_PROFILE(syscall_readdir);
433 /* Default Posix readdir() does not give us stat info.
434 * Set to invalid to indicate we didn't return this info. */
435 SET_STAT_INVALID(*sbuf);
436 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
437 if (result != NULL) {
438 /* See if we can efficiently return this. */
440 int flags = AT_SYMLINK_NOFOLLOW;
441 int ret = fstatat(dirfd(dirp),
446 * As this is an optimization,
447 * ignore it if we stat'ed a
448 * symlink. Make the caller
449 * do it again as we don't
450 * know if they wanted the link
451 * info, or its target info.
453 if ((ret == 0) && (!S_ISLNK(st.st_mode))) {
454 init_stat_ex_from_stat(sbuf,
456 lp_fake_directory_create_times(
457 SNUM(handle->conn)));
465 static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
466 const struct smb_filename *fname,
468 struct readdir_attr_data **attr_data)
470 return NT_STATUS_NOT_SUPPORTED;
473 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
475 START_PROFILE(syscall_seekdir);
476 seekdir(dirp, offset);
477 END_PROFILE(syscall_seekdir);
480 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
483 START_PROFILE(syscall_telldir);
484 result = telldir(dirp);
485 END_PROFILE(syscall_telldir);
489 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
491 START_PROFILE(syscall_rewinddir);
493 END_PROFILE(syscall_rewinddir);
496 static int vfswrap_mkdir(vfs_handle_struct *handle,
497 const struct smb_filename *smb_fname,
501 const char *path = smb_fname->base_name;
504 START_PROFILE(syscall_mkdir);
506 if (lp_inherit_acls(SNUM(handle->conn))
507 && parent_dirname(talloc_tos(), path, &parent, NULL)
508 && directory_has_default_acl(handle->conn, parent)) {
509 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
514 result = mkdir(path, mode);
516 END_PROFILE(syscall_mkdir);
520 static int vfswrap_rmdir(vfs_handle_struct *handle,
521 const struct smb_filename *smb_fname)
525 START_PROFILE(syscall_rmdir);
526 result = rmdir(smb_fname->base_name);
527 END_PROFILE(syscall_rmdir);
531 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
535 START_PROFILE(syscall_closedir);
536 result = closedir(dirp);
537 END_PROFILE(syscall_closedir);
541 /* File operations */
543 static int vfswrap_open(vfs_handle_struct *handle,
544 struct smb_filename *smb_fname,
545 files_struct *fsp, int flags, mode_t mode)
549 START_PROFILE(syscall_open);
551 if (smb_fname->stream_name) {
556 result = open(smb_fname->base_name, flags, mode);
558 END_PROFILE(syscall_open);
562 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
563 struct smb_request *req,
564 uint16_t root_dir_fid,
565 struct smb_filename *smb_fname,
566 uint32_t access_mask,
567 uint32_t share_access,
568 uint32_t create_disposition,
569 uint32_t create_options,
570 uint32_t file_attributes,
571 uint32_t oplock_request,
572 struct smb2_lease *lease,
573 uint64_t allocation_size,
574 uint32_t private_flags,
575 struct security_descriptor *sd,
576 struct ea_list *ea_list,
577 files_struct **result,
579 const struct smb2_create_blobs *in_context_blobs,
580 struct smb2_create_blobs *out_context_blobs)
582 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
583 access_mask, share_access,
584 create_disposition, create_options,
585 file_attributes, oplock_request, lease,
586 allocation_size, private_flags,
588 pinfo, in_context_blobs, out_context_blobs);
591 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
595 START_PROFILE(syscall_close);
596 result = fd_close_posix(fsp);
597 END_PROFILE(syscall_close);
601 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
602 size_t n, off_t offset)
606 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
607 START_PROFILE_BYTES(syscall_pread, n);
608 result = sys_pread(fsp->fh->fd, data, n, offset);
609 END_PROFILE_BYTES(syscall_pread);
611 if (result == -1 && errno == ESPIPE) {
612 /* Maintain the fiction that pipes can be seeked (sought?) on. */
613 result = sys_read(fsp->fh->fd, data, n);
617 #else /* HAVE_PREAD */
620 #endif /* HAVE_PREAD */
625 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
626 size_t n, off_t offset)
630 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
631 START_PROFILE_BYTES(syscall_pwrite, n);
632 result = sys_pwrite(fsp->fh->fd, data, n, offset);
633 END_PROFILE_BYTES(syscall_pwrite);
635 if (result == -1 && errno == ESPIPE) {
636 /* Maintain the fiction that pipes can be sought on. */
637 result = sys_write(fsp->fh->fd, data, n);
640 #else /* HAVE_PWRITE */
643 #endif /* HAVE_PWRITE */
648 struct vfswrap_pread_state {
655 struct vfs_aio_state vfs_aio_state;
656 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
659 static void vfs_pread_do(void *private_data);
660 static void vfs_pread_done(struct tevent_req *subreq);
661 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state);
663 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
665 struct tevent_context *ev,
666 struct files_struct *fsp,
668 size_t n, off_t offset)
670 struct tevent_req *req, *subreq;
671 struct vfswrap_pread_state *state;
673 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
679 state->fd = fsp->fh->fd;
682 state->offset = offset;
684 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
685 state->profile_bytes, n);
686 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
688 subreq = pthreadpool_tevent_job_send(
689 state, ev, handle->conn->sconn->pool,
690 vfs_pread_do, state);
691 if (tevent_req_nomem(subreq, req)) {
692 return tevent_req_post(req, ev);
694 tevent_req_set_callback(subreq, vfs_pread_done, req);
696 talloc_set_destructor(state, vfs_pread_state_destructor);
701 static void vfs_pread_do(void *private_data)
703 struct vfswrap_pread_state *state = talloc_get_type_abort(
704 private_data, struct vfswrap_pread_state);
705 struct timespec start_time;
706 struct timespec end_time;
708 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
710 PROFILE_TIMESTAMP(&start_time);
713 state->ret = pread(state->fd, state->buf, state->count,
715 } while ((state->ret == -1) && (errno == EINTR));
717 if (state->ret == -1) {
718 state->vfs_aio_state.error = errno;
721 PROFILE_TIMESTAMP(&end_time);
723 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
725 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
728 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state)
733 static void vfs_pread_done(struct tevent_req *subreq)
735 struct tevent_req *req = tevent_req_callback_data(
736 subreq, struct tevent_req);
737 struct vfswrap_pread_state *state = tevent_req_data(
738 req, struct vfswrap_pread_state);
741 ret = pthreadpool_tevent_job_recv(subreq);
743 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
744 talloc_set_destructor(state, NULL);
747 tevent_req_error(req, ret);
751 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
752 * means the lower level pthreadpool failed to create a new
753 * thread. Fallback to sync processing in that case to allow
754 * some progress for the client.
759 tevent_req_done(req);
762 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
763 struct vfs_aio_state *vfs_aio_state)
765 struct vfswrap_pread_state *state = tevent_req_data(
766 req, struct vfswrap_pread_state);
768 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
772 *vfs_aio_state = state->vfs_aio_state;
776 struct vfswrap_pwrite_state {
783 struct vfs_aio_state vfs_aio_state;
784 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
787 static void vfs_pwrite_do(void *private_data);
788 static void vfs_pwrite_done(struct tevent_req *subreq);
789 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state);
791 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
793 struct tevent_context *ev,
794 struct files_struct *fsp,
796 size_t n, off_t offset)
798 struct tevent_req *req, *subreq;
799 struct vfswrap_pwrite_state *state;
801 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
807 state->fd = fsp->fh->fd;
810 state->offset = offset;
812 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
813 state->profile_bytes, n);
814 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
816 subreq = pthreadpool_tevent_job_send(
817 state, ev, handle->conn->sconn->pool,
818 vfs_pwrite_do, state);
819 if (tevent_req_nomem(subreq, req)) {
820 return tevent_req_post(req, ev);
822 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
824 talloc_set_destructor(state, vfs_pwrite_state_destructor);
829 static void vfs_pwrite_do(void *private_data)
831 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
832 private_data, struct vfswrap_pwrite_state);
833 struct timespec start_time;
834 struct timespec end_time;
836 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
838 PROFILE_TIMESTAMP(&start_time);
841 state->ret = pwrite(state->fd, state->buf, state->count,
843 } while ((state->ret == -1) && (errno == EINTR));
845 if (state->ret == -1) {
846 state->vfs_aio_state.error = errno;
849 PROFILE_TIMESTAMP(&end_time);
851 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
853 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
856 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state)
861 static void vfs_pwrite_done(struct tevent_req *subreq)
863 struct tevent_req *req = tevent_req_callback_data(
864 subreq, struct tevent_req);
865 struct vfswrap_pwrite_state *state = tevent_req_data(
866 req, struct vfswrap_pwrite_state);
869 ret = pthreadpool_tevent_job_recv(subreq);
871 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
872 talloc_set_destructor(state, NULL);
875 tevent_req_error(req, ret);
879 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
880 * means the lower level pthreadpool failed to create a new
881 * thread. Fallback to sync processing in that case to allow
882 * some progress for the client.
884 vfs_pwrite_do(state);
887 tevent_req_done(req);
890 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
891 struct vfs_aio_state *vfs_aio_state)
893 struct vfswrap_pwrite_state *state = tevent_req_data(
894 req, struct vfswrap_pwrite_state);
896 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
900 *vfs_aio_state = state->vfs_aio_state;
904 struct vfswrap_fsync_state {
908 struct vfs_aio_state vfs_aio_state;
909 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
912 static void vfs_fsync_do(void *private_data);
913 static void vfs_fsync_done(struct tevent_req *subreq);
914 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state);
916 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
918 struct tevent_context *ev,
919 struct files_struct *fsp)
921 struct tevent_req *req, *subreq;
922 struct vfswrap_fsync_state *state;
924 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
930 state->fd = fsp->fh->fd;
932 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_fsync, profile_p,
933 state->profile_bytes, 0);
934 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
936 subreq = pthreadpool_tevent_job_send(
937 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
938 if (tevent_req_nomem(subreq, req)) {
939 return tevent_req_post(req, ev);
941 tevent_req_set_callback(subreq, vfs_fsync_done, req);
943 talloc_set_destructor(state, vfs_fsync_state_destructor);
948 static void vfs_fsync_do(void *private_data)
950 struct vfswrap_fsync_state *state = talloc_get_type_abort(
951 private_data, struct vfswrap_fsync_state);
952 struct timespec start_time;
953 struct timespec end_time;
955 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
957 PROFILE_TIMESTAMP(&start_time);
960 state->ret = fsync(state->fd);
961 } while ((state->ret == -1) && (errno == EINTR));
963 if (state->ret == -1) {
964 state->vfs_aio_state.error = errno;
967 PROFILE_TIMESTAMP(&end_time);
969 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
971 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
974 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state)
979 static void vfs_fsync_done(struct tevent_req *subreq)
981 struct tevent_req *req = tevent_req_callback_data(
982 subreq, struct tevent_req);
983 struct vfswrap_fsync_state *state = tevent_req_data(
984 req, struct vfswrap_fsync_state);
987 ret = pthreadpool_tevent_job_recv(subreq);
989 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
990 talloc_set_destructor(state, NULL);
993 tevent_req_error(req, ret);
997 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
998 * means the lower level pthreadpool failed to create a new
999 * thread. Fallback to sync processing in that case to allow
1000 * some progress for the client.
1002 vfs_fsync_do(state);
1005 tevent_req_done(req);
1008 static int vfswrap_fsync_recv(struct tevent_req *req,
1009 struct vfs_aio_state *vfs_aio_state)
1011 struct vfswrap_fsync_state *state = tevent_req_data(
1012 req, struct vfswrap_fsync_state);
1014 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1018 *vfs_aio_state = state->vfs_aio_state;
1022 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1026 START_PROFILE(syscall_lseek);
1028 result = lseek(fsp->fh->fd, offset, whence);
1030 * We want to maintain the fiction that we can seek
1031 * on a fifo for file system purposes. This allows
1032 * people to set up UNIX fifo's that feed data to Windows
1033 * applications. JRA.
1036 if((result == -1) && (errno == ESPIPE)) {
1041 END_PROFILE(syscall_lseek);
1045 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1046 off_t offset, size_t n)
1050 START_PROFILE_BYTES(syscall_sendfile, n);
1051 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
1052 END_PROFILE_BYTES(syscall_sendfile);
1056 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1058 files_struct *tofsp,
1064 START_PROFILE_BYTES(syscall_recvfile, n);
1065 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
1066 END_PROFILE_BYTES(syscall_recvfile);
1070 static int vfswrap_rename(vfs_handle_struct *handle,
1071 const struct smb_filename *smb_fname_src,
1072 const struct smb_filename *smb_fname_dst)
1076 START_PROFILE(syscall_rename);
1078 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
1083 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
1086 END_PROFILE(syscall_rename);
1090 static int vfswrap_stat(vfs_handle_struct *handle,
1091 struct smb_filename *smb_fname)
1095 START_PROFILE(syscall_stat);
1097 if (smb_fname->stream_name) {
1102 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1103 lp_fake_directory_create_times(SNUM(handle->conn)));
1105 END_PROFILE(syscall_stat);
1109 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1113 START_PROFILE(syscall_fstat);
1114 result = sys_fstat(fsp->fh->fd,
1115 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1116 END_PROFILE(syscall_fstat);
1120 static int vfswrap_lstat(vfs_handle_struct *handle,
1121 struct smb_filename *smb_fname)
1125 START_PROFILE(syscall_lstat);
1127 if (smb_fname->stream_name) {
1132 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1133 lp_fake_directory_create_times(SNUM(handle->conn)));
1135 END_PROFILE(syscall_lstat);
1139 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1141 enum vfs_translate_direction direction,
1142 TALLOC_CTX *mem_ctx,
1145 return NT_STATUS_NONE_MAPPED;
1149 * Implement the default fsctl operation.
1151 static bool vfswrap_logged_ioctl_message = false;
1153 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1154 struct files_struct *fsp,
1157 uint16_t req_flags, /* Needed for UNICODE ... */
1158 const uint8_t *_in_data,
1160 uint8_t **_out_data,
1161 uint32_t max_out_len,
1164 const char *in_data = (const char *)_in_data;
1165 char **out_data = (char **)_out_data;
1169 case FSCTL_SET_SPARSE:
1171 bool set_sparse = true;
1173 if (in_len >= 1 && in_data[0] == 0) {
1177 status = file_set_sparse(handle->conn, fsp, set_sparse);
1179 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1180 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1181 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1182 nt_errstr(status)));
1187 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1189 unsigned char objid[16];
1190 char *return_data = NULL;
1192 /* This should return the object-id on this file.
1193 * I think I'll make this be the inode+dev. JRA.
1196 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1197 fsp_fnum_dbg(fsp)));
1199 *out_len = MIN(max_out_len, 64);
1201 /* Hmmm, will this cause problems if less data asked for? */
1202 return_data = talloc_array(ctx, char, 64);
1203 if (return_data == NULL) {
1204 return NT_STATUS_NO_MEMORY;
1207 /* For backwards compatibility only store the dev/inode. */
1208 push_file_id_16(return_data, &fsp->file_id);
1209 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1210 push_file_id_16(return_data+32, &fsp->file_id);
1211 memset(return_data+48, 0, 16);
1212 *out_data = return_data;
1213 return NT_STATUS_OK;
1216 case FSCTL_GET_REPARSE_POINT:
1218 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1219 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1220 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1221 return NT_STATUS_NOT_A_REPARSE_POINT;
1224 case FSCTL_SET_REPARSE_POINT:
1226 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1227 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1228 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1229 return NT_STATUS_NOT_A_REPARSE_POINT;
1232 case FSCTL_GET_SHADOW_COPY_DATA:
1235 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1236 * and return their volume names. If max_data_count is 16, then it is just
1237 * asking for the number of volumes and length of the combined names.
1239 * pdata is the data allocated by our caller, but that uses
1240 * total_data_count (which is 0 in our case) rather than max_data_count.
1241 * Allocate the correct amount and return the pointer to let
1242 * it be deallocated when we return.
1244 struct shadow_copy_data *shadow_data = NULL;
1245 bool labels = False;
1246 uint32_t labels_data_count = 0;
1248 char *cur_pdata = NULL;
1250 if (max_out_len < 16) {
1251 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1253 return NT_STATUS_INVALID_PARAMETER;
1256 if (max_out_len > 16) {
1260 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1261 if (shadow_data == NULL) {
1262 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1263 return NT_STATUS_NO_MEMORY;
1267 * Call the VFS routine to actually do the work.
1269 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1272 /* broken module didn't set errno on error */
1273 status = NT_STATUS_UNSUCCESSFUL;
1275 status = map_nt_error_from_unix(errno);
1276 if (NT_STATUS_EQUAL(status,
1277 NT_STATUS_NOT_SUPPORTED)) {
1281 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1282 "connectpath %s, failed - %s.\n",
1283 fsp->conn->connectpath,
1284 nt_errstr(status)));
1285 TALLOC_FREE(shadow_data);
1289 labels_data_count = (shadow_data->num_volumes * 2 *
1290 sizeof(SHADOW_COPY_LABEL)) + 2;
1295 *out_len = 12 + labels_data_count;
1298 if (max_out_len < *out_len) {
1299 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1300 max_out_len, *out_len));
1301 TALLOC_FREE(shadow_data);
1302 return NT_STATUS_BUFFER_TOO_SMALL;
1305 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1306 if (cur_pdata == NULL) {
1307 TALLOC_FREE(shadow_data);
1308 return NT_STATUS_NO_MEMORY;
1311 *out_data = cur_pdata;
1313 /* num_volumes 4 bytes */
1314 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1317 /* num_labels 4 bytes */
1318 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1321 /* needed_data_count 4 bytes */
1322 SIVAL(cur_pdata, 8, labels_data_count);
1326 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1327 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1328 if (labels && shadow_data->labels) {
1329 for (i=0; i<shadow_data->num_volumes; i++) {
1331 status = srvstr_push(cur_pdata, req_flags,
1332 cur_pdata, shadow_data->labels[i],
1333 2 * sizeof(SHADOW_COPY_LABEL),
1334 STR_UNICODE|STR_TERMINATE, &len);
1335 if (!NT_STATUS_IS_OK(status)) {
1336 TALLOC_FREE(*out_data);
1337 TALLOC_FREE(shadow_data);
1340 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1341 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1345 TALLOC_FREE(shadow_data);
1347 return NT_STATUS_OK;
1350 case FSCTL_FIND_FILES_BY_SID:
1352 /* pretend this succeeded -
1354 * we have to send back a list with all files owned by this SID
1356 * but I have to check that --metze
1360 struct dom_sid_buf buf;
1364 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1365 fsp_fnum_dbg(fsp)));
1368 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1369 return NT_STATUS_INVALID_PARAMETER;
1372 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1374 /* unknown 4 bytes: this is not the length of the sid :-( */
1375 /*unknown = IVAL(pdata,0);*/
1377 ret = sid_parse(_in_data + 4, sid_len, &sid);
1379 return NT_STATUS_INVALID_PARAMETER;
1381 DEBUGADD(10, ("for SID: %s\n",
1382 dom_sid_str_buf(&sid, &buf)));
1384 if (!sid_to_uid(&sid, &uid)) {
1385 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1386 dom_sid_str_buf(&sid, &buf),
1387 (unsigned long)sid_len));
1391 /* we can take a look at the find source :-)
1393 * find ./ -uid $uid -name '*' is what we need here
1396 * and send 4bytes len and then NULL terminated unicode strings
1399 * but I don't know how to deal with the paged results
1400 * (maybe we can hang the result anywhere in the fsp struct)
1402 * but I don't know how to deal with the paged results
1403 * (maybe we can hang the result anywhere in the fsp struct)
1405 * we don't send all files at once
1406 * and at the next we should *not* start from the beginning,
1407 * so we have to cache the result
1412 /* this works for now... */
1413 return NT_STATUS_OK;
1416 case FSCTL_QUERY_ALLOCATED_RANGES:
1418 /* FIXME: This is just a dummy reply, telling that all of the
1419 * file is allocated. MKS cp needs that.
1420 * Adding the real allocated ranges via FIEMAP on Linux
1421 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1422 * this FSCTL correct for sparse files.
1424 uint64_t offset, length;
1425 char *out_data_tmp = NULL;
1428 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1430 return NT_STATUS_INVALID_PARAMETER;
1433 if (max_out_len < 16) {
1434 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1436 return NT_STATUS_INVALID_PARAMETER;
1439 offset = BVAL(in_data,0);
1440 length = BVAL(in_data,8);
1442 if (offset + length < offset) {
1443 /* No 64-bit integer wrap. */
1444 return NT_STATUS_INVALID_PARAMETER;
1447 /* Shouldn't this be SMB_VFS_STAT ... ? */
1448 status = vfs_stat_fsp(fsp);
1449 if (!NT_STATUS_IS_OK(status)) {
1454 out_data_tmp = talloc_array(ctx, char, *out_len);
1455 if (out_data_tmp == NULL) {
1456 DEBUG(10, ("unable to allocate memory for response\n"));
1457 return NT_STATUS_NO_MEMORY;
1460 if (offset > fsp->fsp_name->st.st_ex_size ||
1461 fsp->fsp_name->st.st_ex_size == 0 ||
1463 memset(out_data_tmp, 0, *out_len);
1465 uint64_t end = offset + length;
1466 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1467 SBVAL(out_data_tmp, 0, 0);
1468 SBVAL(out_data_tmp, 8, end);
1471 *out_data = out_data_tmp;
1473 return NT_STATUS_OK;
1476 case FSCTL_IS_VOLUME_DIRTY:
1478 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1479 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1481 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1482 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1484 return NT_STATUS_INVALID_PARAMETER;
1489 * Only print once ... unfortunately there could be lots of
1490 * different FSCTLs that are called.
1492 if (!vfswrap_logged_ioctl_message) {
1493 vfswrap_logged_ioctl_message = true;
1494 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1495 __func__, function));
1499 return NT_STATUS_NOT_SUPPORTED;
1502 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
1503 const struct smb_filename *fname,
1504 SMB_STRUCT_STAT *sbuf);
1506 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1507 struct smb_filename *smb_fname,
1512 offline = vfswrap_is_offline(handle, smb_fname, &smb_fname->st);
1514 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1517 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1520 struct vfswrap_get_dos_attributes_state {
1521 struct vfs_aio_state aio_state;
1522 connection_struct *conn;
1523 TALLOC_CTX *mem_ctx;
1524 struct tevent_context *ev;
1525 files_struct *dir_fsp;
1526 struct smb_filename *smb_fname;
1531 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq);
1533 static struct tevent_req *vfswrap_get_dos_attributes_send(
1534 TALLOC_CTX *mem_ctx,
1535 struct tevent_context *ev,
1536 struct vfs_handle_struct *handle,
1537 files_struct *dir_fsp,
1538 struct smb_filename *smb_fname)
1540 struct tevent_req *req = NULL;
1541 struct tevent_req *subreq = NULL;
1542 struct vfswrap_get_dos_attributes_state *state = NULL;
1544 req = tevent_req_create(mem_ctx, &state,
1545 struct vfswrap_get_dos_attributes_state);
1550 *state = (struct vfswrap_get_dos_attributes_state) {
1551 .conn = dir_fsp->conn,
1555 .smb_fname = smb_fname,
1558 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1562 SAMBA_XATTR_DOS_ATTRIB,
1564 if (tevent_req_nomem(subreq, req)) {
1565 return tevent_req_post(req, ev);
1567 tevent_req_set_callback(subreq,
1568 vfswrap_get_dos_attributes_getxattr_done,
1574 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq)
1576 struct tevent_req *req =
1577 tevent_req_callback_data(subreq,
1579 struct vfswrap_get_dos_attributes_state *state =
1580 tevent_req_data(req,
1581 struct vfswrap_get_dos_attributes_state);
1583 DATA_BLOB blob = {0};
1586 xattr_size = SMB_VFS_GETXATTRAT_RECV(subreq,
1590 TALLOC_FREE(subreq);
1591 if (xattr_size == -1) {
1592 status = map_nt_error_from_unix(state->aio_state.error);
1594 if (state->as_root) {
1595 tevent_req_nterror(req, status);
1598 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1599 tevent_req_nterror(req, status);
1603 state->as_root = true;
1606 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1610 SAMBA_XATTR_DOS_ATTRIB,
1613 if (tevent_req_nomem(subreq, req)) {
1616 tevent_req_set_callback(subreq,
1617 vfswrap_get_dos_attributes_getxattr_done,
1622 blob.length = xattr_size;
1624 status = parse_dos_attribute_blob(state->smb_fname,
1627 if (!NT_STATUS_IS_OK(status)) {
1628 tevent_req_nterror(req, status);
1632 tevent_req_done(req);
1636 static NTSTATUS vfswrap_get_dos_attributes_recv(struct tevent_req *req,
1637 struct vfs_aio_state *aio_state,
1640 struct vfswrap_get_dos_attributes_state *state =
1641 tevent_req_data(req,
1642 struct vfswrap_get_dos_attributes_state);
1645 if (tevent_req_is_nterror(req, &status)) {
1646 tevent_req_received(req);
1650 *aio_state = state->aio_state;
1651 *dosmode = state->dosmode;
1652 tevent_req_received(req);
1653 return NT_STATUS_OK;
1656 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1657 struct files_struct *fsp,
1662 offline = vfswrap_is_offline(handle, fsp->fsp_name, &fsp->fsp_name->st);
1664 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1667 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1670 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1671 const struct smb_filename *smb_fname,
1674 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1677 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1678 struct files_struct *fsp,
1681 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1684 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1686 struct vfswrap_offload_read_state {
1690 static struct tevent_req *vfswrap_offload_read_send(
1691 TALLOC_CTX *mem_ctx,
1692 struct tevent_context *ev,
1693 struct vfs_handle_struct *handle,
1694 struct files_struct *fsp,
1700 struct tevent_req *req = NULL;
1701 struct vfswrap_offload_read_state *state = NULL;
1704 req = tevent_req_create(mem_ctx, &state,
1705 struct vfswrap_offload_read_state);
1710 status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1711 &vfswrap_offload_ctx);
1712 if (tevent_req_nterror(req, status)) {
1713 return tevent_req_post(req, ev);
1716 if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1717 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1718 return tevent_req_post(req, ev);
1721 status = vfs_offload_token_create_blob(state, fsp, fsctl,
1723 if (tevent_req_nterror(req, status)) {
1724 return tevent_req_post(req, ev);
1727 status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1729 if (tevent_req_nterror(req, status)) {
1730 return tevent_req_post(req, ev);
1733 tevent_req_done(req);
1734 return tevent_req_post(req, ev);
1737 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
1738 struct vfs_handle_struct *handle,
1739 TALLOC_CTX *mem_ctx,
1742 struct vfswrap_offload_read_state *state = tevent_req_data(
1743 req, struct vfswrap_offload_read_state);
1746 if (tevent_req_is_nterror(req, &status)) {
1747 tevent_req_received(req);
1751 token->length = state->token.length;
1752 token->data = talloc_move(mem_ctx, &state->token.data);
1754 tevent_req_received(req);
1755 return NT_STATUS_OK;
1758 struct vfswrap_offload_write_state {
1760 bool read_lck_locked;
1761 bool write_lck_locked;
1763 struct tevent_context *src_ev;
1764 struct files_struct *src_fsp;
1766 struct tevent_context *dst_ev;
1767 struct files_struct *dst_fsp;
1771 size_t next_io_size;
1774 static void vfswrap_offload_write_cleanup(struct tevent_req *req,
1775 enum tevent_req_state req_state)
1777 struct vfswrap_offload_write_state *state = tevent_req_data(
1778 req, struct vfswrap_offload_write_state);
1781 if (state->dst_fsp == NULL) {
1785 ok = change_to_user_by_fsp(state->dst_fsp);
1787 state->dst_fsp = NULL;
1790 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
1792 static struct tevent_req *vfswrap_offload_write_send(
1793 struct vfs_handle_struct *handle,
1794 TALLOC_CTX *mem_ctx,
1795 struct tevent_context *ev,
1798 off_t transfer_offset,
1799 struct files_struct *dest_fsp,
1803 struct tevent_req *req;
1804 struct vfswrap_offload_write_state *state = NULL;
1805 /* off_t is signed! */
1806 off_t max_offset = INT64_MAX - to_copy;
1807 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
1808 files_struct *src_fsp = NULL;
1812 req = tevent_req_create(mem_ctx, &state,
1813 struct vfswrap_offload_write_state);
1818 *state = (struct vfswrap_offload_write_state) {
1820 .src_off = transfer_offset,
1822 .dst_fsp = dest_fsp,
1823 .dst_off = dest_off,
1825 .remaining = to_copy,
1828 tevent_req_set_cleanup_fn(req, vfswrap_offload_write_cleanup);
1831 case FSCTL_SRV_COPYCHUNK:
1832 case FSCTL_SRV_COPYCHUNK_WRITE:
1835 case FSCTL_OFFLOAD_WRITE:
1836 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
1837 return tevent_req_post(req, ev);
1839 case FSCTL_DUP_EXTENTS_TO_FILE:
1840 DBG_DEBUG("COW clones not supported by vfs_default\n");
1841 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1842 return tevent_req_post(req, ev);
1845 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1846 return tevent_req_post(req, ev);
1850 * From here on we assume a copy-chunk fsctl
1854 tevent_req_done(req);
1855 return tevent_req_post(req, ev);
1858 if (state->src_off > max_offset) {
1860 * Protect integer checks below.
1862 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1863 return tevent_req_post(req, ev);
1865 if (state->src_off < 0) {
1867 * Protect integer checks below.
1869 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1870 return tevent_req_post(req, ev);
1872 if (state->dst_off > max_offset) {
1874 * Protect integer checks below.
1876 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1877 return tevent_req_post(req, ev);
1879 if (state->dst_off < 0) {
1881 * Protect integer checks below.
1883 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1884 return tevent_req_post(req, ev);
1887 status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
1889 if (tevent_req_nterror(req, status)) {
1890 return tevent_req_post(req, ev);
1893 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
1895 status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
1896 if (!NT_STATUS_IS_OK(status)) {
1897 tevent_req_nterror(req, status);
1898 return tevent_req_post(req, ev);
1901 ok = change_to_user_by_fsp(src_fsp);
1903 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1904 return tevent_req_post(req, ev);
1907 state->src_ev = src_fsp->conn->sconn->ev_ctx;
1908 state->src_fsp = src_fsp;
1910 status = vfs_stat_fsp(src_fsp);
1911 if (tevent_req_nterror(req, status)) {
1912 return tevent_req_post(req, ev);
1915 if (src_fsp->fsp_name->st.st_ex_size < state->src_off + to_copy) {
1917 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1918 * If the SourceOffset or SourceOffset + Length extends beyond
1919 * the end of file, the server SHOULD<240> treat this as a
1920 * STATUS_END_OF_FILE error.
1922 * <240> Section 3.3.5.15.6: Windows servers will return
1923 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1925 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1926 return tevent_req_post(req, ev);
1929 state->buf = talloc_array(state, uint8_t, num);
1930 if (tevent_req_nomem(state->buf, req)) {
1931 return tevent_req_post(req, ev);
1934 status = vfswrap_offload_write_loop(req);
1935 if (!NT_STATUS_IS_OK(status)) {
1936 tevent_req_nterror(req, status);
1937 return tevent_req_post(req, ev);
1943 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
1945 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
1947 struct vfswrap_offload_write_state *state = tevent_req_data(
1948 req, struct vfswrap_offload_write_state);
1949 struct tevent_req *subreq = NULL;
1950 struct lock_struct read_lck;
1954 * This is called under the context of state->src_fsp.
1957 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
1959 init_strict_lock_struct(state->src_fsp,
1960 state->src_fsp->op->global->open_persistent_id,
1962 state->next_io_size,
1966 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
1970 return NT_STATUS_FILE_LOCK_CONFLICT;
1973 subreq = SMB_VFS_PREAD_SEND(state,
1977 state->next_io_size,
1979 if (subreq == NULL) {
1980 return NT_STATUS_NO_MEMORY;
1982 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
1984 return NT_STATUS_OK;
1987 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
1989 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
1991 struct tevent_req *req = tevent_req_callback_data(
1992 subreq, struct tevent_req);
1993 struct vfswrap_offload_write_state *state = tevent_req_data(
1994 req, struct vfswrap_offload_write_state);
1995 struct vfs_aio_state aio_state;
1996 struct lock_struct write_lck;
2000 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
2001 TALLOC_FREE(subreq);
2003 DBG_ERR("read failed: %s\n", strerror(aio_state.error));
2004 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2007 if (nread != state->next_io_size) {
2008 DBG_ERR("Short read, only %zd of %zu\n",
2009 nread, state->next_io_size);
2010 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2014 state->src_off += nread;
2016 ok = change_to_user_by_fsp(state->dst_fsp);
2018 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2022 init_strict_lock_struct(state->dst_fsp,
2023 state->dst_fsp->op->global->open_persistent_id,
2025 state->next_io_size,
2029 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
2033 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
2037 subreq = SMB_VFS_PWRITE_SEND(state,
2041 state->next_io_size,
2043 if (subreq == NULL) {
2044 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2047 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
2050 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
2052 struct tevent_req *req = tevent_req_callback_data(
2053 subreq, struct tevent_req);
2054 struct vfswrap_offload_write_state *state = tevent_req_data(
2055 req, struct vfswrap_offload_write_state);
2056 struct vfs_aio_state aio_state;
2061 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
2062 TALLOC_FREE(subreq);
2063 if (nwritten == -1) {
2064 DBG_ERR("write failed: %s\n", strerror(aio_state.error));
2065 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2068 if (nwritten != state->next_io_size) {
2069 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
2070 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2074 state->dst_off += nwritten;
2076 if (state->remaining < nwritten) {
2077 /* Paranoia check */
2078 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2081 state->remaining -= nwritten;
2082 if (state->remaining == 0) {
2083 tevent_req_done(req);
2087 ok = change_to_user_by_fsp(state->src_fsp);
2089 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2093 status = vfswrap_offload_write_loop(req);
2094 if (!NT_STATUS_IS_OK(status)) {
2095 tevent_req_nterror(req, status);
2102 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
2103 struct tevent_req *req,
2106 struct vfswrap_offload_write_state *state = tevent_req_data(
2107 req, struct vfswrap_offload_write_state);
2110 if (tevent_req_is_nterror(req, &status)) {
2111 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
2113 tevent_req_received(req);
2117 *copied = state->to_copy;
2118 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
2119 tevent_req_received(req);
2121 return NT_STATUS_OK;
2124 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
2125 TALLOC_CTX *mem_ctx,
2126 struct files_struct *fsp,
2127 struct smb_filename *smb_fname,
2128 uint16_t *_compression_fmt)
2130 return NT_STATUS_INVALID_DEVICE_REQUEST;
2133 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
2134 TALLOC_CTX *mem_ctx,
2135 struct files_struct *fsp,
2136 uint16_t compression_fmt)
2138 return NT_STATUS_INVALID_DEVICE_REQUEST;
2141 /********************************************************************
2142 Given a stat buffer return the allocated size on disk, taking into
2143 account sparse files.
2144 ********************************************************************/
2145 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
2146 struct files_struct *fsp,
2147 const SMB_STRUCT_STAT *sbuf)
2151 START_PROFILE(syscall_get_alloc_size);
2153 if(S_ISDIR(sbuf->st_ex_mode)) {
2158 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2159 /* The type of st_blocksize is blkcnt_t which *MUST* be
2160 signed (according to POSIX) and can be less than 64-bits.
2161 Ensure when we're converting to 64 bits wide we don't
2163 #if defined(SIZEOF_BLKCNT_T_8)
2164 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2165 #elif defined(SIZEOF_BLKCNT_T_4)
2167 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2168 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2171 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2175 * Some file systems do not allocate a block for very
2176 * small files. But for non-empty file should report a
2180 uint64_t filesize = get_file_size_stat(sbuf);
2182 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2186 result = get_file_size_stat(sbuf);
2189 if (fsp && fsp->initial_allocation_size)
2190 result = MAX(result,fsp->initial_allocation_size);
2192 result = smb_roundup(handle->conn, result);
2195 END_PROFILE(syscall_get_alloc_size);
2199 static int vfswrap_unlink(vfs_handle_struct *handle,
2200 const struct smb_filename *smb_fname)
2204 START_PROFILE(syscall_unlink);
2206 if (smb_fname->stream_name) {
2210 result = unlink(smb_fname->base_name);
2213 END_PROFILE(syscall_unlink);
2217 static int vfswrap_chmod(vfs_handle_struct *handle,
2218 const struct smb_filename *smb_fname,
2223 START_PROFILE(syscall_chmod);
2224 result = chmod(smb_fname->base_name, mode);
2225 END_PROFILE(syscall_chmod);
2229 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2233 START_PROFILE(syscall_fchmod);
2234 #if defined(HAVE_FCHMOD)
2235 result = fchmod(fsp->fh->fd, mode);
2241 END_PROFILE(syscall_fchmod);
2245 static int vfswrap_chown(vfs_handle_struct *handle,
2246 const struct smb_filename *smb_fname,
2252 START_PROFILE(syscall_chown);
2253 result = chown(smb_fname->base_name, uid, gid);
2254 END_PROFILE(syscall_chown);
2258 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2263 START_PROFILE(syscall_fchown);
2264 result = fchown(fsp->fh->fd, uid, gid);
2265 END_PROFILE(syscall_fchown);
2273 static int vfswrap_lchown(vfs_handle_struct *handle,
2274 const struct smb_filename *smb_fname,
2280 START_PROFILE(syscall_lchown);
2281 result = lchown(smb_fname->base_name, uid, gid);
2282 END_PROFILE(syscall_lchown);
2286 static int vfswrap_chdir(vfs_handle_struct *handle,
2287 const struct smb_filename *smb_fname)
2291 START_PROFILE(syscall_chdir);
2292 result = chdir(smb_fname->base_name);
2293 END_PROFILE(syscall_chdir);
2297 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2301 struct smb_filename *smb_fname = NULL;
2303 START_PROFILE(syscall_getwd);
2304 result = sys_getwd();
2305 END_PROFILE(syscall_getwd);
2307 if (result == NULL) {
2310 smb_fname = synthetic_smb_fname(ctx,
2316 * sys_getwd() *always* returns malloced memory.
2317 * We must free here to avoid leaks:
2318 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2324 /*********************************************************************
2325 nsec timestamp resolution call. Convert down to whatever the underlying
2326 system will support.
2327 **********************************************************************/
2329 static int vfswrap_ntimes(vfs_handle_struct *handle,
2330 const struct smb_filename *smb_fname,
2331 struct smb_file_time *ft)
2335 START_PROFILE(syscall_ntimes);
2337 if (smb_fname->stream_name) {
2343 if (null_timespec(ft->atime)) {
2344 ft->atime= smb_fname->st.st_ex_atime;
2347 if (null_timespec(ft->mtime)) {
2348 ft->mtime = smb_fname->st.st_ex_mtime;
2351 if (!null_timespec(ft->create_time)) {
2352 set_create_timespec_ea(handle->conn,
2357 if ((timespec_compare(&ft->atime,
2358 &smb_fname->st.st_ex_atime) == 0) &&
2359 (timespec_compare(&ft->mtime,
2360 &smb_fname->st.st_ex_mtime) == 0)) {
2365 #if defined(HAVE_UTIMENSAT)
2367 struct timespec ts[2];
2370 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2372 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2374 if (!((result == -1) && (errno == ENOSYS))) {
2378 #if defined(HAVE_UTIMES)
2380 struct timeval tv[2];
2381 tv[0] = convert_timespec_to_timeval(ft->atime);
2382 tv[1] = convert_timespec_to_timeval(ft->mtime);
2383 result = utimes(smb_fname->base_name, tv);
2385 result = utimes(smb_fname->base_name, NULL);
2387 if (!((result == -1) && (errno == ENOSYS))) {
2391 #if defined(HAVE_UTIME)
2393 struct utimbuf times;
2394 times.actime = convert_timespec_to_time_t(ft->atime);
2395 times.modtime = convert_timespec_to_time_t(ft->mtime);
2396 result = utime(smb_fname->base_name, ×);
2398 result = utime(smb_fname->base_name, NULL);
2400 if (!((result == -1) && (errno == ENOSYS))) {
2408 END_PROFILE(syscall_ntimes);
2412 /*********************************************************************
2413 A version of ftruncate that will write the space on disk if strict
2415 **********************************************************************/
2417 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2419 off_t space_to_write;
2420 uint64_t space_avail;
2421 uint64_t bsize,dfree,dsize;
2424 SMB_STRUCT_STAT *pst;
2426 status = vfs_stat_fsp(fsp);
2427 if (!NT_STATUS_IS_OK(status)) {
2430 pst = &fsp->fsp_name->st;
2433 if (S_ISFIFO(pst->st_ex_mode))
2437 if (pst->st_ex_size == len)
2440 /* Shrink - just ftruncate. */
2441 if (pst->st_ex_size > len)
2442 return ftruncate(fsp->fh->fd, len);
2444 space_to_write = len - pst->st_ex_size;
2446 /* for allocation try fallocate first. This can fail on some
2447 platforms e.g. when the filesystem doesn't support it and no
2448 emulation is being done by the libc (like on AIX with JFS1). In that
2449 case we do our own emulation. fallocate implementations can
2450 return ENOTSUP or EINVAL in cases like that. */
2451 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2452 if (ret == -1 && errno == ENOSPC) {
2458 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2459 "error %d. Falling back to slow manual allocation\n", errno));
2461 /* available disk space is enough or not? */
2463 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2464 /* space_avail is 1k blocks */
2465 if (space_avail == (uint64_t)-1 ||
2466 ((uint64_t)space_to_write/1024 > space_avail) ) {
2471 /* Write out the real space on disk. */
2472 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2480 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2483 SMB_STRUCT_STAT *pst;
2487 START_PROFILE(syscall_ftruncate);
2489 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2490 result = strict_allocate_ftruncate(handle, fsp, len);
2491 END_PROFILE(syscall_ftruncate);
2495 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2496 ftruncate if the system supports it. Then I discovered that
2497 you can have some filesystems that support ftruncate
2498 expansion and some that don't! On Linux fat can't do
2499 ftruncate extend but ext2 can. */
2501 result = ftruncate(fsp->fh->fd, len);
2503 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2504 extend a file with ftruncate. Provide alternate implementation
2507 /* Do an fstat to see if the file is longer than the requested
2508 size in which case the ftruncate above should have
2509 succeeded or shorter, in which case seek to len - 1 and
2510 write 1 byte of zero */
2511 status = vfs_stat_fsp(fsp);
2512 if (!NT_STATUS_IS_OK(status)) {
2516 /* We need to update the files_struct after successful ftruncate */
2521 pst = &fsp->fsp_name->st;
2524 if (S_ISFIFO(pst->st_ex_mode)) {
2530 if (pst->st_ex_size == len) {
2535 if (pst->st_ex_size > len) {
2536 /* the ftruncate should have worked */
2540 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2548 END_PROFILE(syscall_ftruncate);
2552 static int vfswrap_fallocate(vfs_handle_struct *handle,
2560 START_PROFILE(syscall_fallocate);
2562 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2564 * posix_fallocate returns 0 on success, errno on error
2565 * and doesn't set errno. Make it behave like fallocate()
2566 * which returns -1, and sets errno on failure.
2573 /* sys_fallocate handles filtering of unsupported mode flags */
2574 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2576 END_PROFILE(syscall_fallocate);
2580 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2584 START_PROFILE(syscall_fcntl_lock);
2586 if (fsp->use_ofd_locks) {
2587 op = map_process_lock_to_ofd_lock(op);
2590 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2591 END_PROFILE(syscall_fcntl_lock);
2595 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2596 uint32_t share_mode, uint32_t access_mask)
2598 START_PROFILE(syscall_kernel_flock);
2599 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2600 END_PROFILE(syscall_kernel_flock);
2604 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2609 START_PROFILE(syscall_fcntl_getlock);
2611 if (fsp->use_ofd_locks) {
2612 op = map_process_lock_to_ofd_lock(op);
2615 result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2616 END_PROFILE(syscall_fcntl_getlock);
2620 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2625 START_PROFILE(syscall_linux_setlease);
2627 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2628 result = linux_setlease(fsp->fh->fd, leasetype);
2632 END_PROFILE(syscall_linux_setlease);
2636 static int vfswrap_symlink(vfs_handle_struct *handle,
2637 const char *link_target,
2638 const struct smb_filename *new_smb_fname)
2642 START_PROFILE(syscall_symlink);
2643 result = symlink(link_target, new_smb_fname->base_name);
2644 END_PROFILE(syscall_symlink);
2648 static int vfswrap_readlink(vfs_handle_struct *handle,
2649 const struct smb_filename *smb_fname,
2655 START_PROFILE(syscall_readlink);
2656 result = readlink(smb_fname->base_name, buf, bufsiz);
2657 END_PROFILE(syscall_readlink);
2661 static int vfswrap_link(vfs_handle_struct *handle,
2662 const struct smb_filename *old_smb_fname,
2663 const struct smb_filename *new_smb_fname)
2667 START_PROFILE(syscall_link);
2668 result = link(old_smb_fname->base_name, new_smb_fname->base_name);
2669 END_PROFILE(syscall_link);
2673 static int vfswrap_mknod(vfs_handle_struct *handle,
2674 const struct smb_filename *smb_fname,
2680 START_PROFILE(syscall_mknod);
2681 result = sys_mknod(smb_fname->base_name, mode, dev);
2682 END_PROFILE(syscall_mknod);
2686 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2688 const struct smb_filename *smb_fname)
2691 struct smb_filename *result_fname = NULL;
2693 START_PROFILE(syscall_realpath);
2694 result = sys_realpath(smb_fname->base_name);
2695 END_PROFILE(syscall_realpath);
2697 result_fname = synthetic_smb_fname(ctx, result, NULL, NULL, 0);
2700 return result_fname;
2703 static int vfswrap_chflags(vfs_handle_struct *handle,
2704 const struct smb_filename *smb_fname,
2708 return chflags(smb_fname->base_name, flags);
2715 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2716 const SMB_STRUCT_STAT *sbuf)
2720 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2724 key.devid = sbuf->st_ex_dev;
2725 key.inode = sbuf->st_ex_ino;
2726 /* key.extid is unused by default. */
2731 static uint64_t vfswrap_fs_file_id(struct vfs_handle_struct *handle,
2732 const SMB_STRUCT_STAT *psbuf)
2736 if (!(psbuf->st_ex_iflags & ST_EX_IFLAG_CALCULATED_ITIME)) {
2737 return psbuf->st_ex_file_id;
2740 if (handle->conn->base_share_dev == psbuf->st_ex_dev) {
2741 return (uint64_t)psbuf->st_ex_ino;
2745 file_id = ((psbuf->st_ex_ino) & UINT32_MAX);
2748 file_id |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32;
2753 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2754 struct files_struct *fsp,
2755 const struct smb_filename *smb_fname,
2756 TALLOC_CTX *mem_ctx,
2757 unsigned int *pnum_streams,
2758 struct stream_struct **pstreams)
2760 SMB_STRUCT_STAT sbuf;
2761 struct stream_struct *tmp_streams = NULL;
2764 if ((fsp != NULL) && (fsp->is_directory)) {
2766 * No default streams on directories
2771 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2772 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2775 struct smb_filename smb_fname_cp;
2777 ZERO_STRUCT(smb_fname_cp);
2778 smb_fname_cp.base_name = discard_const_p(char,
2779 smb_fname->base_name);
2780 smb_fname_cp.flags = smb_fname->flags;
2782 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
2783 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2785 ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2787 sbuf = smb_fname_cp.st;
2791 return map_nt_error_from_unix(errno);
2794 if (S_ISDIR(sbuf.st_ex_mode)) {
2798 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2799 (*pnum_streams) + 1);
2800 if (tmp_streams == NULL) {
2801 return NT_STATUS_NO_MEMORY;
2803 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2804 if (tmp_streams[*pnum_streams].name == NULL) {
2805 return NT_STATUS_NO_MEMORY;
2807 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2808 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2811 *pstreams = tmp_streams;
2813 return NT_STATUS_OK;
2816 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2819 TALLOC_CTX *mem_ctx,
2823 * Don't fall back to get_real_filename so callers can differentiate
2824 * between a full directory scan and an actual case-insensitive stat.
2830 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2831 const struct smb_filename *smb_fname)
2833 return handle->conn->connectpath;
2836 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2837 struct byte_range_lock *br_lck,
2838 struct lock_struct *plock)
2840 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2842 /* Note: blr is not used in the default implementation. */
2843 return brl_lock_windows_default(br_lck, plock);
2846 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2847 struct byte_range_lock *br_lck,
2848 const struct lock_struct *plock)
2850 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2852 return brl_unlock_windows_default(br_lck, plock);
2855 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
2857 struct lock_struct *plock)
2859 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2860 plock->lock_type == WRITE_LOCK);
2862 return strict_lock_check_default(fsp, plock);
2865 /* NT ACL operations. */
2867 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2869 uint32_t security_info,
2870 TALLOC_CTX *mem_ctx,
2871 struct security_descriptor **ppdesc)
2875 START_PROFILE(fget_nt_acl);
2876 result = posix_fget_nt_acl(fsp, security_info,
2878 END_PROFILE(fget_nt_acl);
2882 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2883 const struct smb_filename *smb_fname,
2884 uint32_t security_info,
2885 TALLOC_CTX *mem_ctx,
2886 struct security_descriptor **ppdesc)
2890 START_PROFILE(get_nt_acl);
2891 result = posix_get_nt_acl(handle->conn,
2896 END_PROFILE(get_nt_acl);
2900 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2904 START_PROFILE(fset_nt_acl);
2905 result = set_nt_acl(fsp, security_info_sent, psd);
2906 END_PROFILE(fset_nt_acl);
2910 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2911 struct smb_filename *file,
2912 struct security_acl *sacl,
2913 uint32_t access_requested,
2914 uint32_t access_denied)
2916 return NT_STATUS_OK; /* Nothing to do here ... */
2919 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2920 const struct smb_filename *smb_fname,
2921 SMB_ACL_TYPE_T type,
2922 TALLOC_CTX *mem_ctx)
2924 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
2927 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2929 TALLOC_CTX *mem_ctx)
2931 return sys_acl_get_fd(handle, fsp, mem_ctx);
2934 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
2935 const struct smb_filename *smb_fname,
2936 SMB_ACL_TYPE_T acltype,
2939 return sys_acl_set_file(handle, smb_fname, acltype, theacl);
2942 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2944 return sys_acl_set_fd(handle, fsp, theacl);
2947 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
2948 const struct smb_filename *smb_fname)
2950 return sys_acl_delete_def_file(handle, smb_fname);
2953 /****************************************************************
2954 Extended attribute operations.
2955 *****************************************************************/
2957 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
2958 const struct smb_filename *smb_fname,
2963 return getxattr(smb_fname->base_name, name, value, size);
2966 struct vfswrap_getxattrat_state {
2967 struct tevent_context *ev;
2968 files_struct *dir_fsp;
2969 const struct smb_filename *smb_fname;
2970 struct tevent_req *req;
2973 * The following variables are talloced off "state" which is protected
2974 * by a destructor and thus are guaranteed to be safe to be used in the
2975 * job function in the worker thread.
2978 const char *xattr_name;
2979 uint8_t *xattr_value;
2980 struct security_unix_token *token;
2983 struct vfs_aio_state vfs_aio_state;
2984 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
2987 static int vfswrap_getxattrat_state_destructor(
2988 struct vfswrap_getxattrat_state *state)
2993 static void vfswrap_getxattrat_do_sync(struct tevent_req *req);
2994 static void vfswrap_getxattrat_do_async(void *private_data);
2995 static void vfswrap_getxattrat_done(struct tevent_req *subreq);
2997 static struct tevent_req *vfswrap_getxattrat_send(
2998 TALLOC_CTX *mem_ctx,
2999 struct tevent_context *ev,
3000 struct vfs_handle_struct *handle,
3001 files_struct *dir_fsp,
3002 const struct smb_filename *smb_fname,
3003 const char *xattr_name,
3006 struct tevent_req *req = NULL;
3007 struct tevent_req *subreq = NULL;
3008 struct vfswrap_getxattrat_state *state = NULL;
3009 size_t max_threads = 0;
3010 bool have_per_thread_cwd = false;
3011 bool have_per_thread_creds = false;
3012 bool do_async = false;
3014 req = tevent_req_create(mem_ctx, &state,
3015 struct vfswrap_getxattrat_state);
3019 *state = (struct vfswrap_getxattrat_state) {
3022 .smb_fname = smb_fname,
3026 max_threads = pthreadpool_tevent_max_threads(dir_fsp->conn->sconn->pool);
3027 if (max_threads >= 1) {
3029 * We need a non sync threadpool!
3031 have_per_thread_cwd = per_thread_cwd_supported();
3033 #ifdef HAVE_LINUX_THREAD_CREDENTIALS
3034 have_per_thread_creds = true;
3036 if (have_per_thread_cwd && have_per_thread_creds) {
3040 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat, profile_p,
3041 state->profile_bytes, 0);
3043 if (dir_fsp->fh->fd == -1) {
3044 DBG_ERR("Need a valid directory fd\n");
3045 tevent_req_error(req, EINVAL);
3046 return tevent_req_post(req, ev);
3049 if (alloc_hint > 0) {
3050 state->xattr_value = talloc_zero_array(state,
3053 if (tevent_req_nomem(state->xattr_value, req)) {
3054 return tevent_req_post(req, ev);
3059 vfswrap_getxattrat_do_sync(req);
3060 return tevent_req_post(req, ev);
3064 * Now allocate all parameters from a memory context that won't go away
3065 * no matter what. These paremeters will get used in threads and we
3066 * can't reliably cancel threads, so all buffers passed to the threads
3067 * must not be freed before all referencing threads terminate.
3070 state->name = talloc_strdup(state, smb_fname->base_name);
3071 if (tevent_req_nomem(state->name, req)) {
3072 return tevent_req_post(req, ev);
3075 state->xattr_name = talloc_strdup(state, xattr_name);
3076 if (tevent_req_nomem(state->xattr_name, req)) {
3077 return tevent_req_post(req, ev);
3081 * This is a hot codepath so at first glance one might think we should
3082 * somehow optimize away the token allocation and do a
3083 * talloc_reference() or similar black magic instead. But due to the
3084 * talloc_stackframe pool per SMB2 request this should be a simple copy
3085 * without a malloc in most cases.
3087 if (geteuid() == sec_initial_uid()) {
3088 state->token = root_unix_token(state);
3090 state->token = copy_unix_token(
3092 dir_fsp->conn->session_info->unix_token);
3094 if (tevent_req_nomem(state->token, req)) {
3095 return tevent_req_post(req, ev);
3098 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3100 subreq = pthreadpool_tevent_job_send(
3103 dir_fsp->conn->sconn->pool,
3104 vfswrap_getxattrat_do_async,
3106 if (tevent_req_nomem(subreq, req)) {
3107 return tevent_req_post(req, ev);
3109 tevent_req_set_callback(subreq, vfswrap_getxattrat_done, req);
3111 talloc_set_destructor(state, vfswrap_getxattrat_state_destructor);
3116 static void vfswrap_getxattrat_do_sync(struct tevent_req *req)
3118 struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3119 req, struct vfswrap_getxattrat_state);
3121 char *tofree = NULL;
3122 char pathbuf[PATH_MAX+1];
3126 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
3127 state->smb_fname->base_name,
3132 if (pathlen == -1) {
3133 tevent_req_error(req, ENOMEM);
3137 state->xattr_size = getxattr(path,
3140 talloc_array_length(state->xattr_value));
3142 TALLOC_FREE(tofree);
3143 if (state->xattr_size == -1) {
3144 tevent_req_error(req, err);
3148 tevent_req_done(req);
3152 static void vfswrap_getxattrat_do_async(void *private_data)
3154 struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3155 private_data, struct vfswrap_getxattrat_state);
3156 struct timespec start_time;
3157 struct timespec end_time;
3160 PROFILE_TIMESTAMP(&start_time);
3161 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
3164 * Here we simulate a getxattrat()
3165 * call using fchdir();getxattr()
3168 per_thread_cwd_activate();
3170 /* Become the correct credential on this thread. */
3171 ret = set_thread_credentials(state->token->uid,
3173 (size_t)state->token->ngroups,
3174 state->token->groups);
3176 state->xattr_size = -1;
3177 state->vfs_aio_state.error = errno;
3181 ret = fchdir(state->dir_fsp->fh->fd);
3183 state->xattr_size = -1;
3184 state->vfs_aio_state.error = errno;
3188 state->xattr_size = getxattr(state->name,
3191 talloc_array_length(state->xattr_value));
3192 if (state->xattr_size == -1) {
3193 state->vfs_aio_state.error = errno;
3197 PROFILE_TIMESTAMP(&end_time);
3198 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
3199 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3202 static void vfswrap_getxattrat_done(struct tevent_req *subreq)
3204 struct tevent_req *req = tevent_req_callback_data(
3205 subreq, struct tevent_req);
3206 struct vfswrap_getxattrat_state *state = tevent_req_data(
3207 req, struct vfswrap_getxattrat_state);
3212 * Make sure we run as the user again
3214 ok = change_to_user_by_fsp(state->dir_fsp);
3217 ret = pthreadpool_tevent_job_recv(subreq);
3218 TALLOC_FREE(subreq);
3219 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
3220 talloc_set_destructor(state, NULL);
3222 if (ret != EAGAIN) {
3223 tevent_req_error(req, ret);
3227 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
3228 * means the lower level pthreadpool failed to create a new
3229 * thread. Fallback to sync processing in that case to allow
3230 * some progress for the client.
3232 vfswrap_getxattrat_do_sync(req);
3236 if (state->xattr_size == -1) {
3237 tevent_req_error(req, state->vfs_aio_state.error);
3241 if (state->xattr_value == NULL) {
3243 * The caller only wanted the size.
3245 tevent_req_done(req);
3250 * shrink the buffer to the returned size.
3251 * (can't fail). It means NULL if size is 0.
3253 state->xattr_value = talloc_realloc(state,
3258 tevent_req_done(req);
3261 static ssize_t vfswrap_getxattrat_recv(struct tevent_req *req,
3262 struct vfs_aio_state *aio_state,
3263 TALLOC_CTX *mem_ctx,
3264 uint8_t **xattr_value)
3266 struct vfswrap_getxattrat_state *state = tevent_req_data(
3267 req, struct vfswrap_getxattrat_state);
3270 if (tevent_req_is_unix_error(req, &aio_state->error)) {
3271 tevent_req_received(req);
3275 *aio_state = state->vfs_aio_state;
3276 xattr_size = state->xattr_size;
3277 if (xattr_value != NULL) {
3278 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
3281 tevent_req_received(req);
3285 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
3287 return fgetxattr(fsp->fh->fd, name, value, size);
3290 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
3291 const struct smb_filename *smb_fname,
3295 return listxattr(smb_fname->base_name, list, size);
3298 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
3300 return flistxattr(fsp->fh->fd, list, size);
3303 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
3304 const struct smb_filename *smb_fname,
3307 return removexattr(smb_fname->base_name, name);
3310 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
3312 return fremovexattr(fsp->fh->fd, name);
3315 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
3316 const struct smb_filename *smb_fname,
3322 return setxattr(smb_fname->base_name, name, value, size, flags);
3325 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
3327 return fsetxattr(fsp->fh->fd, name, value, size, flags);
3330 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
3335 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
3336 const struct smb_filename *fname,
3337 SMB_STRUCT_STAT *sbuf)
3341 bool offline = false;
3343 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
3347 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
3348 #if defined(ENOTSUP)
3354 status = get_full_smb_filename(talloc_tos(), fname, &path);
3355 if (!NT_STATUS_IS_OK(status)) {
3356 errno = map_errno_from_nt_status(status);
3360 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
3367 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
3368 struct files_struct *fsp,
3369 TALLOC_CTX *mem_ctx,
3372 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
3375 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
3376 struct files_struct *fsp,
3377 const DATA_BLOB old_cookie,
3378 TALLOC_CTX *mem_ctx,
3379 DATA_BLOB *new_cookie)
3381 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
3385 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
3386 struct smb_request *smb1req,
3387 struct smbXsrv_open *op,
3388 const DATA_BLOB old_cookie,
3389 TALLOC_CTX *mem_ctx,
3390 struct files_struct **fsp,
3391 DATA_BLOB *new_cookie)
3393 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
3394 old_cookie, mem_ctx,
3398 static struct vfs_fn_pointers vfs_default_fns = {
3399 /* Disk operations */
3401 .connect_fn = vfswrap_connect,
3402 .disconnect_fn = vfswrap_disconnect,
3403 .disk_free_fn = vfswrap_disk_free,
3404 .get_quota_fn = vfswrap_get_quota,
3405 .set_quota_fn = vfswrap_set_quota,
3406 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3407 .statvfs_fn = vfswrap_statvfs,
3408 .fs_capabilities_fn = vfswrap_fs_capabilities,
3409 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3410 .snap_check_path_fn = vfswrap_snap_check_path,
3411 .snap_create_fn = vfswrap_snap_create,
3412 .snap_delete_fn = vfswrap_snap_delete,
3414 /* Directory operations */
3416 .opendir_fn = vfswrap_opendir,
3417 .fdopendir_fn = vfswrap_fdopendir,
3418 .readdir_fn = vfswrap_readdir,
3419 .readdir_attr_fn = vfswrap_readdir_attr,
3420 .seekdir_fn = vfswrap_seekdir,
3421 .telldir_fn = vfswrap_telldir,
3422 .rewind_dir_fn = vfswrap_rewinddir,
3423 .mkdir_fn = vfswrap_mkdir,
3424 .rmdir_fn = vfswrap_rmdir,
3425 .closedir_fn = vfswrap_closedir,
3427 /* File operations */
3429 .open_fn = vfswrap_open,
3430 .create_file_fn = vfswrap_create_file,
3431 .close_fn = vfswrap_close,
3432 .pread_fn = vfswrap_pread,
3433 .pread_send_fn = vfswrap_pread_send,
3434 .pread_recv_fn = vfswrap_pread_recv,
3435 .pwrite_fn = vfswrap_pwrite,
3436 .pwrite_send_fn = vfswrap_pwrite_send,
3437 .pwrite_recv_fn = vfswrap_pwrite_recv,
3438 .lseek_fn = vfswrap_lseek,
3439 .sendfile_fn = vfswrap_sendfile,
3440 .recvfile_fn = vfswrap_recvfile,
3441 .rename_fn = vfswrap_rename,
3442 .fsync_send_fn = vfswrap_fsync_send,
3443 .fsync_recv_fn = vfswrap_fsync_recv,
3444 .stat_fn = vfswrap_stat,
3445 .fstat_fn = vfswrap_fstat,
3446 .lstat_fn = vfswrap_lstat,
3447 .get_alloc_size_fn = vfswrap_get_alloc_size,
3448 .unlink_fn = vfswrap_unlink,
3449 .chmod_fn = vfswrap_chmod,
3450 .fchmod_fn = vfswrap_fchmod,
3451 .chown_fn = vfswrap_chown,
3452 .fchown_fn = vfswrap_fchown,
3453 .lchown_fn = vfswrap_lchown,
3454 .chdir_fn = vfswrap_chdir,
3455 .getwd_fn = vfswrap_getwd,
3456 .ntimes_fn = vfswrap_ntimes,
3457 .ftruncate_fn = vfswrap_ftruncate,
3458 .fallocate_fn = vfswrap_fallocate,
3459 .lock_fn = vfswrap_lock,
3460 .kernel_flock_fn = vfswrap_kernel_flock,
3461 .linux_setlease_fn = vfswrap_linux_setlease,
3462 .getlock_fn = vfswrap_getlock,
3463 .symlink_fn = vfswrap_symlink,
3464 .readlink_fn = vfswrap_readlink,
3465 .link_fn = vfswrap_link,
3466 .mknod_fn = vfswrap_mknod,
3467 .realpath_fn = vfswrap_realpath,
3468 .chflags_fn = vfswrap_chflags,
3469 .file_id_create_fn = vfswrap_file_id_create,
3470 .fs_file_id_fn = vfswrap_fs_file_id,
3471 .streaminfo_fn = vfswrap_streaminfo,
3472 .get_real_filename_fn = vfswrap_get_real_filename,
3473 .connectpath_fn = vfswrap_connectpath,
3474 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
3475 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3476 .strict_lock_check_fn = vfswrap_strict_lock_check,
3477 .translate_name_fn = vfswrap_translate_name,
3478 .fsctl_fn = vfswrap_fsctl,
3479 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
3480 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
3481 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
3482 .get_dos_attributes_send_fn = vfswrap_get_dos_attributes_send,
3483 .get_dos_attributes_recv_fn = vfswrap_get_dos_attributes_recv,
3484 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
3485 .offload_read_send_fn = vfswrap_offload_read_send,
3486 .offload_read_recv_fn = vfswrap_offload_read_recv,
3487 .offload_write_send_fn = vfswrap_offload_write_send,
3488 .offload_write_recv_fn = vfswrap_offload_write_recv,
3489 .get_compression_fn = vfswrap_get_compression,
3490 .set_compression_fn = vfswrap_set_compression,
3492 /* NT ACL operations. */
3494 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
3495 .get_nt_acl_fn = vfswrap_get_nt_acl,
3496 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
3497 .audit_file_fn = vfswrap_audit_file,
3499 /* POSIX ACL operations. */
3501 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
3502 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3503 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
3504 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3505 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
3506 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3507 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
3509 /* EA operations. */
3510 .getxattr_fn = vfswrap_getxattr,
3511 .getxattrat_send_fn = vfswrap_getxattrat_send,
3512 .getxattrat_recv_fn = vfswrap_getxattrat_recv,
3513 .fgetxattr_fn = vfswrap_fgetxattr,
3514 .listxattr_fn = vfswrap_listxattr,
3515 .flistxattr_fn = vfswrap_flistxattr,
3516 .removexattr_fn = vfswrap_removexattr,
3517 .fremovexattr_fn = vfswrap_fremovexattr,
3518 .setxattr_fn = vfswrap_setxattr,
3519 .fsetxattr_fn = vfswrap_fsetxattr,
3521 /* aio operations */
3522 .aio_force_fn = vfswrap_aio_force,
3524 /* durable handle operations */
3525 .durable_cookie_fn = vfswrap_durable_cookie,
3526 .durable_disconnect_fn = vfswrap_durable_disconnect,
3527 .durable_reconnect_fn = vfswrap_durable_reconnect,
3531 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3534 * Here we need to implement every call!
3536 * As this is the end of the vfs module chain.
3538 smb_vfs_assert_all_fns(&vfs_default_fns, DEFAULT_VFS_MODULE_NAME);
3539 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3540 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);