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);
745 if (tevent_req_error(req, ret)) {
749 tevent_req_done(req);
752 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
753 struct vfs_aio_state *vfs_aio_state)
755 struct vfswrap_pread_state *state = tevent_req_data(
756 req, struct vfswrap_pread_state);
758 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
762 *vfs_aio_state = state->vfs_aio_state;
766 struct vfswrap_pwrite_state {
773 struct vfs_aio_state vfs_aio_state;
774 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
777 static void vfs_pwrite_do(void *private_data);
778 static void vfs_pwrite_done(struct tevent_req *subreq);
779 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state);
781 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
783 struct tevent_context *ev,
784 struct files_struct *fsp,
786 size_t n, off_t offset)
788 struct tevent_req *req, *subreq;
789 struct vfswrap_pwrite_state *state;
791 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
797 state->fd = fsp->fh->fd;
800 state->offset = offset;
802 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
803 state->profile_bytes, n);
804 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
806 subreq = pthreadpool_tevent_job_send(
807 state, ev, handle->conn->sconn->pool,
808 vfs_pwrite_do, state);
809 if (tevent_req_nomem(subreq, req)) {
810 return tevent_req_post(req, ev);
812 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
814 talloc_set_destructor(state, vfs_pwrite_state_destructor);
819 static void vfs_pwrite_do(void *private_data)
821 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
822 private_data, struct vfswrap_pwrite_state);
823 struct timespec start_time;
824 struct timespec end_time;
826 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
828 PROFILE_TIMESTAMP(&start_time);
831 state->ret = pwrite(state->fd, state->buf, state->count,
833 } while ((state->ret == -1) && (errno == EINTR));
835 if (state->ret == -1) {
836 state->vfs_aio_state.error = errno;
839 PROFILE_TIMESTAMP(&end_time);
841 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
843 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
846 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state)
851 static void vfs_pwrite_done(struct tevent_req *subreq)
853 struct tevent_req *req = tevent_req_callback_data(
854 subreq, struct tevent_req);
855 struct vfswrap_pwrite_state *state = tevent_req_data(
856 req, struct vfswrap_pwrite_state);
859 ret = pthreadpool_tevent_job_recv(subreq);
861 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
862 talloc_set_destructor(state, NULL);
863 if (tevent_req_error(req, ret)) {
867 tevent_req_done(req);
870 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
871 struct vfs_aio_state *vfs_aio_state)
873 struct vfswrap_pwrite_state *state = tevent_req_data(
874 req, struct vfswrap_pwrite_state);
876 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
880 *vfs_aio_state = state->vfs_aio_state;
884 struct vfswrap_fsync_state {
888 struct vfs_aio_state vfs_aio_state;
889 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
892 static void vfs_fsync_do(void *private_data);
893 static void vfs_fsync_done(struct tevent_req *subreq);
894 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state);
896 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
898 struct tevent_context *ev,
899 struct files_struct *fsp)
901 struct tevent_req *req, *subreq;
902 struct vfswrap_fsync_state *state;
904 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
910 state->fd = fsp->fh->fd;
912 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_fsync, profile_p,
913 state->profile_bytes, 0);
914 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
916 subreq = pthreadpool_tevent_job_send(
917 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
918 if (tevent_req_nomem(subreq, req)) {
919 return tevent_req_post(req, ev);
921 tevent_req_set_callback(subreq, vfs_fsync_done, req);
923 talloc_set_destructor(state, vfs_fsync_state_destructor);
928 static void vfs_fsync_do(void *private_data)
930 struct vfswrap_fsync_state *state = talloc_get_type_abort(
931 private_data, struct vfswrap_fsync_state);
932 struct timespec start_time;
933 struct timespec end_time;
935 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
937 PROFILE_TIMESTAMP(&start_time);
940 state->ret = fsync(state->fd);
941 } while ((state->ret == -1) && (errno == EINTR));
943 if (state->ret == -1) {
944 state->vfs_aio_state.error = errno;
947 PROFILE_TIMESTAMP(&end_time);
949 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
951 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
954 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state)
959 static void vfs_fsync_done(struct tevent_req *subreq)
961 struct tevent_req *req = tevent_req_callback_data(
962 subreq, struct tevent_req);
963 struct vfswrap_fsync_state *state = tevent_req_data(
964 req, struct vfswrap_fsync_state);
967 ret = pthreadpool_tevent_job_recv(subreq);
969 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
970 talloc_set_destructor(state, NULL);
971 if (tevent_req_error(req, ret)) {
975 tevent_req_done(req);
978 static int vfswrap_fsync_recv(struct tevent_req *req,
979 struct vfs_aio_state *vfs_aio_state)
981 struct vfswrap_fsync_state *state = tevent_req_data(
982 req, struct vfswrap_fsync_state);
984 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
988 *vfs_aio_state = state->vfs_aio_state;
992 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
996 START_PROFILE(syscall_lseek);
998 /* Cope with 'stat' file opens. */
999 if (fsp->fh->fd != -1)
1000 result = lseek(fsp->fh->fd, offset, whence);
1003 * We want to maintain the fiction that we can seek
1004 * on a fifo for file system purposes. This allows
1005 * people to set up UNIX fifo's that feed data to Windows
1006 * applications. JRA.
1009 if((result == -1) && (errno == ESPIPE)) {
1014 END_PROFILE(syscall_lseek);
1018 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1019 off_t offset, size_t n)
1023 START_PROFILE_BYTES(syscall_sendfile, n);
1024 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
1025 END_PROFILE_BYTES(syscall_sendfile);
1029 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1031 files_struct *tofsp,
1037 START_PROFILE_BYTES(syscall_recvfile, n);
1038 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
1039 END_PROFILE_BYTES(syscall_recvfile);
1043 static int vfswrap_rename(vfs_handle_struct *handle,
1044 const struct smb_filename *smb_fname_src,
1045 const struct smb_filename *smb_fname_dst)
1049 START_PROFILE(syscall_rename);
1051 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
1056 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
1059 END_PROFILE(syscall_rename);
1063 static int vfswrap_stat(vfs_handle_struct *handle,
1064 struct smb_filename *smb_fname)
1068 START_PROFILE(syscall_stat);
1070 if (smb_fname->stream_name) {
1075 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1076 lp_fake_directory_create_times(SNUM(handle->conn)));
1078 END_PROFILE(syscall_stat);
1082 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1086 START_PROFILE(syscall_fstat);
1087 result = sys_fstat(fsp->fh->fd,
1088 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1089 END_PROFILE(syscall_fstat);
1093 static int vfswrap_lstat(vfs_handle_struct *handle,
1094 struct smb_filename *smb_fname)
1098 START_PROFILE(syscall_lstat);
1100 if (smb_fname->stream_name) {
1105 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1106 lp_fake_directory_create_times(SNUM(handle->conn)));
1108 END_PROFILE(syscall_lstat);
1112 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1114 enum vfs_translate_direction direction,
1115 TALLOC_CTX *mem_ctx,
1118 return NT_STATUS_NONE_MAPPED;
1122 * Implement the default fsctl operation.
1124 static bool vfswrap_logged_ioctl_message = false;
1126 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1127 struct files_struct *fsp,
1130 uint16_t req_flags, /* Needed for UNICODE ... */
1131 const uint8_t *_in_data,
1133 uint8_t **_out_data,
1134 uint32_t max_out_len,
1137 const char *in_data = (const char *)_in_data;
1138 char **out_data = (char **)_out_data;
1142 case FSCTL_SET_SPARSE:
1144 bool set_sparse = true;
1146 if (in_len >= 1 && in_data[0] == 0) {
1150 status = file_set_sparse(handle->conn, fsp, set_sparse);
1152 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1153 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1154 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1155 nt_errstr(status)));
1160 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1162 unsigned char objid[16];
1163 char *return_data = NULL;
1165 /* This should return the object-id on this file.
1166 * I think I'll make this be the inode+dev. JRA.
1169 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1170 fsp_fnum_dbg(fsp)));
1172 *out_len = MIN(max_out_len, 64);
1174 /* Hmmm, will this cause problems if less data asked for? */
1175 return_data = talloc_array(ctx, char, 64);
1176 if (return_data == NULL) {
1177 return NT_STATUS_NO_MEMORY;
1180 /* For backwards compatibility only store the dev/inode. */
1181 push_file_id_16(return_data, &fsp->file_id);
1182 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1183 push_file_id_16(return_data+32, &fsp->file_id);
1184 memset(return_data+48, 0, 16);
1185 *out_data = return_data;
1186 return NT_STATUS_OK;
1189 case FSCTL_GET_REPARSE_POINT:
1191 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1192 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1193 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1194 return NT_STATUS_NOT_A_REPARSE_POINT;
1197 case FSCTL_SET_REPARSE_POINT:
1199 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1200 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1201 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1202 return NT_STATUS_NOT_A_REPARSE_POINT;
1205 case FSCTL_GET_SHADOW_COPY_DATA:
1208 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1209 * and return their volume names. If max_data_count is 16, then it is just
1210 * asking for the number of volumes and length of the combined names.
1212 * pdata is the data allocated by our caller, but that uses
1213 * total_data_count (which is 0 in our case) rather than max_data_count.
1214 * Allocate the correct amount and return the pointer to let
1215 * it be deallocated when we return.
1217 struct shadow_copy_data *shadow_data = NULL;
1218 bool labels = False;
1219 uint32_t labels_data_count = 0;
1221 char *cur_pdata = NULL;
1223 if (max_out_len < 16) {
1224 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1226 return NT_STATUS_INVALID_PARAMETER;
1229 if (max_out_len > 16) {
1233 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1234 if (shadow_data == NULL) {
1235 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1236 return NT_STATUS_NO_MEMORY;
1240 * Call the VFS routine to actually do the work.
1242 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1245 /* broken module didn't set errno on error */
1246 status = NT_STATUS_UNSUCCESSFUL;
1248 status = map_nt_error_from_unix(errno);
1249 if (NT_STATUS_EQUAL(status,
1250 NT_STATUS_NOT_SUPPORTED)) {
1254 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1255 "connectpath %s, failed - %s.\n",
1256 fsp->conn->connectpath,
1257 nt_errstr(status)));
1258 TALLOC_FREE(shadow_data);
1262 labels_data_count = (shadow_data->num_volumes * 2 *
1263 sizeof(SHADOW_COPY_LABEL)) + 2;
1268 *out_len = 12 + labels_data_count;
1271 if (max_out_len < *out_len) {
1272 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1273 max_out_len, *out_len));
1274 TALLOC_FREE(shadow_data);
1275 return NT_STATUS_BUFFER_TOO_SMALL;
1278 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1279 if (cur_pdata == NULL) {
1280 TALLOC_FREE(shadow_data);
1281 return NT_STATUS_NO_MEMORY;
1284 *out_data = cur_pdata;
1286 /* num_volumes 4 bytes */
1287 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1290 /* num_labels 4 bytes */
1291 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1294 /* needed_data_count 4 bytes */
1295 SIVAL(cur_pdata, 8, labels_data_count);
1299 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1300 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1301 if (labels && shadow_data->labels) {
1302 for (i=0; i<shadow_data->num_volumes; i++) {
1304 status = srvstr_push(cur_pdata, req_flags,
1305 cur_pdata, shadow_data->labels[i],
1306 2 * sizeof(SHADOW_COPY_LABEL),
1307 STR_UNICODE|STR_TERMINATE, &len);
1308 if (!NT_STATUS_IS_OK(status)) {
1309 TALLOC_FREE(*out_data);
1310 TALLOC_FREE(shadow_data);
1313 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1314 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1318 TALLOC_FREE(shadow_data);
1320 return NT_STATUS_OK;
1323 case FSCTL_FIND_FILES_BY_SID:
1325 /* pretend this succeeded -
1327 * we have to send back a list with all files owned by this SID
1329 * but I have to check that --metze
1335 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1336 fsp_fnum_dbg(fsp)));
1339 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1340 return NT_STATUS_INVALID_PARAMETER;
1343 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1345 /* unknown 4 bytes: this is not the length of the sid :-( */
1346 /*unknown = IVAL(pdata,0);*/
1348 if (!sid_parse(_in_data + 4, sid_len, &sid)) {
1349 return NT_STATUS_INVALID_PARAMETER;
1351 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1353 if (!sid_to_uid(&sid, &uid)) {
1354 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1355 sid_string_dbg(&sid),
1356 (unsigned long)sid_len));
1360 /* we can take a look at the find source :-)
1362 * find ./ -uid $uid -name '*' is what we need here
1365 * and send 4bytes len and then NULL terminated unicode strings
1368 * but I don't know how to deal with the paged results
1369 * (maybe we can hang the result anywhere in the fsp struct)
1371 * but I don't know how to deal with the paged results
1372 * (maybe we can hang the result anywhere in the fsp struct)
1374 * we don't send all files at once
1375 * and at the next we should *not* start from the beginning,
1376 * so we have to cache the result
1381 /* this works for now... */
1382 return NT_STATUS_OK;
1385 case FSCTL_QUERY_ALLOCATED_RANGES:
1387 /* FIXME: This is just a dummy reply, telling that all of the
1388 * file is allocated. MKS cp needs that.
1389 * Adding the real allocated ranges via FIEMAP on Linux
1390 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1391 * this FSCTL correct for sparse files.
1393 uint64_t offset, length;
1394 char *out_data_tmp = NULL;
1397 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1399 return NT_STATUS_INVALID_PARAMETER;
1402 if (max_out_len < 16) {
1403 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1405 return NT_STATUS_INVALID_PARAMETER;
1408 offset = BVAL(in_data,0);
1409 length = BVAL(in_data,8);
1411 if (offset + length < offset) {
1412 /* No 64-bit integer wrap. */
1413 return NT_STATUS_INVALID_PARAMETER;
1416 /* Shouldn't this be SMB_VFS_STAT ... ? */
1417 status = vfs_stat_fsp(fsp);
1418 if (!NT_STATUS_IS_OK(status)) {
1423 out_data_tmp = talloc_array(ctx, char, *out_len);
1424 if (out_data_tmp == NULL) {
1425 DEBUG(10, ("unable to allocate memory for response\n"));
1426 return NT_STATUS_NO_MEMORY;
1429 if (offset > fsp->fsp_name->st.st_ex_size ||
1430 fsp->fsp_name->st.st_ex_size == 0 ||
1432 memset(out_data_tmp, 0, *out_len);
1434 uint64_t end = offset + length;
1435 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1436 SBVAL(out_data_tmp, 0, 0);
1437 SBVAL(out_data_tmp, 8, end);
1440 *out_data = out_data_tmp;
1442 return NT_STATUS_OK;
1445 case FSCTL_IS_VOLUME_DIRTY:
1447 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1448 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1450 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1451 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1453 return NT_STATUS_INVALID_PARAMETER;
1458 * Only print once ... unfortunately there could be lots of
1459 * different FSCTLs that are called.
1461 if (!vfswrap_logged_ioctl_message) {
1462 vfswrap_logged_ioctl_message = true;
1463 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1464 __func__, function));
1468 return NT_STATUS_NOT_SUPPORTED;
1471 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
1472 const struct smb_filename *fname,
1473 SMB_STRUCT_STAT *sbuf);
1475 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1476 struct smb_filename *smb_fname,
1481 offline = vfswrap_is_offline(handle, smb_fname, &smb_fname->st);
1483 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1486 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1489 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1490 struct files_struct *fsp,
1495 offline = vfswrap_is_offline(handle, fsp->fsp_name, &fsp->fsp_name->st);
1497 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1500 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1503 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1504 const struct smb_filename *smb_fname,
1507 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1510 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1511 struct files_struct *fsp,
1514 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1517 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1519 struct vfswrap_offload_read_state {
1523 static struct tevent_req *vfswrap_offload_read_send(
1524 TALLOC_CTX *mem_ctx,
1525 struct tevent_context *ev,
1526 struct vfs_handle_struct *handle,
1527 struct files_struct *fsp,
1533 struct tevent_req *req = NULL;
1534 struct vfswrap_offload_read_state *state = NULL;
1537 req = tevent_req_create(mem_ctx, &state,
1538 struct vfswrap_offload_read_state);
1543 status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1544 &vfswrap_offload_ctx);
1545 if (tevent_req_nterror(req, status)) {
1546 return tevent_req_post(req, ev);
1549 if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1550 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1551 return tevent_req_post(req, ev);
1554 status = vfs_offload_token_create_blob(state, fsp, fsctl,
1556 if (tevent_req_nterror(req, status)) {
1557 return tevent_req_post(req, ev);
1560 status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1562 if (tevent_req_nterror(req, status)) {
1563 return tevent_req_post(req, ev);
1566 tevent_req_done(req);
1567 return tevent_req_post(req, ev);
1570 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
1571 struct vfs_handle_struct *handle,
1572 TALLOC_CTX *mem_ctx,
1575 struct vfswrap_offload_read_state *state = tevent_req_data(
1576 req, struct vfswrap_offload_read_state);
1579 if (tevent_req_is_nterror(req, &status)) {
1580 tevent_req_received(req);
1584 token->length = state->token.length;
1585 token->data = talloc_move(mem_ctx, &state->token.data);
1587 tevent_req_received(req);
1588 return NT_STATUS_OK;
1591 struct vfswrap_offload_write_state {
1593 bool read_lck_locked;
1594 bool write_lck_locked;
1596 struct tevent_context *src_ev;
1597 struct files_struct *src_fsp;
1599 struct tevent_context *dst_ev;
1600 struct files_struct *dst_fsp;
1604 size_t next_io_size;
1607 static void vfswrap_offload_write_cleanup(struct tevent_req *req,
1608 enum tevent_req_state req_state)
1610 struct vfswrap_offload_write_state *state = tevent_req_data(
1611 req, struct vfswrap_offload_write_state);
1614 if (state->dst_fsp == NULL) {
1618 ok = change_to_user_by_fsp(state->dst_fsp);
1620 state->dst_fsp = NULL;
1623 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
1625 static struct tevent_req *vfswrap_offload_write_send(
1626 struct vfs_handle_struct *handle,
1627 TALLOC_CTX *mem_ctx,
1628 struct tevent_context *ev,
1631 off_t transfer_offset,
1632 struct files_struct *dest_fsp,
1636 struct tevent_req *req;
1637 struct vfswrap_offload_write_state *state = NULL;
1638 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
1639 files_struct *src_fsp = NULL;
1643 req = tevent_req_create(mem_ctx, &state,
1644 struct vfswrap_offload_write_state);
1649 *state = (struct vfswrap_offload_write_state) {
1651 .src_off = transfer_offset,
1653 .dst_fsp = dest_fsp,
1654 .dst_off = dest_off,
1656 .remaining = to_copy,
1659 tevent_req_set_cleanup_fn(req, vfswrap_offload_write_cleanup);
1662 case FSCTL_SRV_COPYCHUNK:
1663 case FSCTL_SRV_COPYCHUNK_WRITE:
1666 case FSCTL_OFFLOAD_WRITE:
1667 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
1668 return tevent_req_post(req, ev);
1670 case FSCTL_DUP_EXTENTS_TO_FILE:
1671 DBG_DEBUG("COW clones not supported by vfs_default\n");
1672 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1673 return tevent_req_post(req, ev);
1676 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1677 return tevent_req_post(req, ev);
1681 * From here on we assume a copy-chunk fsctl
1685 tevent_req_done(req);
1686 return tevent_req_post(req, ev);
1689 status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
1691 if (tevent_req_nterror(req, status)) {
1692 return tevent_req_post(req, ev);
1695 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
1697 status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
1698 if (!NT_STATUS_IS_OK(status)) {
1699 tevent_req_nterror(req, status);
1700 return tevent_req_post(req, ev);
1703 ok = change_to_user_by_fsp(src_fsp);
1705 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1706 return tevent_req_post(req, ev);
1709 state->src_ev = src_fsp->conn->user_ev_ctx;
1710 state->src_fsp = src_fsp;
1712 state->buf = talloc_array(state, uint8_t, num);
1713 if (tevent_req_nomem(state->buf, req)) {
1714 return tevent_req_post(req, ev);
1717 status = vfs_stat_fsp(src_fsp);
1718 if (tevent_req_nterror(req, status)) {
1719 return tevent_req_post(req, ev);
1722 if (src_fsp->fsp_name->st.st_ex_size < state->src_off + num) {
1724 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1725 * If the SourceOffset or SourceOffset + Length extends beyond
1726 * the end of file, the server SHOULD<240> treat this as a
1727 * STATUS_END_OF_FILE error.
1729 * <240> Section 3.3.5.15.6: Windows servers will return
1730 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1732 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1733 return tevent_req_post(req, ev);
1736 status = vfswrap_offload_write_loop(req);
1737 if (!NT_STATUS_IS_OK(status)) {
1738 tevent_req_nterror(req, status);
1739 return tevent_req_post(req, ev);
1745 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
1747 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
1749 struct vfswrap_offload_write_state *state = tevent_req_data(
1750 req, struct vfswrap_offload_write_state);
1751 struct tevent_req *subreq = NULL;
1752 struct lock_struct read_lck;
1756 * This is called under the context of state->src_fsp.
1759 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
1761 init_strict_lock_struct(state->src_fsp,
1762 state->src_fsp->op->global->open_persistent_id,
1764 state->next_io_size,
1768 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
1772 return NT_STATUS_FILE_LOCK_CONFLICT;
1775 subreq = SMB_VFS_PREAD_SEND(state,
1779 state->next_io_size,
1781 if (subreq == NULL) {
1782 return NT_STATUS_NO_MEMORY;
1784 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
1786 return NT_STATUS_OK;
1789 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
1791 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
1793 struct tevent_req *req = tevent_req_callback_data(
1794 subreq, struct tevent_req);
1795 struct vfswrap_offload_write_state *state = tevent_req_data(
1796 req, struct vfswrap_offload_write_state);
1797 struct vfs_aio_state aio_state;
1798 struct lock_struct write_lck;
1802 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
1803 TALLOC_FREE(subreq);
1805 DBG_ERR("read failed: %s\n", strerror(errno));
1806 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1809 if (nread != state->next_io_size) {
1810 DBG_ERR("Short read, only %zd of %zu\n",
1811 nread, state->next_io_size);
1812 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1816 state->src_off += nread;
1818 ok = change_to_user_by_fsp(state->dst_fsp);
1820 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1824 init_strict_lock_struct(state->dst_fsp,
1825 state->dst_fsp->op->global->open_persistent_id,
1827 state->next_io_size,
1831 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
1835 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1839 subreq = SMB_VFS_PWRITE_SEND(state,
1843 state->next_io_size,
1845 if (subreq == NULL) {
1846 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1849 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
1852 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
1854 struct tevent_req *req = tevent_req_callback_data(
1855 subreq, struct tevent_req);
1856 struct vfswrap_offload_write_state *state = tevent_req_data(
1857 req, struct vfswrap_offload_write_state);
1858 struct vfs_aio_state aio_state;
1863 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
1864 TALLOC_FREE(subreq);
1865 if (nwritten == -1) {
1866 DBG_ERR("write failed: %s\n", strerror(errno));
1867 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1870 if (nwritten != state->next_io_size) {
1871 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
1872 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1876 state->dst_off += nwritten;
1878 if (state->remaining < nwritten) {
1879 /* Paranoia check */
1880 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1883 state->remaining -= nwritten;
1884 if (state->remaining == 0) {
1885 tevent_req_done(req);
1889 ok = change_to_user_by_fsp(state->src_fsp);
1891 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1895 status = vfswrap_offload_write_loop(req);
1896 if (!NT_STATUS_IS_OK(status)) {
1897 tevent_req_nterror(req, status);
1904 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
1905 struct tevent_req *req,
1908 struct vfswrap_offload_write_state *state = tevent_req_data(
1909 req, struct vfswrap_offload_write_state);
1912 if (tevent_req_is_nterror(req, &status)) {
1913 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
1915 tevent_req_received(req);
1919 *copied = state->to_copy;
1920 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
1921 tevent_req_received(req);
1923 return NT_STATUS_OK;
1926 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1927 TALLOC_CTX *mem_ctx,
1928 struct files_struct *fsp,
1929 struct smb_filename *smb_fname,
1930 uint16_t *_compression_fmt)
1932 return NT_STATUS_INVALID_DEVICE_REQUEST;
1935 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1936 TALLOC_CTX *mem_ctx,
1937 struct files_struct *fsp,
1938 uint16_t compression_fmt)
1940 return NT_STATUS_INVALID_DEVICE_REQUEST;
1943 /********************************************************************
1944 Given a stat buffer return the allocated size on disk, taking into
1945 account sparse files.
1946 ********************************************************************/
1947 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1948 struct files_struct *fsp,
1949 const SMB_STRUCT_STAT *sbuf)
1953 START_PROFILE(syscall_get_alloc_size);
1955 if(S_ISDIR(sbuf->st_ex_mode)) {
1960 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1961 /* The type of st_blocksize is blkcnt_t which *MUST* be
1962 signed (according to POSIX) and can be less than 64-bits.
1963 Ensure when we're converting to 64 bits wide we don't
1965 #if defined(SIZEOF_BLKCNT_T_8)
1966 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1967 #elif defined(SIZEOF_BLKCNT_T_4)
1969 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1970 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1973 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1977 * Some file systems do not allocate a block for very
1978 * small files. But for non-empty file should report a
1982 uint64_t filesize = get_file_size_stat(sbuf);
1984 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
1988 result = get_file_size_stat(sbuf);
1991 if (fsp && fsp->initial_allocation_size)
1992 result = MAX(result,fsp->initial_allocation_size);
1994 result = smb_roundup(handle->conn, result);
1997 END_PROFILE(syscall_get_alloc_size);
2001 static int vfswrap_unlink(vfs_handle_struct *handle,
2002 const struct smb_filename *smb_fname)
2006 START_PROFILE(syscall_unlink);
2008 if (smb_fname->stream_name) {
2012 result = unlink(smb_fname->base_name);
2015 END_PROFILE(syscall_unlink);
2019 static int vfswrap_chmod(vfs_handle_struct *handle,
2020 const struct smb_filename *smb_fname,
2025 START_PROFILE(syscall_chmod);
2026 result = chmod(smb_fname->base_name, mode);
2027 END_PROFILE(syscall_chmod);
2031 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2035 START_PROFILE(syscall_fchmod);
2036 #if defined(HAVE_FCHMOD)
2037 result = fchmod(fsp->fh->fd, mode);
2043 END_PROFILE(syscall_fchmod);
2047 static int vfswrap_chown(vfs_handle_struct *handle,
2048 const struct smb_filename *smb_fname,
2054 START_PROFILE(syscall_chown);
2055 result = chown(smb_fname->base_name, uid, gid);
2056 END_PROFILE(syscall_chown);
2060 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2065 START_PROFILE(syscall_fchown);
2066 result = fchown(fsp->fh->fd, uid, gid);
2067 END_PROFILE(syscall_fchown);
2075 static int vfswrap_lchown(vfs_handle_struct *handle,
2076 const struct smb_filename *smb_fname,
2082 START_PROFILE(syscall_lchown);
2083 result = lchown(smb_fname->base_name, uid, gid);
2084 END_PROFILE(syscall_lchown);
2088 static int vfswrap_chdir(vfs_handle_struct *handle,
2089 const struct smb_filename *smb_fname)
2093 START_PROFILE(syscall_chdir);
2094 result = chdir(smb_fname->base_name);
2095 END_PROFILE(syscall_chdir);
2099 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2103 struct smb_filename *smb_fname = NULL;
2105 START_PROFILE(syscall_getwd);
2106 result = sys_getwd();
2107 END_PROFILE(syscall_getwd);
2109 if (result == NULL) {
2112 smb_fname = synthetic_smb_fname(ctx,
2118 * sys_getwd() *always* returns malloced memory.
2119 * We must free here to avoid leaks:
2120 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2126 /*********************************************************************
2127 nsec timestamp resolution call. Convert down to whatever the underlying
2128 system will support.
2129 **********************************************************************/
2131 static int vfswrap_ntimes(vfs_handle_struct *handle,
2132 const struct smb_filename *smb_fname,
2133 struct smb_file_time *ft)
2137 START_PROFILE(syscall_ntimes);
2139 if (smb_fname->stream_name) {
2145 if (null_timespec(ft->atime)) {
2146 ft->atime= smb_fname->st.st_ex_atime;
2149 if (null_timespec(ft->mtime)) {
2150 ft->mtime = smb_fname->st.st_ex_mtime;
2153 if (!null_timespec(ft->create_time)) {
2154 set_create_timespec_ea(handle->conn,
2159 if ((timespec_compare(&ft->atime,
2160 &smb_fname->st.st_ex_atime) == 0) &&
2161 (timespec_compare(&ft->mtime,
2162 &smb_fname->st.st_ex_mtime) == 0)) {
2167 #if defined(HAVE_UTIMENSAT)
2169 struct timespec ts[2];
2172 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2174 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2176 if (!((result == -1) && (errno == ENOSYS))) {
2180 #if defined(HAVE_UTIMES)
2182 struct timeval tv[2];
2183 tv[0] = convert_timespec_to_timeval(ft->atime);
2184 tv[1] = convert_timespec_to_timeval(ft->mtime);
2185 result = utimes(smb_fname->base_name, tv);
2187 result = utimes(smb_fname->base_name, NULL);
2189 if (!((result == -1) && (errno == ENOSYS))) {
2193 #if defined(HAVE_UTIME)
2195 struct utimbuf times;
2196 times.actime = convert_timespec_to_time_t(ft->atime);
2197 times.modtime = convert_timespec_to_time_t(ft->mtime);
2198 result = utime(smb_fname->base_name, ×);
2200 result = utime(smb_fname->base_name, NULL);
2202 if (!((result == -1) && (errno == ENOSYS))) {
2210 END_PROFILE(syscall_ntimes);
2214 /*********************************************************************
2215 A version of ftruncate that will write the space on disk if strict
2217 **********************************************************************/
2219 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2221 off_t space_to_write;
2222 uint64_t space_avail;
2223 uint64_t bsize,dfree,dsize;
2226 SMB_STRUCT_STAT *pst;
2228 status = vfs_stat_fsp(fsp);
2229 if (!NT_STATUS_IS_OK(status)) {
2232 pst = &fsp->fsp_name->st;
2235 if (S_ISFIFO(pst->st_ex_mode))
2239 if (pst->st_ex_size == len)
2242 /* Shrink - just ftruncate. */
2243 if (pst->st_ex_size > len)
2244 return ftruncate(fsp->fh->fd, len);
2246 space_to_write = len - pst->st_ex_size;
2248 /* for allocation try fallocate first. This can fail on some
2249 platforms e.g. when the filesystem doesn't support it and no
2250 emulation is being done by the libc (like on AIX with JFS1). In that
2251 case we do our own emulation. fallocate implementations can
2252 return ENOTSUP or EINVAL in cases like that. */
2253 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2254 if (ret == -1 && errno == ENOSPC) {
2260 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2261 "error %d. Falling back to slow manual allocation\n", errno));
2263 /* available disk space is enough or not? */
2265 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2266 /* space_avail is 1k blocks */
2267 if (space_avail == (uint64_t)-1 ||
2268 ((uint64_t)space_to_write/1024 > space_avail) ) {
2273 /* Write out the real space on disk. */
2274 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2282 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2285 SMB_STRUCT_STAT *pst;
2289 START_PROFILE(syscall_ftruncate);
2291 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2292 result = strict_allocate_ftruncate(handle, fsp, len);
2293 END_PROFILE(syscall_ftruncate);
2297 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2298 ftruncate if the system supports it. Then I discovered that
2299 you can have some filesystems that support ftruncate
2300 expansion and some that don't! On Linux fat can't do
2301 ftruncate extend but ext2 can. */
2303 result = ftruncate(fsp->fh->fd, len);
2305 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2306 extend a file with ftruncate. Provide alternate implementation
2309 /* Do an fstat to see if the file is longer than the requested
2310 size in which case the ftruncate above should have
2311 succeeded or shorter, in which case seek to len - 1 and
2312 write 1 byte of zero */
2313 status = vfs_stat_fsp(fsp);
2314 if (!NT_STATUS_IS_OK(status)) {
2318 /* We need to update the files_struct after successful ftruncate */
2323 pst = &fsp->fsp_name->st;
2326 if (S_ISFIFO(pst->st_ex_mode)) {
2332 if (pst->st_ex_size == len) {
2337 if (pst->st_ex_size > len) {
2338 /* the ftruncate should have worked */
2342 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2350 END_PROFILE(syscall_ftruncate);
2354 static int vfswrap_fallocate(vfs_handle_struct *handle,
2362 START_PROFILE(syscall_fallocate);
2364 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2366 * posix_fallocate returns 0 on success, errno on error
2367 * and doesn't set errno. Make it behave like fallocate()
2368 * which returns -1, and sets errno on failure.
2375 /* sys_fallocate handles filtering of unsupported mode flags */
2376 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2378 END_PROFILE(syscall_fallocate);
2382 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2386 START_PROFILE(syscall_fcntl_lock);
2388 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2390 "force process locks",
2392 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2395 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2396 END_PROFILE(syscall_fcntl_lock);
2400 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2401 uint32_t share_mode, uint32_t access_mask)
2403 START_PROFILE(syscall_kernel_flock);
2404 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2405 END_PROFILE(syscall_kernel_flock);
2409 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2414 START_PROFILE(syscall_fcntl_getlock);
2416 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2418 "force process locks",
2420 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2423 result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2424 END_PROFILE(syscall_fcntl_getlock);
2428 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2433 START_PROFILE(syscall_linux_setlease);
2435 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2436 result = linux_setlease(fsp->fh->fd, leasetype);
2440 END_PROFILE(syscall_linux_setlease);
2444 static int vfswrap_symlink(vfs_handle_struct *handle,
2445 const char *link_target,
2446 const struct smb_filename *new_smb_fname)
2450 START_PROFILE(syscall_symlink);
2451 result = symlink(link_target, new_smb_fname->base_name);
2452 END_PROFILE(syscall_symlink);
2456 static int vfswrap_readlink(vfs_handle_struct *handle,
2457 const struct smb_filename *smb_fname,
2463 START_PROFILE(syscall_readlink);
2464 result = readlink(smb_fname->base_name, buf, bufsiz);
2465 END_PROFILE(syscall_readlink);
2469 static int vfswrap_link(vfs_handle_struct *handle,
2470 const struct smb_filename *old_smb_fname,
2471 const struct smb_filename *new_smb_fname)
2475 START_PROFILE(syscall_link);
2476 result = link(old_smb_fname->base_name, new_smb_fname->base_name);
2477 END_PROFILE(syscall_link);
2481 static int vfswrap_mknod(vfs_handle_struct *handle,
2482 const struct smb_filename *smb_fname,
2488 START_PROFILE(syscall_mknod);
2489 result = sys_mknod(smb_fname->base_name, mode, dev);
2490 END_PROFILE(syscall_mknod);
2494 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2496 const struct smb_filename *smb_fname)
2499 struct smb_filename *result_fname = NULL;
2501 START_PROFILE(syscall_realpath);
2502 result = sys_realpath(smb_fname->base_name);
2503 END_PROFILE(syscall_realpath);
2505 result_fname = synthetic_smb_fname(ctx, result, NULL, NULL, 0);
2508 return result_fname;
2511 static int vfswrap_chflags(vfs_handle_struct *handle,
2512 const struct smb_filename *smb_fname,
2516 return chflags(smb_fname->base_name, flags);
2523 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2524 const SMB_STRUCT_STAT *sbuf)
2528 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2532 key.devid = sbuf->st_ex_dev;
2533 key.inode = sbuf->st_ex_ino;
2534 /* key.extid is unused by default. */
2539 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2540 struct files_struct *fsp,
2541 const struct smb_filename *smb_fname,
2542 TALLOC_CTX *mem_ctx,
2543 unsigned int *pnum_streams,
2544 struct stream_struct **pstreams)
2546 SMB_STRUCT_STAT sbuf;
2547 struct stream_struct *tmp_streams = NULL;
2550 if ((fsp != NULL) && (fsp->is_directory)) {
2552 * No default streams on directories
2557 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2558 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2561 struct smb_filename smb_fname_cp;
2563 ZERO_STRUCT(smb_fname_cp);
2564 smb_fname_cp.base_name = discard_const_p(char,
2565 smb_fname->base_name);
2566 smb_fname_cp.flags = smb_fname->flags;
2568 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
2569 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2571 ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2573 sbuf = smb_fname_cp.st;
2577 return map_nt_error_from_unix(errno);
2580 if (S_ISDIR(sbuf.st_ex_mode)) {
2584 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2585 (*pnum_streams) + 1);
2586 if (tmp_streams == NULL) {
2587 return NT_STATUS_NO_MEMORY;
2589 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2590 if (tmp_streams[*pnum_streams].name == NULL) {
2591 return NT_STATUS_NO_MEMORY;
2593 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2594 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2597 *pstreams = tmp_streams;
2599 return NT_STATUS_OK;
2602 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2605 TALLOC_CTX *mem_ctx,
2609 * Don't fall back to get_real_filename so callers can differentiate
2610 * between a full directory scan and an actual case-insensitive stat.
2616 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2617 const struct smb_filename *smb_fname)
2619 return handle->conn->connectpath;
2622 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2623 struct byte_range_lock *br_lck,
2624 struct lock_struct *plock,
2627 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2629 /* Note: blr is not used in the default implementation. */
2630 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2633 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2634 struct messaging_context *msg_ctx,
2635 struct byte_range_lock *br_lck,
2636 const struct lock_struct *plock)
2638 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2640 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2643 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2644 struct byte_range_lock *br_lck,
2645 struct lock_struct *plock)
2647 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2649 /* Note: blr is not used in the default implementation. */
2650 return brl_lock_cancel_default(br_lck, plock);
2653 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
2655 struct lock_struct *plock)
2657 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2658 plock->lock_type == WRITE_LOCK);
2660 return strict_lock_check_default(fsp, plock);
2663 /* NT ACL operations. */
2665 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2667 uint32_t security_info,
2668 TALLOC_CTX *mem_ctx,
2669 struct security_descriptor **ppdesc)
2673 START_PROFILE(fget_nt_acl);
2674 result = posix_fget_nt_acl(fsp, security_info,
2676 END_PROFILE(fget_nt_acl);
2680 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2681 const struct smb_filename *smb_fname,
2682 uint32_t security_info,
2683 TALLOC_CTX *mem_ctx,
2684 struct security_descriptor **ppdesc)
2688 START_PROFILE(get_nt_acl);
2689 result = posix_get_nt_acl(handle->conn,
2694 END_PROFILE(get_nt_acl);
2698 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2702 START_PROFILE(fset_nt_acl);
2703 result = set_nt_acl(fsp, security_info_sent, psd);
2704 END_PROFILE(fset_nt_acl);
2708 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2709 struct smb_filename *file,
2710 struct security_acl *sacl,
2711 uint32_t access_requested,
2712 uint32_t access_denied)
2714 return NT_STATUS_OK; /* Nothing to do here ... */
2717 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2718 const struct smb_filename *smb_fname,
2719 SMB_ACL_TYPE_T type,
2720 TALLOC_CTX *mem_ctx)
2722 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
2725 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2727 TALLOC_CTX *mem_ctx)
2729 return sys_acl_get_fd(handle, fsp, mem_ctx);
2732 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
2733 const struct smb_filename *smb_fname,
2734 SMB_ACL_TYPE_T acltype,
2737 return sys_acl_set_file(handle, smb_fname, acltype, theacl);
2740 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2742 return sys_acl_set_fd(handle, fsp, theacl);
2745 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
2746 const struct smb_filename *smb_fname)
2748 return sys_acl_delete_def_file(handle, smb_fname);
2751 /****************************************************************
2752 Extended attribute operations.
2753 *****************************************************************/
2755 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
2756 const struct smb_filename *smb_fname,
2761 return getxattr(smb_fname->base_name, name, value, size);
2764 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2766 return fgetxattr(fsp->fh->fd, name, value, size);
2769 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
2770 const struct smb_filename *smb_fname,
2774 return listxattr(smb_fname->base_name, list, size);
2777 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2779 return flistxattr(fsp->fh->fd, list, size);
2782 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
2783 const struct smb_filename *smb_fname,
2786 return removexattr(smb_fname->base_name, name);
2789 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2791 return fremovexattr(fsp->fh->fd, name);
2794 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
2795 const struct smb_filename *smb_fname,
2801 return setxattr(smb_fname->base_name, name, value, size, flags);
2804 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2806 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2809 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2814 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2815 const struct smb_filename *fname,
2816 SMB_STRUCT_STAT *sbuf)
2820 bool offline = false;
2822 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2826 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2827 #if defined(ENOTSUP)
2833 status = get_full_smb_filename(talloc_tos(), fname, &path);
2834 if (!NT_STATUS_IS_OK(status)) {
2835 errno = map_errno_from_nt_status(status);
2839 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2846 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2847 struct files_struct *fsp,
2848 TALLOC_CTX *mem_ctx,
2851 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2854 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2855 struct files_struct *fsp,
2856 const DATA_BLOB old_cookie,
2857 TALLOC_CTX *mem_ctx,
2858 DATA_BLOB *new_cookie)
2860 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2864 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2865 struct smb_request *smb1req,
2866 struct smbXsrv_open *op,
2867 const DATA_BLOB old_cookie,
2868 TALLOC_CTX *mem_ctx,
2869 struct files_struct **fsp,
2870 DATA_BLOB *new_cookie)
2872 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2873 old_cookie, mem_ctx,
2877 static struct vfs_fn_pointers vfs_default_fns = {
2878 /* Disk operations */
2880 .connect_fn = vfswrap_connect,
2881 .disconnect_fn = vfswrap_disconnect,
2882 .disk_free_fn = vfswrap_disk_free,
2883 .get_quota_fn = vfswrap_get_quota,
2884 .set_quota_fn = vfswrap_set_quota,
2885 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2886 .statvfs_fn = vfswrap_statvfs,
2887 .fs_capabilities_fn = vfswrap_fs_capabilities,
2888 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2889 .snap_check_path_fn = vfswrap_snap_check_path,
2890 .snap_create_fn = vfswrap_snap_create,
2891 .snap_delete_fn = vfswrap_snap_delete,
2893 /* Directory operations */
2895 .opendir_fn = vfswrap_opendir,
2896 .fdopendir_fn = vfswrap_fdopendir,
2897 .readdir_fn = vfswrap_readdir,
2898 .readdir_attr_fn = vfswrap_readdir_attr,
2899 .seekdir_fn = vfswrap_seekdir,
2900 .telldir_fn = vfswrap_telldir,
2901 .rewind_dir_fn = vfswrap_rewinddir,
2902 .mkdir_fn = vfswrap_mkdir,
2903 .rmdir_fn = vfswrap_rmdir,
2904 .closedir_fn = vfswrap_closedir,
2906 /* File operations */
2908 .open_fn = vfswrap_open,
2909 .create_file_fn = vfswrap_create_file,
2910 .close_fn = vfswrap_close,
2911 .pread_fn = vfswrap_pread,
2912 .pread_send_fn = vfswrap_pread_send,
2913 .pread_recv_fn = vfswrap_pread_recv,
2914 .pwrite_fn = vfswrap_pwrite,
2915 .pwrite_send_fn = vfswrap_pwrite_send,
2916 .pwrite_recv_fn = vfswrap_pwrite_recv,
2917 .lseek_fn = vfswrap_lseek,
2918 .sendfile_fn = vfswrap_sendfile,
2919 .recvfile_fn = vfswrap_recvfile,
2920 .rename_fn = vfswrap_rename,
2921 .fsync_send_fn = vfswrap_fsync_send,
2922 .fsync_recv_fn = vfswrap_fsync_recv,
2923 .stat_fn = vfswrap_stat,
2924 .fstat_fn = vfswrap_fstat,
2925 .lstat_fn = vfswrap_lstat,
2926 .get_alloc_size_fn = vfswrap_get_alloc_size,
2927 .unlink_fn = vfswrap_unlink,
2928 .chmod_fn = vfswrap_chmod,
2929 .fchmod_fn = vfswrap_fchmod,
2930 .chown_fn = vfswrap_chown,
2931 .fchown_fn = vfswrap_fchown,
2932 .lchown_fn = vfswrap_lchown,
2933 .chdir_fn = vfswrap_chdir,
2934 .getwd_fn = vfswrap_getwd,
2935 .ntimes_fn = vfswrap_ntimes,
2936 .ftruncate_fn = vfswrap_ftruncate,
2937 .fallocate_fn = vfswrap_fallocate,
2938 .lock_fn = vfswrap_lock,
2939 .kernel_flock_fn = vfswrap_kernel_flock,
2940 .linux_setlease_fn = vfswrap_linux_setlease,
2941 .getlock_fn = vfswrap_getlock,
2942 .symlink_fn = vfswrap_symlink,
2943 .readlink_fn = vfswrap_readlink,
2944 .link_fn = vfswrap_link,
2945 .mknod_fn = vfswrap_mknod,
2946 .realpath_fn = vfswrap_realpath,
2947 .chflags_fn = vfswrap_chflags,
2948 .file_id_create_fn = vfswrap_file_id_create,
2949 .streaminfo_fn = vfswrap_streaminfo,
2950 .get_real_filename_fn = vfswrap_get_real_filename,
2951 .connectpath_fn = vfswrap_connectpath,
2952 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2953 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2954 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2955 .strict_lock_check_fn = vfswrap_strict_lock_check,
2956 .translate_name_fn = vfswrap_translate_name,
2957 .fsctl_fn = vfswrap_fsctl,
2958 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
2959 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
2960 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
2961 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
2962 .offload_read_send_fn = vfswrap_offload_read_send,
2963 .offload_read_recv_fn = vfswrap_offload_read_recv,
2964 .offload_write_send_fn = vfswrap_offload_write_send,
2965 .offload_write_recv_fn = vfswrap_offload_write_recv,
2966 .get_compression_fn = vfswrap_get_compression,
2967 .set_compression_fn = vfswrap_set_compression,
2969 /* NT ACL operations. */
2971 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2972 .get_nt_acl_fn = vfswrap_get_nt_acl,
2973 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2974 .audit_file_fn = vfswrap_audit_file,
2976 /* POSIX ACL operations. */
2978 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2979 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2980 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2981 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2982 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2983 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2984 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2986 /* EA operations. */
2987 .getxattr_fn = vfswrap_getxattr,
2988 .fgetxattr_fn = vfswrap_fgetxattr,
2989 .listxattr_fn = vfswrap_listxattr,
2990 .flistxattr_fn = vfswrap_flistxattr,
2991 .removexattr_fn = vfswrap_removexattr,
2992 .fremovexattr_fn = vfswrap_fremovexattr,
2993 .setxattr_fn = vfswrap_setxattr,
2994 .fsetxattr_fn = vfswrap_fsetxattr,
2996 /* aio operations */
2997 .aio_force_fn = vfswrap_aio_force,
2999 /* durable handle operations */
3000 .durable_cookie_fn = vfswrap_durable_cookie,
3001 .durable_disconnect_fn = vfswrap_durable_disconnect,
3002 .durable_reconnect_fn = vfswrap_durable_reconnect,
3006 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3009 * Here we need to implement every call!
3011 * As this is the end of the vfs module chain.
3013 smb_vfs_assert_all_fns(&vfs_default_fns, DEFAULT_VFS_MODULE_NAME);
3014 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3015 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);