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 const struct loadparm_substitution *lp_sub =
127 loadparm_s3_global_substitution();
128 connection_struct *conn = handle->conn;
129 uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
130 struct smb_filename *smb_fname_cpath = NULL;
131 struct vfs_statvfs_struct statbuf;
134 smb_fname_cpath = synthetic_smb_fname(talloc_tos(), conn->connectpath,
136 if (smb_fname_cpath == NULL) {
140 ZERO_STRUCT(statbuf);
141 ret = SMB_VFS_STATVFS(conn, smb_fname_cpath, &statbuf);
143 caps = statbuf.FsCapabilities;
146 *p_ts_res = TIMESTAMP_SET_SECONDS;
148 /* Work out what timestamp resolution we can
149 * use when setting a timestamp. */
151 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
153 TALLOC_FREE(smb_fname_cpath);
157 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
158 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
159 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
160 /* If any of the normal UNIX directory timestamps
161 * have a non-zero tv_nsec component assume
162 * we might be able to set sub-second timestamps.
163 * See what filetime set primitives we have.
165 #if defined(HAVE_UTIMENSAT)
166 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
167 #elif defined(HAVE_UTIMES)
168 /* utimes allows msec timestamps to be set. */
169 *p_ts_res = TIMESTAMP_SET_MSEC;
170 #elif defined(HAVE_UTIME)
171 /* utime only allows sec timestamps to be set. */
172 *p_ts_res = TIMESTAMP_SET_SECONDS;
175 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
177 "available on share %s, directory %s\n",
178 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
179 lp_servicename(talloc_tos(), lp_sub, conn->params->service),
180 conn->connectpath ));
182 TALLOC_FREE(smb_fname_cpath);
186 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
187 struct dfs_GetDFSReferral *r)
189 struct junction_map *junction = NULL;
191 bool self_referral = false;
192 char *pathnamep = NULL;
193 char *local_dfs_path = NULL;
196 uint16_t max_referral_level = r->in.req.max_referral_level;
199 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
202 /* get the junction entry */
203 if (r->in.req.servername == NULL) {
204 return NT_STATUS_NOT_FOUND;
208 * Trim pathname sent by client so it begins with only one backslash.
209 * Two backslashes confuse some dfs clients
212 local_dfs_path = talloc_strdup(r, r->in.req.servername);
213 if (local_dfs_path == NULL) {
214 return NT_STATUS_NO_MEMORY;
216 pathnamep = local_dfs_path;
217 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
218 IS_DIRECTORY_SEP(pathnamep[1])) {
222 junction = talloc_zero(r, struct junction_map);
223 if (junction == NULL) {
224 return NT_STATUS_NO_MEMORY;
227 /* The following call can change cwd. */
228 status = get_referred_path(r, pathnamep,
229 handle->conn->sconn->remote_address,
230 handle->conn->sconn->local_address,
231 !handle->conn->sconn->using_smb2,
232 junction, &consumedcnt, &self_referral);
233 if (!NT_STATUS_IS_OK(status)) {
234 struct smb_filename connectpath_fname = {
235 .base_name = handle->conn->connectpath
237 vfs_ChDir(handle->conn, &connectpath_fname);
241 struct smb_filename connectpath_fname = {
242 .base_name = handle->conn->connectpath
244 vfs_ChDir(handle->conn, &connectpath_fname);
247 if (!self_referral) {
248 pathnamep[consumedcnt] = '\0';
251 dbgtext("Path %s to alternate path(s):",
253 for (i=0; i < junction->referral_count; i++) {
255 junction->referral_list[i].alternate_path);
261 if (r->in.req.max_referral_level <= 2) {
262 max_referral_level = 2;
264 if (r->in.req.max_referral_level >= 3) {
265 max_referral_level = 3;
268 r->out.resp = talloc_zero(r, struct dfs_referral_resp);
269 if (r->out.resp == NULL) {
270 return NT_STATUS_NO_MEMORY;
273 r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
274 r->out.resp->nb_referrals = junction->referral_count;
276 r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
278 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
281 r->out.resp->referral_entries = talloc_zero_array(r,
282 struct dfs_referral_type,
283 r->out.resp->nb_referrals);
284 if (r->out.resp->referral_entries == NULL) {
285 return NT_STATUS_NO_MEMORY;
288 switch (max_referral_level) {
290 for(i=0; i < junction->referral_count; i++) {
291 struct referral *ref = &junction->referral_list[i];
292 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
293 struct dfs_referral_type *t =
294 &r->out.resp->referral_entries[i];
295 struct dfs_referral_v2 *v2 = &t->referral.v2;
298 v2->size = VERSION2_REFERRAL_SIZE;
300 v2->server_type = DFS_SERVER_ROOT;
302 v2->server_type = DFS_SERVER_NON_ROOT;
305 v2->proximity = ref->proximity;
307 v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
308 if (v2->DFS_path == NULL) {
309 return NT_STATUS_NO_MEMORY;
311 v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
312 if (v2->DFS_alt_path == NULL) {
313 return NT_STATUS_NO_MEMORY;
315 v2->netw_address = talloc_strdup(mem_ctx,
316 ref->alternate_path);
317 if (v2->netw_address == NULL) {
318 return NT_STATUS_NO_MEMORY;
324 for(i=0; i < junction->referral_count; i++) {
325 struct referral *ref = &junction->referral_list[i];
326 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
327 struct dfs_referral_type *t =
328 &r->out.resp->referral_entries[i];
329 struct dfs_referral_v3 *v3 = &t->referral.v3;
330 struct dfs_normal_referral *r1 = &v3->referrals.r1;
333 v3->size = VERSION3_REFERRAL_SIZE;
335 v3->server_type = DFS_SERVER_ROOT;
337 v3->server_type = DFS_SERVER_NON_ROOT;
341 r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
342 if (r1->DFS_path == NULL) {
343 return NT_STATUS_NO_MEMORY;
345 r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
346 if (r1->DFS_alt_path == NULL) {
347 return NT_STATUS_NO_MEMORY;
349 r1->netw_address = talloc_strdup(mem_ctx,
350 ref->alternate_path);
351 if (r1->netw_address == NULL) {
352 return NT_STATUS_NO_MEMORY;
357 DEBUG(0,("Invalid dfs referral version: %d\n",
358 max_referral_level));
359 return NT_STATUS_INVALID_LEVEL;
363 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
369 static NTSTATUS vfswrap_snap_check_path(struct vfs_handle_struct *handle,
371 const char *service_path,
374 return NT_STATUS_NOT_SUPPORTED;
377 static NTSTATUS vfswrap_snap_create(struct vfs_handle_struct *handle,
379 const char *base_volume,
385 return NT_STATUS_NOT_SUPPORTED;
388 static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle,
393 return NT_STATUS_NOT_SUPPORTED;
396 /* Directory operations */
398 static DIR *vfswrap_opendir(vfs_handle_struct *handle,
399 const struct smb_filename *smb_fname,
405 START_PROFILE(syscall_opendir);
406 result = opendir(smb_fname->base_name);
407 END_PROFILE(syscall_opendir);
411 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
418 START_PROFILE(syscall_fdopendir);
419 result = sys_fdopendir(fsp->fh->fd);
420 END_PROFILE(syscall_fdopendir);
425 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
427 SMB_STRUCT_STAT *sbuf)
429 struct dirent *result;
431 START_PROFILE(syscall_readdir);
432 result = readdir(dirp);
433 END_PROFILE(syscall_readdir);
435 /* Default Posix readdir() does not give us stat info.
436 * Set to invalid to indicate we didn't return this info. */
437 SET_STAT_INVALID(*sbuf);
438 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
439 if (result != NULL) {
440 /* See if we can efficiently return this. */
442 int flags = AT_SYMLINK_NOFOLLOW;
443 int ret = fstatat(dirfd(dirp),
448 * As this is an optimization,
449 * ignore it if we stat'ed a
450 * symlink. Make the caller
451 * do it again as we don't
452 * know if they wanted the link
453 * info, or its target info.
455 if ((ret == 0) && (!S_ISLNK(st.st_mode))) {
456 init_stat_ex_from_stat(sbuf,
458 lp_fake_directory_create_times(
459 SNUM(handle->conn)));
467 static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
468 const struct smb_filename *fname,
470 struct readdir_attr_data **attr_data)
472 return NT_STATUS_NOT_SUPPORTED;
475 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
477 START_PROFILE(syscall_seekdir);
478 seekdir(dirp, offset);
479 END_PROFILE(syscall_seekdir);
482 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
485 START_PROFILE(syscall_telldir);
486 result = telldir(dirp);
487 END_PROFILE(syscall_telldir);
491 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
493 START_PROFILE(syscall_rewinddir);
495 END_PROFILE(syscall_rewinddir);
498 static int vfswrap_mkdirat(vfs_handle_struct *handle,
499 struct files_struct *dirfsp,
500 const struct smb_filename *smb_fname,
504 const char *path = smb_fname->base_name;
507 START_PROFILE(syscall_mkdirat);
509 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
511 if (lp_inherit_acls(SNUM(handle->conn))
512 && parent_dirname(talloc_tos(), path, &parent, NULL)
513 && directory_has_default_acl(handle->conn, parent)) {
514 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
519 result = mkdirat(dirfsp->fh->fd, path, mode);
521 END_PROFILE(syscall_mkdirat);
525 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
529 START_PROFILE(syscall_closedir);
530 result = closedir(dirp);
531 END_PROFILE(syscall_closedir);
535 /* File operations */
537 static int vfswrap_open(vfs_handle_struct *handle,
538 struct smb_filename *smb_fname,
539 files_struct *fsp, int flags, mode_t mode)
543 START_PROFILE(syscall_open);
545 if (is_named_stream(smb_fname)) {
550 result = open(smb_fname->base_name, flags, mode);
552 END_PROFILE(syscall_open);
556 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
557 struct smb_request *req,
558 uint16_t root_dir_fid,
559 struct smb_filename *smb_fname,
560 uint32_t access_mask,
561 uint32_t share_access,
562 uint32_t create_disposition,
563 uint32_t create_options,
564 uint32_t file_attributes,
565 uint32_t oplock_request,
566 const struct smb2_lease *lease,
567 uint64_t allocation_size,
568 uint32_t private_flags,
569 struct security_descriptor *sd,
570 struct ea_list *ea_list,
571 files_struct **result,
573 const struct smb2_create_blobs *in_context_blobs,
574 struct smb2_create_blobs *out_context_blobs)
576 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
577 access_mask, share_access,
578 create_disposition, create_options,
579 file_attributes, oplock_request, lease,
580 allocation_size, private_flags,
582 pinfo, in_context_blobs, out_context_blobs);
585 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
589 START_PROFILE(syscall_close);
590 result = fd_close_posix(fsp);
591 END_PROFILE(syscall_close);
595 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
596 size_t n, off_t offset)
600 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
601 START_PROFILE_BYTES(syscall_pread, n);
602 result = sys_pread(fsp->fh->fd, data, n, offset);
603 END_PROFILE_BYTES(syscall_pread);
605 if (result == -1 && errno == ESPIPE) {
606 /* Maintain the fiction that pipes can be seeked (sought?) on. */
607 result = sys_read(fsp->fh->fd, data, n);
611 #else /* HAVE_PREAD */
614 #endif /* HAVE_PREAD */
619 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
620 size_t n, off_t offset)
624 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
625 START_PROFILE_BYTES(syscall_pwrite, n);
626 result = sys_pwrite(fsp->fh->fd, data, n, offset);
627 END_PROFILE_BYTES(syscall_pwrite);
629 if (result == -1 && errno == ESPIPE) {
630 /* Maintain the fiction that pipes can be sought on. */
631 result = sys_write(fsp->fh->fd, data, n);
634 #else /* HAVE_PWRITE */
637 #endif /* HAVE_PWRITE */
642 struct vfswrap_pread_state {
649 struct vfs_aio_state vfs_aio_state;
650 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
653 static void vfs_pread_do(void *private_data);
654 static void vfs_pread_done(struct tevent_req *subreq);
655 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state);
657 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
659 struct tevent_context *ev,
660 struct files_struct *fsp,
662 size_t n, off_t offset)
664 struct tevent_req *req, *subreq;
665 struct vfswrap_pread_state *state;
667 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
673 state->fd = fsp->fh->fd;
676 state->offset = offset;
678 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
679 state->profile_bytes, n);
680 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
682 subreq = pthreadpool_tevent_job_send(
683 state, ev, handle->conn->sconn->pool,
684 vfs_pread_do, state);
685 if (tevent_req_nomem(subreq, req)) {
686 return tevent_req_post(req, ev);
688 tevent_req_set_callback(subreq, vfs_pread_done, req);
690 talloc_set_destructor(state, vfs_pread_state_destructor);
695 static void vfs_pread_do(void *private_data)
697 struct vfswrap_pread_state *state = talloc_get_type_abort(
698 private_data, struct vfswrap_pread_state);
699 struct timespec start_time;
700 struct timespec end_time;
702 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
704 PROFILE_TIMESTAMP(&start_time);
707 state->ret = pread(state->fd, state->buf, state->count,
709 } while ((state->ret == -1) && (errno == EINTR));
711 if (state->ret == -1) {
712 state->vfs_aio_state.error = errno;
715 PROFILE_TIMESTAMP(&end_time);
717 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
719 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
722 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state)
727 static void vfs_pread_done(struct tevent_req *subreq)
729 struct tevent_req *req = tevent_req_callback_data(
730 subreq, struct tevent_req);
731 struct vfswrap_pread_state *state = tevent_req_data(
732 req, struct vfswrap_pread_state);
735 ret = pthreadpool_tevent_job_recv(subreq);
737 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
738 talloc_set_destructor(state, NULL);
741 tevent_req_error(req, ret);
745 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
746 * means the lower level pthreadpool failed to create a new
747 * thread. Fallback to sync processing in that case to allow
748 * some progress for the client.
753 tevent_req_done(req);
756 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
757 struct vfs_aio_state *vfs_aio_state)
759 struct vfswrap_pread_state *state = tevent_req_data(
760 req, struct vfswrap_pread_state);
762 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
766 *vfs_aio_state = state->vfs_aio_state;
770 struct vfswrap_pwrite_state {
777 struct vfs_aio_state vfs_aio_state;
778 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
781 static void vfs_pwrite_do(void *private_data);
782 static void vfs_pwrite_done(struct tevent_req *subreq);
783 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state);
785 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
787 struct tevent_context *ev,
788 struct files_struct *fsp,
790 size_t n, off_t offset)
792 struct tevent_req *req, *subreq;
793 struct vfswrap_pwrite_state *state;
795 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
801 state->fd = fsp->fh->fd;
804 state->offset = offset;
806 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
807 state->profile_bytes, n);
808 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
810 subreq = pthreadpool_tevent_job_send(
811 state, ev, handle->conn->sconn->pool,
812 vfs_pwrite_do, state);
813 if (tevent_req_nomem(subreq, req)) {
814 return tevent_req_post(req, ev);
816 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
818 talloc_set_destructor(state, vfs_pwrite_state_destructor);
823 static void vfs_pwrite_do(void *private_data)
825 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
826 private_data, struct vfswrap_pwrite_state);
827 struct timespec start_time;
828 struct timespec end_time;
830 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
832 PROFILE_TIMESTAMP(&start_time);
835 state->ret = pwrite(state->fd, state->buf, state->count,
837 } while ((state->ret == -1) && (errno == EINTR));
839 if (state->ret == -1) {
840 state->vfs_aio_state.error = errno;
843 PROFILE_TIMESTAMP(&end_time);
845 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
847 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
850 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state)
855 static void vfs_pwrite_done(struct tevent_req *subreq)
857 struct tevent_req *req = tevent_req_callback_data(
858 subreq, struct tevent_req);
859 struct vfswrap_pwrite_state *state = tevent_req_data(
860 req, struct vfswrap_pwrite_state);
863 ret = pthreadpool_tevent_job_recv(subreq);
865 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
866 talloc_set_destructor(state, NULL);
869 tevent_req_error(req, ret);
873 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
874 * means the lower level pthreadpool failed to create a new
875 * thread. Fallback to sync processing in that case to allow
876 * some progress for the client.
878 vfs_pwrite_do(state);
881 tevent_req_done(req);
884 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
885 struct vfs_aio_state *vfs_aio_state)
887 struct vfswrap_pwrite_state *state = tevent_req_data(
888 req, struct vfswrap_pwrite_state);
890 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
894 *vfs_aio_state = state->vfs_aio_state;
898 struct vfswrap_fsync_state {
902 struct vfs_aio_state vfs_aio_state;
903 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
906 static void vfs_fsync_do(void *private_data);
907 static void vfs_fsync_done(struct tevent_req *subreq);
908 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state);
910 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
912 struct tevent_context *ev,
913 struct files_struct *fsp)
915 struct tevent_req *req, *subreq;
916 struct vfswrap_fsync_state *state;
918 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
924 state->fd = fsp->fh->fd;
926 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_fsync, profile_p,
927 state->profile_bytes, 0);
928 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
930 subreq = pthreadpool_tevent_job_send(
931 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
932 if (tevent_req_nomem(subreq, req)) {
933 return tevent_req_post(req, ev);
935 tevent_req_set_callback(subreq, vfs_fsync_done, req);
937 talloc_set_destructor(state, vfs_fsync_state_destructor);
942 static void vfs_fsync_do(void *private_data)
944 struct vfswrap_fsync_state *state = talloc_get_type_abort(
945 private_data, struct vfswrap_fsync_state);
946 struct timespec start_time;
947 struct timespec end_time;
949 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
951 PROFILE_TIMESTAMP(&start_time);
954 state->ret = fsync(state->fd);
955 } while ((state->ret == -1) && (errno == EINTR));
957 if (state->ret == -1) {
958 state->vfs_aio_state.error = errno;
961 PROFILE_TIMESTAMP(&end_time);
963 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
965 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
968 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state)
973 static void vfs_fsync_done(struct tevent_req *subreq)
975 struct tevent_req *req = tevent_req_callback_data(
976 subreq, struct tevent_req);
977 struct vfswrap_fsync_state *state = tevent_req_data(
978 req, struct vfswrap_fsync_state);
981 ret = pthreadpool_tevent_job_recv(subreq);
983 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
984 talloc_set_destructor(state, NULL);
987 tevent_req_error(req, ret);
991 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
992 * means the lower level pthreadpool failed to create a new
993 * thread. Fallback to sync processing in that case to allow
994 * some progress for the client.
999 tevent_req_done(req);
1002 static int vfswrap_fsync_recv(struct tevent_req *req,
1003 struct vfs_aio_state *vfs_aio_state)
1005 struct vfswrap_fsync_state *state = tevent_req_data(
1006 req, struct vfswrap_fsync_state);
1008 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1012 *vfs_aio_state = state->vfs_aio_state;
1016 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1020 START_PROFILE(syscall_lseek);
1022 result = lseek(fsp->fh->fd, offset, whence);
1024 * We want to maintain the fiction that we can seek
1025 * on a fifo for file system purposes. This allows
1026 * people to set up UNIX fifo's that feed data to Windows
1027 * applications. JRA.
1030 if((result == -1) && (errno == ESPIPE)) {
1035 END_PROFILE(syscall_lseek);
1039 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1040 off_t offset, size_t n)
1044 START_PROFILE_BYTES(syscall_sendfile, n);
1045 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
1046 END_PROFILE_BYTES(syscall_sendfile);
1050 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1052 files_struct *tofsp,
1058 START_PROFILE_BYTES(syscall_recvfile, n);
1059 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
1060 END_PROFILE_BYTES(syscall_recvfile);
1064 static int vfswrap_renameat(vfs_handle_struct *handle,
1065 files_struct *srcfsp,
1066 const struct smb_filename *smb_fname_src,
1067 files_struct *dstfsp,
1068 const struct smb_filename *smb_fname_dst)
1072 START_PROFILE(syscall_renameat);
1074 if (is_named_stream(smb_fname_src) || is_named_stream(smb_fname_dst)) {
1079 result = renameat(srcfsp->fh->fd,
1080 smb_fname_src->base_name,
1082 smb_fname_dst->base_name);
1085 END_PROFILE(syscall_renameat);
1089 static int vfswrap_stat(vfs_handle_struct *handle,
1090 struct smb_filename *smb_fname)
1094 START_PROFILE(syscall_stat);
1096 if (is_named_stream(smb_fname)) {
1101 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1102 lp_fake_directory_create_times(SNUM(handle->conn)));
1104 END_PROFILE(syscall_stat);
1108 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1112 START_PROFILE(syscall_fstat);
1113 result = sys_fstat(fsp->fh->fd,
1114 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1115 END_PROFILE(syscall_fstat);
1119 static int vfswrap_lstat(vfs_handle_struct *handle,
1120 struct smb_filename *smb_fname)
1124 START_PROFILE(syscall_lstat);
1126 if (is_named_stream(smb_fname)) {
1131 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1132 lp_fake_directory_create_times(SNUM(handle->conn)));
1134 END_PROFILE(syscall_lstat);
1138 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1140 enum vfs_translate_direction direction,
1141 TALLOC_CTX *mem_ctx,
1144 return NT_STATUS_NONE_MAPPED;
1148 * Implement the default fsctl operation.
1150 static bool vfswrap_logged_ioctl_message = false;
1152 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1153 struct files_struct *fsp,
1156 uint16_t req_flags, /* Needed for UNICODE ... */
1157 const uint8_t *_in_data,
1159 uint8_t **_out_data,
1160 uint32_t max_out_len,
1163 const char *in_data = (const char *)_in_data;
1164 char **out_data = (char **)_out_data;
1168 case FSCTL_SET_SPARSE:
1170 bool set_sparse = true;
1172 if (in_len >= 1 && in_data[0] == 0) {
1176 status = file_set_sparse(handle->conn, fsp, set_sparse);
1178 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1179 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1180 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1181 nt_errstr(status)));
1186 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1188 unsigned char objid[16];
1189 char *return_data = NULL;
1191 /* This should return the object-id on this file.
1192 * I think I'll make this be the inode+dev. JRA.
1195 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1196 fsp_fnum_dbg(fsp)));
1198 *out_len = MIN(max_out_len, 64);
1200 /* Hmmm, will this cause problems if less data asked for? */
1201 return_data = talloc_array(ctx, char, 64);
1202 if (return_data == NULL) {
1203 return NT_STATUS_NO_MEMORY;
1206 /* For backwards compatibility only store the dev/inode. */
1207 push_file_id_16(return_data, &fsp->file_id);
1208 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1209 push_file_id_16(return_data+32, &fsp->file_id);
1210 memset(return_data+48, 0, 16);
1211 *out_data = return_data;
1212 return NT_STATUS_OK;
1215 case FSCTL_GET_REPARSE_POINT:
1217 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1218 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1219 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1220 return NT_STATUS_NOT_A_REPARSE_POINT;
1223 case FSCTL_SET_REPARSE_POINT:
1225 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1226 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1227 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1228 return NT_STATUS_NOT_A_REPARSE_POINT;
1231 case FSCTL_GET_SHADOW_COPY_DATA:
1234 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1235 * and return their volume names. If max_data_count is 16, then it is just
1236 * asking for the number of volumes and length of the combined names.
1238 * pdata is the data allocated by our caller, but that uses
1239 * total_data_count (which is 0 in our case) rather than max_data_count.
1240 * Allocate the correct amount and return the pointer to let
1241 * it be deallocated when we return.
1243 struct shadow_copy_data *shadow_data = NULL;
1244 bool labels = False;
1245 uint32_t labels_data_count = 0;
1247 char *cur_pdata = NULL;
1249 if (max_out_len < 16) {
1250 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1252 return NT_STATUS_INVALID_PARAMETER;
1255 if (max_out_len > 16) {
1259 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1260 if (shadow_data == NULL) {
1261 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1262 return NT_STATUS_NO_MEMORY;
1266 * Call the VFS routine to actually do the work.
1268 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1271 /* broken module didn't set errno on error */
1272 status = NT_STATUS_UNSUCCESSFUL;
1274 status = map_nt_error_from_unix(errno);
1275 if (NT_STATUS_EQUAL(status,
1276 NT_STATUS_NOT_SUPPORTED)) {
1280 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1281 "connectpath %s, failed - %s.\n",
1282 fsp->conn->connectpath,
1283 nt_errstr(status)));
1284 TALLOC_FREE(shadow_data);
1288 labels_data_count = (shadow_data->num_volumes * 2 *
1289 sizeof(SHADOW_COPY_LABEL)) + 2;
1294 *out_len = 12 + labels_data_count;
1297 if (max_out_len < *out_len) {
1298 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1299 max_out_len, *out_len));
1300 TALLOC_FREE(shadow_data);
1301 return NT_STATUS_BUFFER_TOO_SMALL;
1304 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1305 if (cur_pdata == NULL) {
1306 TALLOC_FREE(shadow_data);
1307 return NT_STATUS_NO_MEMORY;
1310 *out_data = cur_pdata;
1312 /* num_volumes 4 bytes */
1313 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1316 /* num_labels 4 bytes */
1317 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1320 /* needed_data_count 4 bytes */
1321 SIVAL(cur_pdata, 8, labels_data_count);
1325 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1326 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1327 if (labels && shadow_data->labels) {
1328 for (i=0; i<shadow_data->num_volumes; i++) {
1330 status = srvstr_push(cur_pdata, req_flags,
1331 cur_pdata, shadow_data->labels[i],
1332 2 * sizeof(SHADOW_COPY_LABEL),
1333 STR_UNICODE|STR_TERMINATE, &len);
1334 if (!NT_STATUS_IS_OK(status)) {
1335 TALLOC_FREE(*out_data);
1336 TALLOC_FREE(shadow_data);
1339 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1340 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1344 TALLOC_FREE(shadow_data);
1346 return NT_STATUS_OK;
1349 case FSCTL_FIND_FILES_BY_SID:
1351 /* pretend this succeeded -
1353 * we have to send back a list with all files owned by this SID
1355 * but I have to check that --metze
1359 struct dom_sid_buf buf;
1363 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1364 fsp_fnum_dbg(fsp)));
1367 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1368 return NT_STATUS_INVALID_PARAMETER;
1371 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1373 /* unknown 4 bytes: this is not the length of the sid :-( */
1374 /*unknown = IVAL(pdata,0);*/
1376 ret = sid_parse(_in_data + 4, sid_len, &sid);
1378 return NT_STATUS_INVALID_PARAMETER;
1380 DEBUGADD(10, ("for SID: %s\n",
1381 dom_sid_str_buf(&sid, &buf)));
1383 if (!sid_to_uid(&sid, &uid)) {
1384 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1385 dom_sid_str_buf(&sid, &buf),
1386 (unsigned long)sid_len));
1390 /* we can take a look at the find source :-)
1392 * find ./ -uid $uid -name '*' is what we need here
1395 * and send 4bytes len and then NULL terminated unicode strings
1398 * but I don't know how to deal with the paged results
1399 * (maybe we can hang the result anywhere in the fsp struct)
1401 * but I don't know how to deal with the paged results
1402 * (maybe we can hang the result anywhere in the fsp struct)
1404 * we don't send all files at once
1405 * and at the next we should *not* start from the beginning,
1406 * so we have to cache the result
1411 /* this works for now... */
1412 return NT_STATUS_OK;
1415 case FSCTL_QUERY_ALLOCATED_RANGES:
1417 /* FIXME: This is just a dummy reply, telling that all of the
1418 * file is allocated. MKS cp needs that.
1419 * Adding the real allocated ranges via FIEMAP on Linux
1420 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1421 * this FSCTL correct for sparse files.
1423 uint64_t offset, length;
1424 char *out_data_tmp = NULL;
1427 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1429 return NT_STATUS_INVALID_PARAMETER;
1432 if (max_out_len < 16) {
1433 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1435 return NT_STATUS_INVALID_PARAMETER;
1438 offset = BVAL(in_data,0);
1439 length = BVAL(in_data,8);
1441 if (offset + length < offset) {
1442 /* No 64-bit integer wrap. */
1443 return NT_STATUS_INVALID_PARAMETER;
1446 /* Shouldn't this be SMB_VFS_STAT ... ? */
1447 status = vfs_stat_fsp(fsp);
1448 if (!NT_STATUS_IS_OK(status)) {
1453 out_data_tmp = talloc_array(ctx, char, *out_len);
1454 if (out_data_tmp == NULL) {
1455 DEBUG(10, ("unable to allocate memory for response\n"));
1456 return NT_STATUS_NO_MEMORY;
1459 if (offset > fsp->fsp_name->st.st_ex_size ||
1460 fsp->fsp_name->st.st_ex_size == 0 ||
1462 memset(out_data_tmp, 0, *out_len);
1464 uint64_t end = offset + length;
1465 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1466 SBVAL(out_data_tmp, 0, 0);
1467 SBVAL(out_data_tmp, 8, end);
1470 *out_data = out_data_tmp;
1472 return NT_STATUS_OK;
1475 case FSCTL_IS_VOLUME_DIRTY:
1477 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1478 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1480 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1481 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1483 return NT_STATUS_INVALID_PARAMETER;
1488 * Only print once ... unfortunately there could be lots of
1489 * different FSCTLs that are called.
1491 if (!vfswrap_logged_ioctl_message) {
1492 vfswrap_logged_ioctl_message = true;
1493 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1494 __func__, function));
1498 return NT_STATUS_NOT_SUPPORTED;
1501 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
1502 const struct smb_filename *fname,
1503 SMB_STRUCT_STAT *sbuf);
1505 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1506 struct smb_filename *smb_fname,
1511 offline = vfswrap_is_offline(handle, smb_fname, &smb_fname->st);
1513 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1516 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1519 struct vfswrap_get_dos_attributes_state {
1520 struct vfs_aio_state aio_state;
1521 connection_struct *conn;
1522 TALLOC_CTX *mem_ctx;
1523 struct tevent_context *ev;
1524 files_struct *dir_fsp;
1525 struct smb_filename *smb_fname;
1530 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq);
1532 static struct tevent_req *vfswrap_get_dos_attributes_send(
1533 TALLOC_CTX *mem_ctx,
1534 struct tevent_context *ev,
1535 struct vfs_handle_struct *handle,
1536 files_struct *dir_fsp,
1537 struct smb_filename *smb_fname)
1539 struct tevent_req *req = NULL;
1540 struct tevent_req *subreq = NULL;
1541 struct vfswrap_get_dos_attributes_state *state = NULL;
1543 req = tevent_req_create(mem_ctx, &state,
1544 struct vfswrap_get_dos_attributes_state);
1549 *state = (struct vfswrap_get_dos_attributes_state) {
1550 .conn = dir_fsp->conn,
1554 .smb_fname = smb_fname,
1557 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1561 SAMBA_XATTR_DOS_ATTRIB,
1563 if (tevent_req_nomem(subreq, req)) {
1564 return tevent_req_post(req, ev);
1566 tevent_req_set_callback(subreq,
1567 vfswrap_get_dos_attributes_getxattr_done,
1573 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq)
1575 struct tevent_req *req =
1576 tevent_req_callback_data(subreq,
1578 struct vfswrap_get_dos_attributes_state *state =
1579 tevent_req_data(req,
1580 struct vfswrap_get_dos_attributes_state);
1582 DATA_BLOB blob = {0};
1585 xattr_size = SMB_VFS_GETXATTRAT_RECV(subreq,
1589 TALLOC_FREE(subreq);
1590 if (xattr_size == -1) {
1591 status = map_nt_error_from_unix(state->aio_state.error);
1593 if (state->as_root) {
1594 tevent_req_nterror(req, status);
1597 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1598 tevent_req_nterror(req, status);
1602 state->as_root = true;
1605 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1609 SAMBA_XATTR_DOS_ATTRIB,
1612 if (tevent_req_nomem(subreq, req)) {
1615 tevent_req_set_callback(subreq,
1616 vfswrap_get_dos_attributes_getxattr_done,
1621 blob.length = xattr_size;
1623 status = parse_dos_attribute_blob(state->smb_fname,
1626 if (!NT_STATUS_IS_OK(status)) {
1627 tevent_req_nterror(req, status);
1631 tevent_req_done(req);
1635 static NTSTATUS vfswrap_get_dos_attributes_recv(struct tevent_req *req,
1636 struct vfs_aio_state *aio_state,
1639 struct vfswrap_get_dos_attributes_state *state =
1640 tevent_req_data(req,
1641 struct vfswrap_get_dos_attributes_state);
1644 if (tevent_req_is_nterror(req, &status)) {
1645 tevent_req_received(req);
1649 *aio_state = state->aio_state;
1650 *dosmode = state->dosmode;
1651 tevent_req_received(req);
1652 return NT_STATUS_OK;
1655 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1656 struct files_struct *fsp,
1661 offline = vfswrap_is_offline(handle, fsp->fsp_name, &fsp->fsp_name->st);
1663 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1666 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1669 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1670 const struct smb_filename *smb_fname,
1673 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1676 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1677 struct files_struct *fsp,
1680 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1683 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1685 struct vfswrap_offload_read_state {
1689 static struct tevent_req *vfswrap_offload_read_send(
1690 TALLOC_CTX *mem_ctx,
1691 struct tevent_context *ev,
1692 struct vfs_handle_struct *handle,
1693 struct files_struct *fsp,
1699 struct tevent_req *req = NULL;
1700 struct vfswrap_offload_read_state *state = NULL;
1703 req = tevent_req_create(mem_ctx, &state,
1704 struct vfswrap_offload_read_state);
1709 status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1710 &vfswrap_offload_ctx);
1711 if (tevent_req_nterror(req, status)) {
1712 return tevent_req_post(req, ev);
1715 if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1716 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1717 return tevent_req_post(req, ev);
1720 status = vfs_offload_token_create_blob(state, fsp, fsctl,
1722 if (tevent_req_nterror(req, status)) {
1723 return tevent_req_post(req, ev);
1726 status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1728 if (tevent_req_nterror(req, status)) {
1729 return tevent_req_post(req, ev);
1732 tevent_req_done(req);
1733 return tevent_req_post(req, ev);
1736 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
1737 struct vfs_handle_struct *handle,
1738 TALLOC_CTX *mem_ctx,
1741 struct vfswrap_offload_read_state *state = tevent_req_data(
1742 req, struct vfswrap_offload_read_state);
1745 if (tevent_req_is_nterror(req, &status)) {
1746 tevent_req_received(req);
1750 token->length = state->token.length;
1751 token->data = talloc_move(mem_ctx, &state->token.data);
1753 tevent_req_received(req);
1754 return NT_STATUS_OK;
1757 struct vfswrap_offload_write_state {
1759 bool read_lck_locked;
1760 bool write_lck_locked;
1762 struct tevent_context *src_ev;
1763 struct files_struct *src_fsp;
1765 struct tevent_context *dst_ev;
1766 struct files_struct *dst_fsp;
1770 size_t next_io_size;
1773 static void vfswrap_offload_write_cleanup(struct tevent_req *req,
1774 enum tevent_req_state req_state)
1776 struct vfswrap_offload_write_state *state = tevent_req_data(
1777 req, struct vfswrap_offload_write_state);
1780 if (state->dst_fsp == NULL) {
1784 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
1786 state->dst_fsp = NULL;
1789 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
1791 static struct tevent_req *vfswrap_offload_write_send(
1792 struct vfs_handle_struct *handle,
1793 TALLOC_CTX *mem_ctx,
1794 struct tevent_context *ev,
1797 off_t transfer_offset,
1798 struct files_struct *dest_fsp,
1802 struct tevent_req *req;
1803 struct vfswrap_offload_write_state *state = NULL;
1804 /* off_t is signed! */
1805 off_t max_offset = INT64_MAX - to_copy;
1806 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
1807 files_struct *src_fsp = NULL;
1811 req = tevent_req_create(mem_ctx, &state,
1812 struct vfswrap_offload_write_state);
1817 *state = (struct vfswrap_offload_write_state) {
1819 .src_off = transfer_offset,
1821 .dst_fsp = dest_fsp,
1822 .dst_off = dest_off,
1824 .remaining = to_copy,
1827 tevent_req_set_cleanup_fn(req, vfswrap_offload_write_cleanup);
1830 case FSCTL_SRV_COPYCHUNK:
1831 case FSCTL_SRV_COPYCHUNK_WRITE:
1834 case FSCTL_OFFLOAD_WRITE:
1835 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
1836 return tevent_req_post(req, ev);
1838 case FSCTL_DUP_EXTENTS_TO_FILE:
1839 DBG_DEBUG("COW clones not supported by vfs_default\n");
1840 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1841 return tevent_req_post(req, ev);
1844 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1845 return tevent_req_post(req, ev);
1849 * From here on we assume a copy-chunk fsctl
1853 tevent_req_done(req);
1854 return tevent_req_post(req, ev);
1857 if (state->src_off > max_offset) {
1859 * Protect integer checks below.
1861 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1862 return tevent_req_post(req, ev);
1864 if (state->src_off < 0) {
1866 * Protect integer checks below.
1868 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1869 return tevent_req_post(req, ev);
1871 if (state->dst_off > max_offset) {
1873 * Protect integer checks below.
1875 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1876 return tevent_req_post(req, ev);
1878 if (state->dst_off < 0) {
1880 * Protect integer checks below.
1882 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1883 return tevent_req_post(req, ev);
1886 status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
1888 if (tevent_req_nterror(req, status)) {
1889 return tevent_req_post(req, ev);
1892 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
1894 status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
1895 if (!NT_STATUS_IS_OK(status)) {
1896 tevent_req_nterror(req, status);
1897 return tevent_req_post(req, ev);
1900 ok = change_to_user_and_service_by_fsp(src_fsp);
1902 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1903 return tevent_req_post(req, ev);
1906 state->src_ev = src_fsp->conn->sconn->ev_ctx;
1907 state->src_fsp = src_fsp;
1909 status = vfs_stat_fsp(src_fsp);
1910 if (tevent_req_nterror(req, status)) {
1911 return tevent_req_post(req, ev);
1914 if (src_fsp->fsp_name->st.st_ex_size < state->src_off + to_copy) {
1916 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1917 * If the SourceOffset or SourceOffset + Length extends beyond
1918 * the end of file, the server SHOULD<240> treat this as a
1919 * STATUS_END_OF_FILE error.
1921 * <240> Section 3.3.5.15.6: Windows servers will return
1922 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1924 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1925 return tevent_req_post(req, ev);
1928 state->buf = talloc_array(state, uint8_t, num);
1929 if (tevent_req_nomem(state->buf, req)) {
1930 return tevent_req_post(req, ev);
1933 status = vfswrap_offload_write_loop(req);
1934 if (!NT_STATUS_IS_OK(status)) {
1935 tevent_req_nterror(req, status);
1936 return tevent_req_post(req, ev);
1942 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
1944 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
1946 struct vfswrap_offload_write_state *state = tevent_req_data(
1947 req, struct vfswrap_offload_write_state);
1948 struct tevent_req *subreq = NULL;
1949 struct lock_struct read_lck;
1953 * This is called under the context of state->src_fsp.
1956 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
1958 init_strict_lock_struct(state->src_fsp,
1959 state->src_fsp->op->global->open_persistent_id,
1961 state->next_io_size,
1965 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
1969 return NT_STATUS_FILE_LOCK_CONFLICT;
1972 subreq = SMB_VFS_PREAD_SEND(state,
1976 state->next_io_size,
1978 if (subreq == NULL) {
1979 return NT_STATUS_NO_MEMORY;
1981 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
1983 return NT_STATUS_OK;
1986 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
1988 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
1990 struct tevent_req *req = tevent_req_callback_data(
1991 subreq, struct tevent_req);
1992 struct vfswrap_offload_write_state *state = tevent_req_data(
1993 req, struct vfswrap_offload_write_state);
1994 struct vfs_aio_state aio_state;
1995 struct lock_struct write_lck;
1999 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
2000 TALLOC_FREE(subreq);
2002 DBG_ERR("read failed: %s\n", strerror(aio_state.error));
2003 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2006 if (nread != state->next_io_size) {
2007 DBG_ERR("Short read, only %zd of %zu\n",
2008 nread, state->next_io_size);
2009 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2013 state->src_off += nread;
2015 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2017 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2021 init_strict_lock_struct(state->dst_fsp,
2022 state->dst_fsp->op->global->open_persistent_id,
2024 state->next_io_size,
2028 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
2032 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
2036 subreq = SMB_VFS_PWRITE_SEND(state,
2040 state->next_io_size,
2042 if (subreq == NULL) {
2043 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2046 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
2049 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
2051 struct tevent_req *req = tevent_req_callback_data(
2052 subreq, struct tevent_req);
2053 struct vfswrap_offload_write_state *state = tevent_req_data(
2054 req, struct vfswrap_offload_write_state);
2055 struct vfs_aio_state aio_state;
2060 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
2061 TALLOC_FREE(subreq);
2062 if (nwritten == -1) {
2063 DBG_ERR("write failed: %s\n", strerror(aio_state.error));
2064 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2067 if (nwritten != state->next_io_size) {
2068 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
2069 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2073 state->dst_off += nwritten;
2075 if (state->remaining < nwritten) {
2076 /* Paranoia check */
2077 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2080 state->remaining -= nwritten;
2081 if (state->remaining == 0) {
2082 tevent_req_done(req);
2086 ok = change_to_user_and_service_by_fsp(state->src_fsp);
2088 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2092 status = vfswrap_offload_write_loop(req);
2093 if (!NT_STATUS_IS_OK(status)) {
2094 tevent_req_nterror(req, status);
2101 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
2102 struct tevent_req *req,
2105 struct vfswrap_offload_write_state *state = tevent_req_data(
2106 req, struct vfswrap_offload_write_state);
2109 if (tevent_req_is_nterror(req, &status)) {
2110 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
2112 tevent_req_received(req);
2116 *copied = state->to_copy;
2117 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
2118 tevent_req_received(req);
2120 return NT_STATUS_OK;
2123 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
2124 TALLOC_CTX *mem_ctx,
2125 struct files_struct *fsp,
2126 struct smb_filename *smb_fname,
2127 uint16_t *_compression_fmt)
2129 return NT_STATUS_INVALID_DEVICE_REQUEST;
2132 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
2133 TALLOC_CTX *mem_ctx,
2134 struct files_struct *fsp,
2135 uint16_t compression_fmt)
2137 return NT_STATUS_INVALID_DEVICE_REQUEST;
2140 /********************************************************************
2141 Given a stat buffer return the allocated size on disk, taking into
2142 account sparse files.
2143 ********************************************************************/
2144 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
2145 struct files_struct *fsp,
2146 const SMB_STRUCT_STAT *sbuf)
2150 START_PROFILE(syscall_get_alloc_size);
2152 if(S_ISDIR(sbuf->st_ex_mode)) {
2157 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2158 /* The type of st_blocksize is blkcnt_t which *MUST* be
2159 signed (according to POSIX) and can be less than 64-bits.
2160 Ensure when we're converting to 64 bits wide we don't
2162 #if defined(SIZEOF_BLKCNT_T_8)
2163 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2164 #elif defined(SIZEOF_BLKCNT_T_4)
2166 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2167 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2170 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2174 * Some file systems do not allocate a block for very
2175 * small files. But for non-empty file should report a
2179 uint64_t filesize = get_file_size_stat(sbuf);
2181 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2185 result = get_file_size_stat(sbuf);
2188 if (fsp && fsp->initial_allocation_size)
2189 result = MAX(result,fsp->initial_allocation_size);
2191 result = smb_roundup(handle->conn, result);
2194 END_PROFILE(syscall_get_alloc_size);
2198 static int vfswrap_unlinkat(vfs_handle_struct *handle,
2199 struct files_struct *dirfsp,
2200 const struct smb_filename *smb_fname,
2205 START_PROFILE(syscall_unlinkat);
2207 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2209 if (is_named_stream(smb_fname)) {
2213 result = unlinkat(dirfsp->fh->fd,
2214 smb_fname->base_name,
2218 END_PROFILE(syscall_unlinkat);
2222 static int vfswrap_chmod(vfs_handle_struct *handle,
2223 const struct smb_filename *smb_fname,
2228 START_PROFILE(syscall_chmod);
2229 result = chmod(smb_fname->base_name, mode);
2230 END_PROFILE(syscall_chmod);
2234 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2238 START_PROFILE(syscall_fchmod);
2239 #if defined(HAVE_FCHMOD)
2240 result = fchmod(fsp->fh->fd, mode);
2246 END_PROFILE(syscall_fchmod);
2250 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2255 START_PROFILE(syscall_fchown);
2256 result = fchown(fsp->fh->fd, uid, gid);
2257 END_PROFILE(syscall_fchown);
2265 static int vfswrap_lchown(vfs_handle_struct *handle,
2266 const struct smb_filename *smb_fname,
2272 START_PROFILE(syscall_lchown);
2273 result = lchown(smb_fname->base_name, uid, gid);
2274 END_PROFILE(syscall_lchown);
2278 static int vfswrap_chdir(vfs_handle_struct *handle,
2279 const struct smb_filename *smb_fname)
2283 START_PROFILE(syscall_chdir);
2284 result = chdir(smb_fname->base_name);
2285 END_PROFILE(syscall_chdir);
2289 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2293 struct smb_filename *smb_fname = NULL;
2295 START_PROFILE(syscall_getwd);
2296 result = sys_getwd();
2297 END_PROFILE(syscall_getwd);
2299 if (result == NULL) {
2302 smb_fname = synthetic_smb_fname(ctx,
2308 * sys_getwd() *always* returns malloced memory.
2309 * We must free here to avoid leaks:
2310 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2316 /*********************************************************************
2317 nsec timestamp resolution call. Convert down to whatever the underlying
2318 system will support.
2319 **********************************************************************/
2321 static int vfswrap_ntimes(vfs_handle_struct *handle,
2322 const struct smb_filename *smb_fname,
2323 struct smb_file_time *ft)
2327 START_PROFILE(syscall_ntimes);
2329 if (is_named_stream(smb_fname)) {
2335 if (is_omit_timespec(&ft->atime)) {
2336 ft->atime= smb_fname->st.st_ex_atime;
2339 if (is_omit_timespec(&ft->mtime)) {
2340 ft->mtime = smb_fname->st.st_ex_mtime;
2343 if (!is_omit_timespec(&ft->create_time)) {
2344 set_create_timespec_ea(handle->conn,
2349 if ((timespec_compare(&ft->atime,
2350 &smb_fname->st.st_ex_atime) == 0) &&
2351 (timespec_compare(&ft->mtime,
2352 &smb_fname->st.st_ex_mtime) == 0)) {
2357 #if defined(HAVE_UTIMENSAT)
2359 struct timespec ts[2];
2362 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2364 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2366 if (!((result == -1) && (errno == ENOSYS))) {
2370 #if defined(HAVE_UTIMES)
2372 struct timeval tv[2];
2373 tv[0] = convert_timespec_to_timeval(ft->atime);
2374 tv[1] = convert_timespec_to_timeval(ft->mtime);
2375 result = utimes(smb_fname->base_name, tv);
2377 result = utimes(smb_fname->base_name, NULL);
2379 if (!((result == -1) && (errno == ENOSYS))) {
2383 #if defined(HAVE_UTIME)
2385 struct utimbuf times;
2386 times.actime = convert_timespec_to_time_t(ft->atime);
2387 times.modtime = convert_timespec_to_time_t(ft->mtime);
2388 result = utime(smb_fname->base_name, ×);
2390 result = utime(smb_fname->base_name, NULL);
2392 if (!((result == -1) && (errno == ENOSYS))) {
2400 END_PROFILE(syscall_ntimes);
2404 /*********************************************************************
2405 A version of ftruncate that will write the space on disk if strict
2407 **********************************************************************/
2409 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2411 off_t space_to_write;
2412 uint64_t space_avail;
2413 uint64_t bsize,dfree,dsize;
2416 SMB_STRUCT_STAT *pst;
2418 status = vfs_stat_fsp(fsp);
2419 if (!NT_STATUS_IS_OK(status)) {
2422 pst = &fsp->fsp_name->st;
2425 if (S_ISFIFO(pst->st_ex_mode))
2429 if (pst->st_ex_size == len)
2432 /* Shrink - just ftruncate. */
2433 if (pst->st_ex_size > len)
2434 return ftruncate(fsp->fh->fd, len);
2436 space_to_write = len - pst->st_ex_size;
2438 /* for allocation try fallocate first. This can fail on some
2439 platforms e.g. when the filesystem doesn't support it and no
2440 emulation is being done by the libc (like on AIX with JFS1). In that
2441 case we do our own emulation. fallocate implementations can
2442 return ENOTSUP or EINVAL in cases like that. */
2443 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2444 if (ret == -1 && errno == ENOSPC) {
2450 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2451 "error %d. Falling back to slow manual allocation\n", errno));
2453 /* available disk space is enough or not? */
2455 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2456 /* space_avail is 1k blocks */
2457 if (space_avail == (uint64_t)-1 ||
2458 ((uint64_t)space_to_write/1024 > space_avail) ) {
2463 /* Write out the real space on disk. */
2464 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2472 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2475 SMB_STRUCT_STAT *pst;
2479 START_PROFILE(syscall_ftruncate);
2481 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2482 result = strict_allocate_ftruncate(handle, fsp, len);
2483 END_PROFILE(syscall_ftruncate);
2487 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2488 ftruncate if the system supports it. Then I discovered that
2489 you can have some filesystems that support ftruncate
2490 expansion and some that don't! On Linux fat can't do
2491 ftruncate extend but ext2 can. */
2493 result = ftruncate(fsp->fh->fd, len);
2495 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2496 extend a file with ftruncate. Provide alternate implementation
2499 /* Do an fstat to see if the file is longer than the requested
2500 size in which case the ftruncate above should have
2501 succeeded or shorter, in which case seek to len - 1 and
2502 write 1 byte of zero */
2503 status = vfs_stat_fsp(fsp);
2504 if (!NT_STATUS_IS_OK(status)) {
2508 /* We need to update the files_struct after successful ftruncate */
2513 pst = &fsp->fsp_name->st;
2516 if (S_ISFIFO(pst->st_ex_mode)) {
2522 if (pst->st_ex_size == len) {
2527 if (pst->st_ex_size > len) {
2528 /* the ftruncate should have worked */
2532 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2540 END_PROFILE(syscall_ftruncate);
2544 static int vfswrap_fallocate(vfs_handle_struct *handle,
2552 START_PROFILE(syscall_fallocate);
2554 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2556 * posix_fallocate returns 0 on success, errno on error
2557 * and doesn't set errno. Make it behave like fallocate()
2558 * which returns -1, and sets errno on failure.
2565 /* sys_fallocate handles filtering of unsupported mode flags */
2566 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2568 END_PROFILE(syscall_fallocate);
2572 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2576 START_PROFILE(syscall_fcntl_lock);
2578 if (fsp->use_ofd_locks) {
2579 op = map_process_lock_to_ofd_lock(op);
2582 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2583 END_PROFILE(syscall_fcntl_lock);
2587 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2588 uint32_t share_mode, uint32_t access_mask)
2590 START_PROFILE(syscall_kernel_flock);
2591 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2592 END_PROFILE(syscall_kernel_flock);
2596 static int vfswrap_fcntl(vfs_handle_struct *handle, files_struct *fsp, int cmd,
2600 va_list dup_cmd_arg;
2604 START_PROFILE(syscall_fcntl);
2606 va_copy(dup_cmd_arg, cmd_arg);
2612 #if defined(HAVE_OFD_LOCKS)
2617 #if defined(HAVE_F_OWNER_EX)
2621 #if defined(HAVE_RW_HINTS)
2624 case F_GET_FILE_RW_HINT:
2625 case F_SET_FILE_RW_HINT:
2627 argp = va_arg(dup_cmd_arg, void *);
2628 result = sys_fcntl_ptr(fsp->fh->fd, cmd, argp);
2631 val = va_arg(dup_cmd_arg, int);
2632 result = sys_fcntl_int(fsp->fh->fd, cmd, val);
2635 va_end(dup_cmd_arg);
2637 END_PROFILE(syscall_fcntl);
2641 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2646 START_PROFILE(syscall_fcntl_getlock);
2648 if (fsp->use_ofd_locks) {
2649 op = map_process_lock_to_ofd_lock(op);
2652 result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2653 END_PROFILE(syscall_fcntl_getlock);
2657 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2662 START_PROFILE(syscall_linux_setlease);
2664 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2665 result = linux_setlease(fsp->fh->fd, leasetype);
2669 END_PROFILE(syscall_linux_setlease);
2673 static int vfswrap_symlinkat(vfs_handle_struct *handle,
2674 const char *link_target,
2675 struct files_struct *dirfsp,
2676 const struct smb_filename *new_smb_fname)
2680 START_PROFILE(syscall_symlinkat);
2682 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2684 result = symlinkat(link_target,
2686 new_smb_fname->base_name);
2687 END_PROFILE(syscall_symlinkat);
2691 static int vfswrap_readlinkat(vfs_handle_struct *handle,
2692 files_struct *dirfsp,
2693 const struct smb_filename *smb_fname,
2699 START_PROFILE(syscall_readlinkat);
2701 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2703 result = readlinkat(dirfsp->fh->fd,
2704 smb_fname->base_name,
2708 END_PROFILE(syscall_readlinkat);
2712 static int vfswrap_linkat(vfs_handle_struct *handle,
2713 files_struct *srcfsp,
2714 const struct smb_filename *old_smb_fname,
2715 files_struct *dstfsp,
2716 const struct smb_filename *new_smb_fname,
2721 START_PROFILE(syscall_linkat);
2723 SMB_ASSERT(srcfsp == srcfsp->conn->cwd_fsp);
2724 SMB_ASSERT(dstfsp == dstfsp->conn->cwd_fsp);
2726 result = linkat(srcfsp->fh->fd,
2727 old_smb_fname->base_name,
2729 new_smb_fname->base_name,
2732 END_PROFILE(syscall_linkat);
2736 static int vfswrap_mknodat(vfs_handle_struct *handle,
2737 files_struct *dirfsp,
2738 const struct smb_filename *smb_fname,
2744 START_PROFILE(syscall_mknodat);
2746 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2748 result = sys_mknodat(dirfsp->fh->fd,
2749 smb_fname->base_name,
2753 END_PROFILE(syscall_mknodat);
2757 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2759 const struct smb_filename *smb_fname)
2762 struct smb_filename *result_fname = NULL;
2764 START_PROFILE(syscall_realpath);
2765 result = sys_realpath(smb_fname->base_name);
2766 END_PROFILE(syscall_realpath);
2768 result_fname = synthetic_smb_fname(ctx, result, NULL, NULL, 0);
2771 return result_fname;
2774 static int vfswrap_chflags(vfs_handle_struct *handle,
2775 const struct smb_filename *smb_fname,
2779 return chflags(smb_fname->base_name, flags);
2786 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2787 const SMB_STRUCT_STAT *sbuf)
2791 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2795 key.devid = sbuf->st_ex_dev;
2796 key.inode = sbuf->st_ex_ino;
2797 /* key.extid is unused by default. */
2802 static uint64_t vfswrap_fs_file_id(struct vfs_handle_struct *handle,
2803 const SMB_STRUCT_STAT *psbuf)
2807 if (!(psbuf->st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)) {
2808 return psbuf->st_ex_file_id;
2811 if (handle->conn->base_share_dev == psbuf->st_ex_dev) {
2812 return (uint64_t)psbuf->st_ex_ino;
2816 file_id = ((psbuf->st_ex_ino) & UINT32_MAX);
2819 file_id |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32;
2824 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2825 struct files_struct *fsp,
2826 const struct smb_filename *smb_fname,
2827 TALLOC_CTX *mem_ctx,
2828 unsigned int *pnum_streams,
2829 struct stream_struct **pstreams)
2831 SMB_STRUCT_STAT sbuf;
2832 struct stream_struct *tmp_streams = NULL;
2835 if ((fsp != NULL) && (fsp->is_directory)) {
2837 * No default streams on directories
2842 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2843 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2846 struct smb_filename smb_fname_cp;
2848 ZERO_STRUCT(smb_fname_cp);
2849 smb_fname_cp.base_name = discard_const_p(char,
2850 smb_fname->base_name);
2851 smb_fname_cp.flags = smb_fname->flags;
2853 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
2854 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2856 ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2858 sbuf = smb_fname_cp.st;
2862 return map_nt_error_from_unix(errno);
2865 if (S_ISDIR(sbuf.st_ex_mode)) {
2869 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2870 (*pnum_streams) + 1);
2871 if (tmp_streams == NULL) {
2872 return NT_STATUS_NO_MEMORY;
2874 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2875 if (tmp_streams[*pnum_streams].name == NULL) {
2876 return NT_STATUS_NO_MEMORY;
2878 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2879 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2882 *pstreams = tmp_streams;
2884 return NT_STATUS_OK;
2887 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2890 TALLOC_CTX *mem_ctx,
2894 * Don't fall back to get_real_filename so callers can differentiate
2895 * between a full directory scan and an actual case-insensitive stat.
2901 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2902 const struct smb_filename *smb_fname)
2904 return handle->conn->connectpath;
2907 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2908 struct byte_range_lock *br_lck,
2909 struct lock_struct *plock)
2911 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2913 /* Note: blr is not used in the default implementation. */
2914 return brl_lock_windows_default(br_lck, plock);
2917 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2918 struct byte_range_lock *br_lck,
2919 const struct lock_struct *plock)
2921 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2923 return brl_unlock_windows_default(br_lck, plock);
2926 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
2928 struct lock_struct *plock)
2930 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2931 plock->lock_type == WRITE_LOCK);
2933 return strict_lock_check_default(fsp, plock);
2936 /* NT ACL operations. */
2938 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2940 uint32_t security_info,
2941 TALLOC_CTX *mem_ctx,
2942 struct security_descriptor **ppdesc)
2946 START_PROFILE(fget_nt_acl);
2947 result = posix_fget_nt_acl(fsp, security_info,
2949 END_PROFILE(fget_nt_acl);
2953 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2954 const struct smb_filename *smb_fname,
2955 uint32_t security_info,
2956 TALLOC_CTX *mem_ctx,
2957 struct security_descriptor **ppdesc)
2961 START_PROFILE(get_nt_acl);
2962 result = posix_get_nt_acl(handle->conn,
2967 END_PROFILE(get_nt_acl);
2971 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2975 START_PROFILE(fset_nt_acl);
2976 result = set_nt_acl(fsp, security_info_sent, psd);
2977 END_PROFILE(fset_nt_acl);
2981 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2982 struct smb_filename *file,
2983 struct security_acl *sacl,
2984 uint32_t access_requested,
2985 uint32_t access_denied)
2987 return NT_STATUS_OK; /* Nothing to do here ... */
2990 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2991 const struct smb_filename *smb_fname,
2992 SMB_ACL_TYPE_T type,
2993 TALLOC_CTX *mem_ctx)
2995 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
2998 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
3000 TALLOC_CTX *mem_ctx)
3002 return sys_acl_get_fd(handle, fsp, mem_ctx);
3005 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
3006 const struct smb_filename *smb_fname,
3007 SMB_ACL_TYPE_T acltype,
3010 return sys_acl_set_file(handle, smb_fname, acltype, theacl);
3013 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
3015 return sys_acl_set_fd(handle, fsp, theacl);
3018 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
3019 const struct smb_filename *smb_fname)
3021 return sys_acl_delete_def_file(handle, smb_fname);
3024 /****************************************************************
3025 Extended attribute operations.
3026 *****************************************************************/
3028 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
3029 const struct smb_filename *smb_fname,
3034 return getxattr(smb_fname->base_name, name, value, size);
3037 struct vfswrap_getxattrat_state {
3038 struct tevent_context *ev;
3039 files_struct *dir_fsp;
3040 const struct smb_filename *smb_fname;
3041 struct tevent_req *req;
3044 * The following variables are talloced off "state" which is protected
3045 * by a destructor and thus are guaranteed to be safe to be used in the
3046 * job function in the worker thread.
3049 const char *xattr_name;
3050 uint8_t *xattr_value;
3051 struct security_unix_token *token;
3054 struct vfs_aio_state vfs_aio_state;
3055 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
3058 static int vfswrap_getxattrat_state_destructor(
3059 struct vfswrap_getxattrat_state *state)
3064 static void vfswrap_getxattrat_do_sync(struct tevent_req *req);
3065 static void vfswrap_getxattrat_do_async(void *private_data);
3066 static void vfswrap_getxattrat_done(struct tevent_req *subreq);
3068 static struct tevent_req *vfswrap_getxattrat_send(
3069 TALLOC_CTX *mem_ctx,
3070 struct tevent_context *ev,
3071 struct vfs_handle_struct *handle,
3072 files_struct *dir_fsp,
3073 const struct smb_filename *smb_fname,
3074 const char *xattr_name,
3077 struct tevent_req *req = NULL;
3078 struct tevent_req *subreq = NULL;
3079 struct vfswrap_getxattrat_state *state = NULL;
3080 size_t max_threads = 0;
3081 bool have_per_thread_cwd = false;
3082 bool have_per_thread_creds = false;
3083 bool do_async = false;
3085 req = tevent_req_create(mem_ctx, &state,
3086 struct vfswrap_getxattrat_state);
3090 *state = (struct vfswrap_getxattrat_state) {
3093 .smb_fname = smb_fname,
3097 max_threads = pthreadpool_tevent_max_threads(dir_fsp->conn->sconn->pool);
3098 if (max_threads >= 1) {
3100 * We need a non sync threadpool!
3102 have_per_thread_cwd = per_thread_cwd_supported();
3104 #ifdef HAVE_LINUX_THREAD_CREDENTIALS
3105 have_per_thread_creds = true;
3107 if (have_per_thread_cwd && have_per_thread_creds) {
3111 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat, profile_p,
3112 state->profile_bytes, 0);
3114 if (dir_fsp->fh->fd == -1) {
3115 DBG_ERR("Need a valid directory fd\n");
3116 tevent_req_error(req, EINVAL);
3117 return tevent_req_post(req, ev);
3120 if (alloc_hint > 0) {
3121 state->xattr_value = talloc_zero_array(state,
3124 if (tevent_req_nomem(state->xattr_value, req)) {
3125 return tevent_req_post(req, ev);
3130 vfswrap_getxattrat_do_sync(req);
3131 return tevent_req_post(req, ev);
3135 * Now allocate all parameters from a memory context that won't go away
3136 * no matter what. These paremeters will get used in threads and we
3137 * can't reliably cancel threads, so all buffers passed to the threads
3138 * must not be freed before all referencing threads terminate.
3141 state->name = talloc_strdup(state, smb_fname->base_name);
3142 if (tevent_req_nomem(state->name, req)) {
3143 return tevent_req_post(req, ev);
3146 state->xattr_name = talloc_strdup(state, xattr_name);
3147 if (tevent_req_nomem(state->xattr_name, req)) {
3148 return tevent_req_post(req, ev);
3152 * This is a hot codepath so at first glance one might think we should
3153 * somehow optimize away the token allocation and do a
3154 * talloc_reference() or similar black magic instead. But due to the
3155 * talloc_stackframe pool per SMB2 request this should be a simple copy
3156 * without a malloc in most cases.
3158 if (geteuid() == sec_initial_uid()) {
3159 state->token = root_unix_token(state);
3161 state->token = copy_unix_token(
3163 dir_fsp->conn->session_info->unix_token);
3165 if (tevent_req_nomem(state->token, req)) {
3166 return tevent_req_post(req, ev);
3169 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3171 subreq = pthreadpool_tevent_job_send(
3174 dir_fsp->conn->sconn->pool,
3175 vfswrap_getxattrat_do_async,
3177 if (tevent_req_nomem(subreq, req)) {
3178 return tevent_req_post(req, ev);
3180 tevent_req_set_callback(subreq, vfswrap_getxattrat_done, req);
3182 talloc_set_destructor(state, vfswrap_getxattrat_state_destructor);
3187 static void vfswrap_getxattrat_do_sync(struct tevent_req *req)
3189 struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3190 req, struct vfswrap_getxattrat_state);
3192 char *tofree = NULL;
3193 char pathbuf[PATH_MAX+1];
3197 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
3198 state->smb_fname->base_name,
3203 if (pathlen == -1) {
3204 tevent_req_error(req, ENOMEM);
3208 state->xattr_size = getxattr(path,
3211 talloc_array_length(state->xattr_value));
3213 TALLOC_FREE(tofree);
3214 if (state->xattr_size == -1) {
3215 tevent_req_error(req, err);
3219 tevent_req_done(req);
3223 static void vfswrap_getxattrat_do_async(void *private_data)
3225 struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3226 private_data, struct vfswrap_getxattrat_state);
3227 struct timespec start_time;
3228 struct timespec end_time;
3231 PROFILE_TIMESTAMP(&start_time);
3232 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
3235 * Here we simulate a getxattrat()
3236 * call using fchdir();getxattr()
3239 per_thread_cwd_activate();
3241 /* Become the correct credential on this thread. */
3242 ret = set_thread_credentials(state->token->uid,
3244 (size_t)state->token->ngroups,
3245 state->token->groups);
3247 state->xattr_size = -1;
3248 state->vfs_aio_state.error = errno;
3252 ret = fchdir(state->dir_fsp->fh->fd);
3254 state->xattr_size = -1;
3255 state->vfs_aio_state.error = errno;
3259 state->xattr_size = getxattr(state->name,
3262 talloc_array_length(state->xattr_value));
3263 if (state->xattr_size == -1) {
3264 state->vfs_aio_state.error = errno;
3268 PROFILE_TIMESTAMP(&end_time);
3269 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
3270 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3273 static void vfswrap_getxattrat_done(struct tevent_req *subreq)
3275 struct tevent_req *req = tevent_req_callback_data(
3276 subreq, struct tevent_req);
3277 struct vfswrap_getxattrat_state *state = tevent_req_data(
3278 req, struct vfswrap_getxattrat_state);
3283 * Make sure we run as the user again
3285 ok = change_to_user_and_service_by_fsp(state->dir_fsp);
3288 ret = pthreadpool_tevent_job_recv(subreq);
3289 TALLOC_FREE(subreq);
3290 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
3291 talloc_set_destructor(state, NULL);
3293 if (ret != EAGAIN) {
3294 tevent_req_error(req, ret);
3298 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
3299 * means the lower level pthreadpool failed to create a new
3300 * thread. Fallback to sync processing in that case to allow
3301 * some progress for the client.
3303 vfswrap_getxattrat_do_sync(req);
3307 if (state->xattr_size == -1) {
3308 tevent_req_error(req, state->vfs_aio_state.error);
3312 if (state->xattr_value == NULL) {
3314 * The caller only wanted the size.
3316 tevent_req_done(req);
3321 * shrink the buffer to the returned size.
3322 * (can't fail). It means NULL if size is 0.
3324 state->xattr_value = talloc_realloc(state,
3329 tevent_req_done(req);
3332 static ssize_t vfswrap_getxattrat_recv(struct tevent_req *req,
3333 struct vfs_aio_state *aio_state,
3334 TALLOC_CTX *mem_ctx,
3335 uint8_t **xattr_value)
3337 struct vfswrap_getxattrat_state *state = tevent_req_data(
3338 req, struct vfswrap_getxattrat_state);
3341 if (tevent_req_is_unix_error(req, &aio_state->error)) {
3342 tevent_req_received(req);
3346 *aio_state = state->vfs_aio_state;
3347 xattr_size = state->xattr_size;
3348 if (xattr_value != NULL) {
3349 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
3352 tevent_req_received(req);
3356 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
3358 return fgetxattr(fsp->fh->fd, name, value, size);
3361 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
3362 const struct smb_filename *smb_fname,
3366 return listxattr(smb_fname->base_name, list, size);
3369 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
3371 return flistxattr(fsp->fh->fd, list, size);
3374 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
3375 const struct smb_filename *smb_fname,
3378 return removexattr(smb_fname->base_name, name);
3381 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
3383 return fremovexattr(fsp->fh->fd, name);
3386 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
3387 const struct smb_filename *smb_fname,
3393 return setxattr(smb_fname->base_name, name, value, size, flags);
3396 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
3398 return fsetxattr(fsp->fh->fd, name, value, size, flags);
3401 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
3406 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
3407 const struct smb_filename *fname,
3408 SMB_STRUCT_STAT *sbuf)
3412 bool offline = false;
3414 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
3418 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
3419 #if defined(ENOTSUP)
3425 status = get_full_smb_filename(talloc_tos(), fname, &path);
3426 if (!NT_STATUS_IS_OK(status)) {
3427 errno = map_errno_from_nt_status(status);
3431 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
3438 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
3439 struct files_struct *fsp,
3440 TALLOC_CTX *mem_ctx,
3443 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
3446 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
3447 struct files_struct *fsp,
3448 const DATA_BLOB old_cookie,
3449 TALLOC_CTX *mem_ctx,
3450 DATA_BLOB *new_cookie)
3452 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
3456 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
3457 struct smb_request *smb1req,
3458 struct smbXsrv_open *op,
3459 const DATA_BLOB old_cookie,
3460 TALLOC_CTX *mem_ctx,
3461 struct files_struct **fsp,
3462 DATA_BLOB *new_cookie)
3464 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
3465 old_cookie, mem_ctx,
3469 static struct vfs_fn_pointers vfs_default_fns = {
3470 /* Disk operations */
3472 .connect_fn = vfswrap_connect,
3473 .disconnect_fn = vfswrap_disconnect,
3474 .disk_free_fn = vfswrap_disk_free,
3475 .get_quota_fn = vfswrap_get_quota,
3476 .set_quota_fn = vfswrap_set_quota,
3477 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3478 .statvfs_fn = vfswrap_statvfs,
3479 .fs_capabilities_fn = vfswrap_fs_capabilities,
3480 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3481 .snap_check_path_fn = vfswrap_snap_check_path,
3482 .snap_create_fn = vfswrap_snap_create,
3483 .snap_delete_fn = vfswrap_snap_delete,
3485 /* Directory operations */
3487 .opendir_fn = vfswrap_opendir,
3488 .fdopendir_fn = vfswrap_fdopendir,
3489 .readdir_fn = vfswrap_readdir,
3490 .readdir_attr_fn = vfswrap_readdir_attr,
3491 .seekdir_fn = vfswrap_seekdir,
3492 .telldir_fn = vfswrap_telldir,
3493 .rewind_dir_fn = vfswrap_rewinddir,
3494 .mkdirat_fn = vfswrap_mkdirat,
3495 .closedir_fn = vfswrap_closedir,
3497 /* File operations */
3499 .open_fn = vfswrap_open,
3500 .create_file_fn = vfswrap_create_file,
3501 .close_fn = vfswrap_close,
3502 .pread_fn = vfswrap_pread,
3503 .pread_send_fn = vfswrap_pread_send,
3504 .pread_recv_fn = vfswrap_pread_recv,
3505 .pwrite_fn = vfswrap_pwrite,
3506 .pwrite_send_fn = vfswrap_pwrite_send,
3507 .pwrite_recv_fn = vfswrap_pwrite_recv,
3508 .lseek_fn = vfswrap_lseek,
3509 .sendfile_fn = vfswrap_sendfile,
3510 .recvfile_fn = vfswrap_recvfile,
3511 .renameat_fn = vfswrap_renameat,
3512 .fsync_send_fn = vfswrap_fsync_send,
3513 .fsync_recv_fn = vfswrap_fsync_recv,
3514 .stat_fn = vfswrap_stat,
3515 .fstat_fn = vfswrap_fstat,
3516 .lstat_fn = vfswrap_lstat,
3517 .get_alloc_size_fn = vfswrap_get_alloc_size,
3518 .unlinkat_fn = vfswrap_unlinkat,
3519 .chmod_fn = vfswrap_chmod,
3520 .fchmod_fn = vfswrap_fchmod,
3521 .fchown_fn = vfswrap_fchown,
3522 .lchown_fn = vfswrap_lchown,
3523 .chdir_fn = vfswrap_chdir,
3524 .getwd_fn = vfswrap_getwd,
3525 .ntimes_fn = vfswrap_ntimes,
3526 .ftruncate_fn = vfswrap_ftruncate,
3527 .fallocate_fn = vfswrap_fallocate,
3528 .lock_fn = vfswrap_lock,
3529 .kernel_flock_fn = vfswrap_kernel_flock,
3530 .fcntl_fn = vfswrap_fcntl,
3531 .linux_setlease_fn = vfswrap_linux_setlease,
3532 .getlock_fn = vfswrap_getlock,
3533 .symlinkat_fn = vfswrap_symlinkat,
3534 .readlinkat_fn = vfswrap_readlinkat,
3535 .linkat_fn = vfswrap_linkat,
3536 .mknodat_fn = vfswrap_mknodat,
3537 .realpath_fn = vfswrap_realpath,
3538 .chflags_fn = vfswrap_chflags,
3539 .file_id_create_fn = vfswrap_file_id_create,
3540 .fs_file_id_fn = vfswrap_fs_file_id,
3541 .streaminfo_fn = vfswrap_streaminfo,
3542 .get_real_filename_fn = vfswrap_get_real_filename,
3543 .connectpath_fn = vfswrap_connectpath,
3544 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
3545 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3546 .strict_lock_check_fn = vfswrap_strict_lock_check,
3547 .translate_name_fn = vfswrap_translate_name,
3548 .fsctl_fn = vfswrap_fsctl,
3549 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
3550 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
3551 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
3552 .get_dos_attributes_send_fn = vfswrap_get_dos_attributes_send,
3553 .get_dos_attributes_recv_fn = vfswrap_get_dos_attributes_recv,
3554 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
3555 .offload_read_send_fn = vfswrap_offload_read_send,
3556 .offload_read_recv_fn = vfswrap_offload_read_recv,
3557 .offload_write_send_fn = vfswrap_offload_write_send,
3558 .offload_write_recv_fn = vfswrap_offload_write_recv,
3559 .get_compression_fn = vfswrap_get_compression,
3560 .set_compression_fn = vfswrap_set_compression,
3562 /* NT ACL operations. */
3564 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
3565 .get_nt_acl_fn = vfswrap_get_nt_acl,
3566 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
3567 .audit_file_fn = vfswrap_audit_file,
3569 /* POSIX ACL operations. */
3571 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
3572 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3573 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
3574 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3575 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
3576 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3577 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
3579 /* EA operations. */
3580 .getxattr_fn = vfswrap_getxattr,
3581 .getxattrat_send_fn = vfswrap_getxattrat_send,
3582 .getxattrat_recv_fn = vfswrap_getxattrat_recv,
3583 .fgetxattr_fn = vfswrap_fgetxattr,
3584 .listxattr_fn = vfswrap_listxattr,
3585 .flistxattr_fn = vfswrap_flistxattr,
3586 .removexattr_fn = vfswrap_removexattr,
3587 .fremovexattr_fn = vfswrap_fremovexattr,
3588 .setxattr_fn = vfswrap_setxattr,
3589 .fsetxattr_fn = vfswrap_fsetxattr,
3591 /* aio operations */
3592 .aio_force_fn = vfswrap_aio_force,
3594 /* durable handle operations */
3595 .durable_cookie_fn = vfswrap_durable_cookie,
3596 .durable_disconnect_fn = vfswrap_durable_disconnect,
3597 .durable_reconnect_fn = vfswrap_durable_reconnect,
3601 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3604 * Here we need to implement every call!
3606 * As this is the end of the vfs module chain.
3608 smb_vfs_assert_all_fns(&vfs_default_fns, DEFAULT_VFS_MODULE_NAME);
3609 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3610 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);