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 bool has_dacl = False;
502 const char *path = smb_fname->base_name;
505 START_PROFILE(syscall_mkdir);
507 if (lp_inherit_acls(SNUM(handle->conn))
508 && parent_dirname(talloc_tos(), path, &parent, NULL)
509 && (has_dacl = directory_has_default_acl(handle->conn, parent))) {
510 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
515 result = mkdir(path, mode);
517 if (result == 0 && !has_dacl) {
519 * We need to do this as the default behavior of POSIX ACLs
520 * is to set the mask to be the requested group permission
521 * bits, not the group permission bits to be the requested
522 * group permission bits. This is not what we want, as it will
523 * mess up any inherited ACL bits that were set. JRA.
525 int saved_errno = errno; /* We may get ENOSYS */
526 if ((SMB_VFS_CHMOD_ACL(handle->conn, smb_fname, mode) == -1) &&
532 END_PROFILE(syscall_mkdir);
536 static int vfswrap_rmdir(vfs_handle_struct *handle,
537 const struct smb_filename *smb_fname)
541 START_PROFILE(syscall_rmdir);
542 result = rmdir(smb_fname->base_name);
543 END_PROFILE(syscall_rmdir);
547 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
551 START_PROFILE(syscall_closedir);
552 result = closedir(dirp);
553 END_PROFILE(syscall_closedir);
557 /* File operations */
559 static int vfswrap_open(vfs_handle_struct *handle,
560 struct smb_filename *smb_fname,
561 files_struct *fsp, int flags, mode_t mode)
565 START_PROFILE(syscall_open);
567 if (smb_fname->stream_name) {
572 result = open(smb_fname->base_name, flags, mode);
574 END_PROFILE(syscall_open);
578 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
579 struct smb_request *req,
580 uint16_t root_dir_fid,
581 struct smb_filename *smb_fname,
582 uint32_t access_mask,
583 uint32_t share_access,
584 uint32_t create_disposition,
585 uint32_t create_options,
586 uint32_t file_attributes,
587 uint32_t oplock_request,
588 struct smb2_lease *lease,
589 uint64_t allocation_size,
590 uint32_t private_flags,
591 struct security_descriptor *sd,
592 struct ea_list *ea_list,
593 files_struct **result,
595 const struct smb2_create_blobs *in_context_blobs,
596 struct smb2_create_blobs *out_context_blobs)
598 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
599 access_mask, share_access,
600 create_disposition, create_options,
601 file_attributes, oplock_request, lease,
602 allocation_size, private_flags,
604 pinfo, in_context_blobs, out_context_blobs);
607 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
611 START_PROFILE(syscall_close);
612 result = fd_close_posix(fsp);
613 END_PROFILE(syscall_close);
617 static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
621 START_PROFILE_BYTES(syscall_read, n);
622 result = sys_read(fsp->fh->fd, data, n);
623 END_PROFILE_BYTES(syscall_read);
627 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
628 size_t n, off_t offset)
632 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
633 START_PROFILE_BYTES(syscall_pread, n);
634 result = sys_pread(fsp->fh->fd, data, n, offset);
635 END_PROFILE_BYTES(syscall_pread);
637 if (result == -1 && errno == ESPIPE) {
638 /* Maintain the fiction that pipes can be seeked (sought?) on. */
639 result = SMB_VFS_READ(fsp, data, n);
643 #else /* HAVE_PREAD */
646 #endif /* HAVE_PREAD */
651 static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
655 START_PROFILE_BYTES(syscall_write, n);
656 result = sys_write(fsp->fh->fd, data, n);
657 END_PROFILE_BYTES(syscall_write);
661 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
662 size_t n, off_t offset)
666 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
667 START_PROFILE_BYTES(syscall_pwrite, n);
668 result = sys_pwrite(fsp->fh->fd, data, n, offset);
669 END_PROFILE_BYTES(syscall_pwrite);
671 if (result == -1 && errno == ESPIPE) {
672 /* Maintain the fiction that pipes can be sought on. */
673 result = SMB_VFS_WRITE(fsp, data, n);
676 #else /* HAVE_PWRITE */
680 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
685 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
689 result = SMB_VFS_WRITE(fsp, data, n);
692 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
695 #endif /* HAVE_PWRITE */
700 struct vfswrap_pread_state {
707 struct vfs_aio_state vfs_aio_state;
708 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
711 static void vfs_pread_do(void *private_data);
712 static void vfs_pread_done(struct tevent_req *subreq);
713 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state);
715 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
717 struct tevent_context *ev,
718 struct files_struct *fsp,
720 size_t n, off_t offset)
722 struct tevent_req *req, *subreq;
723 struct vfswrap_pread_state *state;
725 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
731 state->fd = fsp->fh->fd;
734 state->offset = offset;
736 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
737 state->profile_bytes, n);
738 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
740 subreq = pthreadpool_tevent_job_send(
741 state, ev, handle->conn->sconn->pool,
742 vfs_pread_do, state);
743 if (tevent_req_nomem(subreq, req)) {
744 return tevent_req_post(req, ev);
746 tevent_req_set_callback(subreq, vfs_pread_done, req);
748 talloc_set_destructor(state, vfs_pread_state_destructor);
753 static void vfs_pread_do(void *private_data)
755 struct vfswrap_pread_state *state = talloc_get_type_abort(
756 private_data, struct vfswrap_pread_state);
757 struct timespec start_time;
758 struct timespec end_time;
760 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
762 PROFILE_TIMESTAMP(&start_time);
765 state->ret = pread(state->fd, state->buf, state->count,
767 } while ((state->ret == -1) && (errno == EINTR));
769 if (state->ret == -1) {
770 state->vfs_aio_state.error = errno;
773 PROFILE_TIMESTAMP(&end_time);
775 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
777 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
780 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state)
785 static void vfs_pread_done(struct tevent_req *subreq)
787 struct tevent_req *req = tevent_req_callback_data(
788 subreq, struct tevent_req);
789 struct vfswrap_pread_state *state = tevent_req_data(
790 req, struct vfswrap_pread_state);
793 ret = pthreadpool_tevent_job_recv(subreq);
795 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
796 talloc_set_destructor(state, NULL);
797 if (tevent_req_error(req, ret)) {
801 tevent_req_done(req);
804 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
805 struct vfs_aio_state *vfs_aio_state)
807 struct vfswrap_pread_state *state = tevent_req_data(
808 req, struct vfswrap_pread_state);
810 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
814 *vfs_aio_state = state->vfs_aio_state;
818 struct vfswrap_pwrite_state {
825 struct vfs_aio_state vfs_aio_state;
826 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
829 static void vfs_pwrite_do(void *private_data);
830 static void vfs_pwrite_done(struct tevent_req *subreq);
831 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state);
833 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
835 struct tevent_context *ev,
836 struct files_struct *fsp,
838 size_t n, off_t offset)
840 struct tevent_req *req, *subreq;
841 struct vfswrap_pwrite_state *state;
843 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
849 state->fd = fsp->fh->fd;
852 state->offset = offset;
854 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
855 state->profile_bytes, n);
856 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
858 subreq = pthreadpool_tevent_job_send(
859 state, ev, handle->conn->sconn->pool,
860 vfs_pwrite_do, state);
861 if (tevent_req_nomem(subreq, req)) {
862 return tevent_req_post(req, ev);
864 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
866 talloc_set_destructor(state, vfs_pwrite_state_destructor);
871 static void vfs_pwrite_do(void *private_data)
873 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
874 private_data, struct vfswrap_pwrite_state);
875 struct timespec start_time;
876 struct timespec end_time;
878 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
880 PROFILE_TIMESTAMP(&start_time);
883 state->ret = pwrite(state->fd, state->buf, state->count,
885 } while ((state->ret == -1) && (errno == EINTR));
887 if (state->ret == -1) {
888 state->vfs_aio_state.error = errno;
891 PROFILE_TIMESTAMP(&end_time);
893 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
895 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
898 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state)
903 static void vfs_pwrite_done(struct tevent_req *subreq)
905 struct tevent_req *req = tevent_req_callback_data(
906 subreq, struct tevent_req);
907 struct vfswrap_pwrite_state *state = tevent_req_data(
908 req, struct vfswrap_pwrite_state);
911 ret = pthreadpool_tevent_job_recv(subreq);
913 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
914 talloc_set_destructor(state, NULL);
915 if (tevent_req_error(req, ret)) {
919 tevent_req_done(req);
922 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
923 struct vfs_aio_state *vfs_aio_state)
925 struct vfswrap_pwrite_state *state = tevent_req_data(
926 req, struct vfswrap_pwrite_state);
928 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
932 *vfs_aio_state = state->vfs_aio_state;
936 struct vfswrap_fsync_state {
940 struct vfs_aio_state vfs_aio_state;
941 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
944 static void vfs_fsync_do(void *private_data);
945 static void vfs_fsync_done(struct tevent_req *subreq);
946 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state);
948 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
950 struct tevent_context *ev,
951 struct files_struct *fsp)
953 struct tevent_req *req, *subreq;
954 struct vfswrap_fsync_state *state;
956 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
962 state->fd = fsp->fh->fd;
964 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
965 state->profile_basic);
967 subreq = pthreadpool_tevent_job_send(
968 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
969 if (tevent_req_nomem(subreq, req)) {
970 return tevent_req_post(req, ev);
972 tevent_req_set_callback(subreq, vfs_fsync_done, req);
974 talloc_set_destructor(state, vfs_fsync_state_destructor);
979 static void vfs_fsync_do(void *private_data)
981 struct vfswrap_fsync_state *state = talloc_get_type_abort(
982 private_data, struct vfswrap_fsync_state);
983 struct timespec start_time;
984 struct timespec end_time;
986 PROFILE_TIMESTAMP(&start_time);
989 state->ret = fsync(state->fd);
990 } while ((state->ret == -1) && (errno == EINTR));
992 if (state->ret == -1) {
993 state->vfs_aio_state.error = errno;
996 PROFILE_TIMESTAMP(&end_time);
998 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1001 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state)
1006 static void vfs_fsync_done(struct tevent_req *subreq)
1008 struct tevent_req *req = tevent_req_callback_data(
1009 subreq, struct tevent_req);
1010 struct vfswrap_fsync_state *state = tevent_req_data(
1011 req, struct vfswrap_fsync_state);
1014 ret = pthreadpool_tevent_job_recv(subreq);
1015 TALLOC_FREE(subreq);
1016 SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
1017 talloc_set_destructor(state, NULL);
1018 if (tevent_req_error(req, ret)) {
1022 tevent_req_done(req);
1025 static int vfswrap_fsync_recv(struct tevent_req *req,
1026 struct vfs_aio_state *vfs_aio_state)
1028 struct vfswrap_fsync_state *state = tevent_req_data(
1029 req, struct vfswrap_fsync_state);
1031 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1035 *vfs_aio_state = state->vfs_aio_state;
1039 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1043 START_PROFILE(syscall_lseek);
1045 /* Cope with 'stat' file opens. */
1046 if (fsp->fh->fd != -1)
1047 result = lseek(fsp->fh->fd, offset, whence);
1050 * We want to maintain the fiction that we can seek
1051 * on a fifo for file system purposes. This allows
1052 * people to set up UNIX fifo's that feed data to Windows
1053 * applications. JRA.
1056 if((result == -1) && (errno == ESPIPE)) {
1061 END_PROFILE(syscall_lseek);
1065 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1066 off_t offset, size_t n)
1070 START_PROFILE_BYTES(syscall_sendfile, n);
1071 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
1072 END_PROFILE_BYTES(syscall_sendfile);
1076 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1078 files_struct *tofsp,
1084 START_PROFILE_BYTES(syscall_recvfile, n);
1085 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
1086 END_PROFILE_BYTES(syscall_recvfile);
1090 static int vfswrap_rename(vfs_handle_struct *handle,
1091 const struct smb_filename *smb_fname_src,
1092 const struct smb_filename *smb_fname_dst)
1096 START_PROFILE(syscall_rename);
1098 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
1103 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
1106 END_PROFILE(syscall_rename);
1110 static int vfswrap_stat(vfs_handle_struct *handle,
1111 struct smb_filename *smb_fname)
1115 START_PROFILE(syscall_stat);
1117 if (smb_fname->stream_name) {
1122 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1123 lp_fake_directory_create_times(SNUM(handle->conn)));
1125 END_PROFILE(syscall_stat);
1129 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1133 START_PROFILE(syscall_fstat);
1134 result = sys_fstat(fsp->fh->fd,
1135 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1136 END_PROFILE(syscall_fstat);
1140 static int vfswrap_lstat(vfs_handle_struct *handle,
1141 struct smb_filename *smb_fname)
1145 START_PROFILE(syscall_lstat);
1147 if (smb_fname->stream_name) {
1152 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1153 lp_fake_directory_create_times(SNUM(handle->conn)));
1155 END_PROFILE(syscall_lstat);
1159 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1161 enum vfs_translate_direction direction,
1162 TALLOC_CTX *mem_ctx,
1165 return NT_STATUS_NONE_MAPPED;
1169 * Implement the default fsctl operation.
1171 static bool vfswrap_logged_ioctl_message = false;
1173 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1174 struct files_struct *fsp,
1177 uint16_t req_flags, /* Needed for UNICODE ... */
1178 const uint8_t *_in_data,
1180 uint8_t **_out_data,
1181 uint32_t max_out_len,
1184 const char *in_data = (const char *)_in_data;
1185 char **out_data = (char **)_out_data;
1189 case FSCTL_SET_SPARSE:
1191 bool set_sparse = true;
1193 if (in_len >= 1 && in_data[0] == 0) {
1197 status = file_set_sparse(handle->conn, fsp, set_sparse);
1199 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1200 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1201 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1202 nt_errstr(status)));
1207 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1209 unsigned char objid[16];
1210 char *return_data = NULL;
1212 /* This should return the object-id on this file.
1213 * I think I'll make this be the inode+dev. JRA.
1216 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1217 fsp_fnum_dbg(fsp)));
1219 *out_len = MIN(max_out_len, 64);
1221 /* Hmmm, will this cause problems if less data asked for? */
1222 return_data = talloc_array(ctx, char, 64);
1223 if (return_data == NULL) {
1224 return NT_STATUS_NO_MEMORY;
1227 /* For backwards compatibility only store the dev/inode. */
1228 push_file_id_16(return_data, &fsp->file_id);
1229 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1230 push_file_id_16(return_data+32, &fsp->file_id);
1231 memset(return_data+48, 0, 16);
1232 *out_data = return_data;
1233 return NT_STATUS_OK;
1236 case FSCTL_GET_REPARSE_POINT:
1238 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1239 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1240 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1241 return NT_STATUS_NOT_A_REPARSE_POINT;
1244 case FSCTL_SET_REPARSE_POINT:
1246 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1247 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1248 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1249 return NT_STATUS_NOT_A_REPARSE_POINT;
1252 case FSCTL_GET_SHADOW_COPY_DATA:
1255 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1256 * and return their volume names. If max_data_count is 16, then it is just
1257 * asking for the number of volumes and length of the combined names.
1259 * pdata is the data allocated by our caller, but that uses
1260 * total_data_count (which is 0 in our case) rather than max_data_count.
1261 * Allocate the correct amount and return the pointer to let
1262 * it be deallocated when we return.
1264 struct shadow_copy_data *shadow_data = NULL;
1265 bool labels = False;
1266 uint32_t labels_data_count = 0;
1268 char *cur_pdata = NULL;
1270 if (max_out_len < 16) {
1271 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1273 return NT_STATUS_INVALID_PARAMETER;
1276 if (max_out_len > 16) {
1280 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1281 if (shadow_data == NULL) {
1282 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1283 return NT_STATUS_NO_MEMORY;
1287 * Call the VFS routine to actually do the work.
1289 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1292 /* broken module didn't set errno on error */
1293 status = NT_STATUS_UNSUCCESSFUL;
1295 status = map_nt_error_from_unix(errno);
1296 if (NT_STATUS_EQUAL(status,
1297 NT_STATUS_NOT_SUPPORTED)) {
1301 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1302 "connectpath %s, failed - %s.\n",
1303 fsp->conn->connectpath,
1304 nt_errstr(status)));
1305 TALLOC_FREE(shadow_data);
1309 labels_data_count = (shadow_data->num_volumes * 2 *
1310 sizeof(SHADOW_COPY_LABEL)) + 2;
1315 *out_len = 12 + labels_data_count;
1318 if (max_out_len < *out_len) {
1319 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1320 max_out_len, *out_len));
1321 TALLOC_FREE(shadow_data);
1322 return NT_STATUS_BUFFER_TOO_SMALL;
1325 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1326 if (cur_pdata == NULL) {
1327 TALLOC_FREE(shadow_data);
1328 return NT_STATUS_NO_MEMORY;
1331 *out_data = cur_pdata;
1333 /* num_volumes 4 bytes */
1334 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1337 /* num_labels 4 bytes */
1338 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1341 /* needed_data_count 4 bytes */
1342 SIVAL(cur_pdata, 8, labels_data_count);
1346 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1347 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1348 if (labels && shadow_data->labels) {
1349 for (i=0; i<shadow_data->num_volumes; i++) {
1351 status = srvstr_push(cur_pdata, req_flags,
1352 cur_pdata, shadow_data->labels[i],
1353 2 * sizeof(SHADOW_COPY_LABEL),
1354 STR_UNICODE|STR_TERMINATE, &len);
1355 if (!NT_STATUS_IS_OK(status)) {
1356 TALLOC_FREE(*out_data);
1357 TALLOC_FREE(shadow_data);
1360 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1361 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1365 TALLOC_FREE(shadow_data);
1367 return NT_STATUS_OK;
1370 case FSCTL_FIND_FILES_BY_SID:
1372 /* pretend this succeeded -
1374 * we have to send back a list with all files owned by this SID
1376 * but I have to check that --metze
1382 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1383 fsp_fnum_dbg(fsp)));
1386 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1387 return NT_STATUS_INVALID_PARAMETER;
1390 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1392 /* unknown 4 bytes: this is not the length of the sid :-( */
1393 /*unknown = IVAL(pdata,0);*/
1395 if (!sid_parse(_in_data + 4, sid_len, &sid)) {
1396 return NT_STATUS_INVALID_PARAMETER;
1398 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1400 if (!sid_to_uid(&sid, &uid)) {
1401 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1402 sid_string_dbg(&sid),
1403 (unsigned long)sid_len));
1407 /* we can take a look at the find source :-)
1409 * find ./ -uid $uid -name '*' is what we need here
1412 * and send 4bytes len and then NULL terminated unicode strings
1415 * but I don't know how to deal with the paged results
1416 * (maybe we can hang the result anywhere in the fsp struct)
1418 * but I don't know how to deal with the paged results
1419 * (maybe we can hang the result anywhere in the fsp struct)
1421 * we don't send all files at once
1422 * and at the next we should *not* start from the beginning,
1423 * so we have to cache the result
1428 /* this works for now... */
1429 return NT_STATUS_OK;
1432 case FSCTL_QUERY_ALLOCATED_RANGES:
1434 /* FIXME: This is just a dummy reply, telling that all of the
1435 * file is allocated. MKS cp needs that.
1436 * Adding the real allocated ranges via FIEMAP on Linux
1437 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1438 * this FSCTL correct for sparse files.
1440 uint64_t offset, length;
1441 char *out_data_tmp = NULL;
1444 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1446 return NT_STATUS_INVALID_PARAMETER;
1449 if (max_out_len < 16) {
1450 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1452 return NT_STATUS_INVALID_PARAMETER;
1455 offset = BVAL(in_data,0);
1456 length = BVAL(in_data,8);
1458 if (offset + length < offset) {
1459 /* No 64-bit integer wrap. */
1460 return NT_STATUS_INVALID_PARAMETER;
1463 /* Shouldn't this be SMB_VFS_STAT ... ? */
1464 status = vfs_stat_fsp(fsp);
1465 if (!NT_STATUS_IS_OK(status)) {
1470 out_data_tmp = talloc_array(ctx, char, *out_len);
1471 if (out_data_tmp == NULL) {
1472 DEBUG(10, ("unable to allocate memory for response\n"));
1473 return NT_STATUS_NO_MEMORY;
1476 if (offset > fsp->fsp_name->st.st_ex_size ||
1477 fsp->fsp_name->st.st_ex_size == 0 ||
1479 memset(out_data_tmp, 0, *out_len);
1481 uint64_t end = offset + length;
1482 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1483 SBVAL(out_data_tmp, 0, 0);
1484 SBVAL(out_data_tmp, 8, end);
1487 *out_data = out_data_tmp;
1489 return NT_STATUS_OK;
1492 case FSCTL_IS_VOLUME_DIRTY:
1494 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1495 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1497 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1498 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1500 return NT_STATUS_INVALID_PARAMETER;
1505 * Only print once ... unfortunately there could be lots of
1506 * different FSCTLs that are called.
1508 if (!vfswrap_logged_ioctl_message) {
1509 vfswrap_logged_ioctl_message = true;
1510 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1511 __func__, function));
1515 return NT_STATUS_NOT_SUPPORTED;
1518 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
1519 const struct smb_filename *fname,
1520 SMB_STRUCT_STAT *sbuf);
1522 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1523 struct smb_filename *smb_fname,
1528 offline = vfswrap_is_offline(handle, smb_fname, &smb_fname->st);
1530 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1533 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1536 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1537 struct files_struct *fsp,
1542 offline = vfswrap_is_offline(handle, fsp->fsp_name, &fsp->fsp_name->st);
1544 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1547 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1550 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1551 const struct smb_filename *smb_fname,
1554 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1557 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1558 struct files_struct *fsp,
1561 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1564 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1566 struct vfswrap_offload_read_state {
1570 static struct tevent_req *vfswrap_offload_read_send(
1571 TALLOC_CTX *mem_ctx,
1572 struct tevent_context *ev,
1573 struct vfs_handle_struct *handle,
1574 struct files_struct *fsp,
1580 struct tevent_req *req = NULL;
1581 struct vfswrap_offload_read_state *state = NULL;
1584 req = tevent_req_create(mem_ctx, &state,
1585 struct vfswrap_offload_read_state);
1590 status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1591 &vfswrap_offload_ctx);
1592 if (tevent_req_nterror(req, status)) {
1593 return tevent_req_post(req, ev);
1596 if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1597 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1598 return tevent_req_post(req, ev);
1601 status = vfs_offload_token_create_blob(state, fsp, fsctl,
1603 if (tevent_req_nterror(req, status)) {
1604 return tevent_req_post(req, ev);
1607 status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1609 if (tevent_req_nterror(req, status)) {
1610 return tevent_req_post(req, ev);
1613 tevent_req_done(req);
1614 return tevent_req_post(req, ev);
1617 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
1618 struct vfs_handle_struct *handle,
1619 TALLOC_CTX *mem_ctx,
1622 struct vfswrap_offload_read_state *state = tevent_req_data(
1623 req, struct vfswrap_offload_read_state);
1626 if (tevent_req_is_nterror(req, &status)) {
1627 tevent_req_received(req);
1631 token->length = state->token.length;
1632 token->data = talloc_move(mem_ctx, &state->token.data);
1634 tevent_req_received(req);
1635 return NT_STATUS_OK;
1638 struct vfswrap_offload_write_state {
1639 struct tevent_context *ev;
1641 bool read_lck_locked;
1642 bool write_lck_locked;
1644 struct files_struct *src_fsp;
1646 struct files_struct *dst_fsp;
1650 size_t next_io_size;
1653 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
1655 static struct tevent_req *vfswrap_offload_write_send(
1656 struct vfs_handle_struct *handle,
1657 TALLOC_CTX *mem_ctx,
1658 struct tevent_context *ev,
1661 off_t transfer_offset,
1662 struct files_struct *dest_fsp,
1666 struct tevent_req *req;
1667 struct vfswrap_offload_write_state *state = NULL;
1668 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
1669 files_struct *src_fsp = NULL;
1672 req = tevent_req_create(mem_ctx, &state,
1673 struct vfswrap_offload_write_state);
1678 *state = (struct vfswrap_offload_write_state) {
1681 .src_off = transfer_offset,
1682 .dst_fsp = dest_fsp,
1683 .dst_off = dest_off,
1685 .remaining = to_copy,
1689 case FSCTL_SRV_COPYCHUNK:
1690 case FSCTL_SRV_COPYCHUNK_WRITE:
1693 case FSCTL_OFFLOAD_WRITE:
1694 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
1695 return tevent_req_post(req, ev);
1697 case FSCTL_DUP_EXTENTS_TO_FILE:
1698 DBG_DEBUG("COW clones not supported by vfs_default\n");
1699 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1700 return tevent_req_post(req, ev);
1703 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1704 return tevent_req_post(req, ev);
1708 * From here on we assume a copy-chunk fsctl
1712 tevent_req_done(req);
1713 return tevent_req_post(req, ev);
1716 status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
1718 if (tevent_req_nterror(req, status)) {
1719 return tevent_req_post(req, ev);
1721 state->src_fsp = src_fsp;
1723 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
1725 status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
1726 if (!NT_STATUS_IS_OK(status)) {
1727 tevent_req_nterror(req, status);
1728 return tevent_req_post(req, ev);
1731 state->buf = talloc_array(state, uint8_t, num);
1732 if (tevent_req_nomem(state->buf, req)) {
1733 return tevent_req_post(req, ev);
1736 status = vfs_stat_fsp(src_fsp);
1737 if (tevent_req_nterror(req, status)) {
1738 return tevent_req_post(req, ev);
1741 if (src_fsp->fsp_name->st.st_ex_size < state->src_off + num) {
1743 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1744 * If the SourceOffset or SourceOffset + Length extends beyond
1745 * the end of file, the server SHOULD<240> treat this as a
1746 * STATUS_END_OF_FILE error.
1748 * <240> Section 3.3.5.15.6: Windows servers will return
1749 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1751 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1752 return tevent_req_post(req, ev);
1755 if (src_fsp->op == NULL) {
1756 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1757 return tevent_req_post(req, ev);
1760 if (dest_fsp->op == NULL) {
1761 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1762 return tevent_req_post(req, ev);
1765 status = vfswrap_offload_write_loop(req);
1766 if (!NT_STATUS_IS_OK(status)) {
1767 tevent_req_nterror(req, status);
1768 return tevent_req_post(req, ev);
1774 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
1776 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
1778 struct vfswrap_offload_write_state *state = tevent_req_data(
1779 req, struct vfswrap_offload_write_state);
1780 struct tevent_req *subreq = NULL;
1781 struct lock_struct read_lck;
1784 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
1786 init_strict_lock_struct(state->src_fsp,
1787 state->src_fsp->op->global->open_persistent_id,
1789 state->next_io_size,
1793 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
1797 return NT_STATUS_FILE_LOCK_CONFLICT;
1800 subreq = SMB_VFS_PREAD_SEND(state,
1801 state->src_fsp->conn->sconn->ev_ctx,
1804 state->next_io_size,
1806 if (subreq == NULL) {
1807 return NT_STATUS_NO_MEMORY;
1809 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
1811 return NT_STATUS_OK;
1814 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
1816 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
1818 struct tevent_req *req = tevent_req_callback_data(
1819 subreq, struct tevent_req);
1820 struct vfswrap_offload_write_state *state = tevent_req_data(
1821 req, struct vfswrap_offload_write_state);
1822 struct vfs_aio_state aio_state;
1823 struct lock_struct write_lck;
1827 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
1828 TALLOC_FREE(subreq);
1830 DBG_ERR("read failed: %s\n", strerror(errno));
1831 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1834 if (nread != state->next_io_size) {
1835 DBG_ERR("Short read, only %zd of %zu\n",
1836 nread, state->next_io_size);
1837 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1841 state->src_off += nread;
1843 init_strict_lock_struct(state->dst_fsp,
1844 state->dst_fsp->op->global->open_persistent_id,
1846 state->next_io_size,
1850 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
1854 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1858 subreq = SMB_VFS_PWRITE_SEND(state,
1862 state->next_io_size,
1864 if (subreq == NULL) {
1865 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1868 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
1871 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
1873 struct tevent_req *req = tevent_req_callback_data(
1874 subreq, struct tevent_req);
1875 struct vfswrap_offload_write_state *state = tevent_req_data(
1876 req, struct vfswrap_offload_write_state);
1877 struct vfs_aio_state aio_state;
1881 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
1882 TALLOC_FREE(subreq);
1883 if (nwritten == -1) {
1884 DBG_ERR("write failed: %s\n", strerror(errno));
1885 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1888 if (nwritten != state->next_io_size) {
1889 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
1890 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1894 state->dst_off += nwritten;
1896 if (state->remaining < nwritten) {
1897 /* Paranoia check */
1898 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1901 state->remaining -= nwritten;
1902 if (state->remaining == 0) {
1903 tevent_req_done(req);
1907 status = vfswrap_offload_write_loop(req);
1908 if (!NT_STATUS_IS_OK(status)) {
1909 tevent_req_nterror(req, status);
1916 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
1917 struct tevent_req *req,
1920 struct vfswrap_offload_write_state *state = tevent_req_data(
1921 req, struct vfswrap_offload_write_state);
1924 if (tevent_req_is_nterror(req, &status)) {
1925 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
1927 tevent_req_received(req);
1931 *copied = state->to_copy;
1932 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
1933 tevent_req_received(req);
1935 return NT_STATUS_OK;
1938 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1939 TALLOC_CTX *mem_ctx,
1940 struct files_struct *fsp,
1941 struct smb_filename *smb_fname,
1942 uint16_t *_compression_fmt)
1944 return NT_STATUS_INVALID_DEVICE_REQUEST;
1947 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1948 TALLOC_CTX *mem_ctx,
1949 struct files_struct *fsp,
1950 uint16_t compression_fmt)
1952 return NT_STATUS_INVALID_DEVICE_REQUEST;
1955 /********************************************************************
1956 Given a stat buffer return the allocated size on disk, taking into
1957 account sparse files.
1958 ********************************************************************/
1959 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1960 struct files_struct *fsp,
1961 const SMB_STRUCT_STAT *sbuf)
1965 START_PROFILE(syscall_get_alloc_size);
1967 if(S_ISDIR(sbuf->st_ex_mode)) {
1972 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1973 /* The type of st_blocksize is blkcnt_t which *MUST* be
1974 signed (according to POSIX) and can be less than 64-bits.
1975 Ensure when we're converting to 64 bits wide we don't
1977 #if defined(SIZEOF_BLKCNT_T_8)
1978 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1979 #elif defined(SIZEOF_BLKCNT_T_4)
1981 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1982 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1985 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1989 * Some file systems do not allocate a block for very
1990 * small files. But for non-empty file should report a
1994 uint64_t filesize = get_file_size_stat(sbuf);
1996 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2000 result = get_file_size_stat(sbuf);
2003 if (fsp && fsp->initial_allocation_size)
2004 result = MAX(result,fsp->initial_allocation_size);
2006 result = smb_roundup(handle->conn, result);
2009 END_PROFILE(syscall_get_alloc_size);
2013 static int vfswrap_unlink(vfs_handle_struct *handle,
2014 const struct smb_filename *smb_fname)
2018 START_PROFILE(syscall_unlink);
2020 if (smb_fname->stream_name) {
2024 result = unlink(smb_fname->base_name);
2027 END_PROFILE(syscall_unlink);
2031 static int vfswrap_chmod(vfs_handle_struct *handle,
2032 const struct smb_filename *smb_fname,
2037 START_PROFILE(syscall_chmod);
2040 * We need to do this due to the fact that the default POSIX ACL
2041 * chmod modifies the ACL *mask* for the group owner, not the
2042 * group owner bits directly. JRA.
2047 int saved_errno = errno; /* We might get ENOSYS */
2048 result = SMB_VFS_CHMOD_ACL(handle->conn,
2052 END_PROFILE(syscall_chmod);
2055 /* Error - return the old errno. */
2056 errno = saved_errno;
2059 result = chmod(smb_fname->base_name, mode);
2060 END_PROFILE(syscall_chmod);
2064 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2068 START_PROFILE(syscall_fchmod);
2071 * We need to do this due to the fact that the default POSIX ACL
2072 * chmod modifies the ACL *mask* for the group owner, not the
2073 * group owner bits directly. JRA.
2077 int saved_errno = errno; /* We might get ENOSYS */
2078 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
2079 END_PROFILE(syscall_fchmod);
2082 /* Error - return the old errno. */
2083 errno = saved_errno;
2086 #if defined(HAVE_FCHMOD)
2087 result = fchmod(fsp->fh->fd, mode);
2093 END_PROFILE(syscall_fchmod);
2097 static int vfswrap_chown(vfs_handle_struct *handle,
2098 const struct smb_filename *smb_fname,
2104 START_PROFILE(syscall_chown);
2105 result = chown(smb_fname->base_name, uid, gid);
2106 END_PROFILE(syscall_chown);
2110 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2115 START_PROFILE(syscall_fchown);
2116 result = fchown(fsp->fh->fd, uid, gid);
2117 END_PROFILE(syscall_fchown);
2125 static int vfswrap_lchown(vfs_handle_struct *handle,
2126 const struct smb_filename *smb_fname,
2132 START_PROFILE(syscall_lchown);
2133 result = lchown(smb_fname->base_name, uid, gid);
2134 END_PROFILE(syscall_lchown);
2138 static int vfswrap_chdir(vfs_handle_struct *handle,
2139 const struct smb_filename *smb_fname)
2143 START_PROFILE(syscall_chdir);
2144 result = chdir(smb_fname->base_name);
2145 END_PROFILE(syscall_chdir);
2149 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2153 struct smb_filename *smb_fname = NULL;
2155 START_PROFILE(syscall_getwd);
2156 result = sys_getwd();
2157 END_PROFILE(syscall_getwd);
2159 if (result == NULL) {
2162 smb_fname = synthetic_smb_fname(ctx,
2168 * sys_getwd() *always* returns malloced memory.
2169 * We must free here to avoid leaks:
2170 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2176 /*********************************************************************
2177 nsec timestamp resolution call. Convert down to whatever the underlying
2178 system will support.
2179 **********************************************************************/
2181 static int vfswrap_ntimes(vfs_handle_struct *handle,
2182 const struct smb_filename *smb_fname,
2183 struct smb_file_time *ft)
2187 START_PROFILE(syscall_ntimes);
2189 if (smb_fname->stream_name) {
2195 if (null_timespec(ft->atime)) {
2196 ft->atime= smb_fname->st.st_ex_atime;
2199 if (null_timespec(ft->mtime)) {
2200 ft->mtime = smb_fname->st.st_ex_mtime;
2203 if (!null_timespec(ft->create_time)) {
2204 set_create_timespec_ea(handle->conn,
2209 if ((timespec_compare(&ft->atime,
2210 &smb_fname->st.st_ex_atime) == 0) &&
2211 (timespec_compare(&ft->mtime,
2212 &smb_fname->st.st_ex_mtime) == 0)) {
2217 #if defined(HAVE_UTIMENSAT)
2219 struct timespec ts[2];
2222 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2224 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2226 if (!((result == -1) && (errno == ENOSYS))) {
2230 #if defined(HAVE_UTIMES)
2232 struct timeval tv[2];
2233 tv[0] = convert_timespec_to_timeval(ft->atime);
2234 tv[1] = convert_timespec_to_timeval(ft->mtime);
2235 result = utimes(smb_fname->base_name, tv);
2237 result = utimes(smb_fname->base_name, NULL);
2239 if (!((result == -1) && (errno == ENOSYS))) {
2243 #if defined(HAVE_UTIME)
2245 struct utimbuf times;
2246 times.actime = convert_timespec_to_time_t(ft->atime);
2247 times.modtime = convert_timespec_to_time_t(ft->mtime);
2248 result = utime(smb_fname->base_name, ×);
2250 result = utime(smb_fname->base_name, NULL);
2252 if (!((result == -1) && (errno == ENOSYS))) {
2260 END_PROFILE(syscall_ntimes);
2264 /*********************************************************************
2265 A version of ftruncate that will write the space on disk if strict
2267 **********************************************************************/
2269 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2271 off_t space_to_write;
2272 uint64_t space_avail;
2273 uint64_t bsize,dfree,dsize;
2276 SMB_STRUCT_STAT *pst;
2278 status = vfs_stat_fsp(fsp);
2279 if (!NT_STATUS_IS_OK(status)) {
2282 pst = &fsp->fsp_name->st;
2285 if (S_ISFIFO(pst->st_ex_mode))
2289 if (pst->st_ex_size == len)
2292 /* Shrink - just ftruncate. */
2293 if (pst->st_ex_size > len)
2294 return ftruncate(fsp->fh->fd, len);
2296 space_to_write = len - pst->st_ex_size;
2298 /* for allocation try fallocate first. This can fail on some
2299 platforms e.g. when the filesystem doesn't support it and no
2300 emulation is being done by the libc (like on AIX with JFS1). In that
2301 case we do our own emulation. fallocate implementations can
2302 return ENOTSUP or EINVAL in cases like that. */
2303 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2304 if (ret == -1 && errno == ENOSPC) {
2310 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2311 "error %d. Falling back to slow manual allocation\n", errno));
2313 /* available disk space is enough or not? */
2315 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2316 /* space_avail is 1k blocks */
2317 if (space_avail == (uint64_t)-1 ||
2318 ((uint64_t)space_to_write/1024 > space_avail) ) {
2323 /* Write out the real space on disk. */
2324 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2332 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2335 SMB_STRUCT_STAT *pst;
2339 START_PROFILE(syscall_ftruncate);
2341 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2342 result = strict_allocate_ftruncate(handle, fsp, len);
2343 END_PROFILE(syscall_ftruncate);
2347 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2348 ftruncate if the system supports it. Then I discovered that
2349 you can have some filesystems that support ftruncate
2350 expansion and some that don't! On Linux fat can't do
2351 ftruncate extend but ext2 can. */
2353 result = ftruncate(fsp->fh->fd, len);
2355 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2356 extend a file with ftruncate. Provide alternate implementation
2359 /* Do an fstat to see if the file is longer than the requested
2360 size in which case the ftruncate above should have
2361 succeeded or shorter, in which case seek to len - 1 and
2362 write 1 byte of zero */
2363 status = vfs_stat_fsp(fsp);
2364 if (!NT_STATUS_IS_OK(status)) {
2368 /* We need to update the files_struct after successful ftruncate */
2373 pst = &fsp->fsp_name->st;
2376 if (S_ISFIFO(pst->st_ex_mode)) {
2382 if (pst->st_ex_size == len) {
2387 if (pst->st_ex_size > len) {
2388 /* the ftruncate should have worked */
2392 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2400 END_PROFILE(syscall_ftruncate);
2404 static int vfswrap_fallocate(vfs_handle_struct *handle,
2412 START_PROFILE(syscall_fallocate);
2414 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2416 * posix_fallocate returns 0 on success, errno on error
2417 * and doesn't set errno. Make it behave like fallocate()
2418 * which returns -1, and sets errno on failure.
2425 /* sys_fallocate handles filtering of unsupported mode flags */
2426 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2428 END_PROFILE(syscall_fallocate);
2432 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2436 START_PROFILE(syscall_fcntl_lock);
2438 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2440 "force process locks",
2442 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2445 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2446 END_PROFILE(syscall_fcntl_lock);
2450 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2451 uint32_t share_mode, uint32_t access_mask)
2453 START_PROFILE(syscall_kernel_flock);
2454 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2455 END_PROFILE(syscall_kernel_flock);
2459 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2464 START_PROFILE(syscall_fcntl_getlock);
2466 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2468 "force process locks",
2470 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2473 result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2474 END_PROFILE(syscall_fcntl_getlock);
2478 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2483 START_PROFILE(syscall_linux_setlease);
2485 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2486 result = linux_setlease(fsp->fh->fd, leasetype);
2490 END_PROFILE(syscall_linux_setlease);
2494 static int vfswrap_symlink(vfs_handle_struct *handle,
2495 const char *link_target,
2496 const struct smb_filename *new_smb_fname)
2500 START_PROFILE(syscall_symlink);
2501 result = symlink(link_target, new_smb_fname->base_name);
2502 END_PROFILE(syscall_symlink);
2506 static int vfswrap_readlink(vfs_handle_struct *handle,
2507 const struct smb_filename *smb_fname,
2513 START_PROFILE(syscall_readlink);
2514 result = readlink(smb_fname->base_name, buf, bufsiz);
2515 END_PROFILE(syscall_readlink);
2519 static int vfswrap_link(vfs_handle_struct *handle,
2520 const struct smb_filename *old_smb_fname,
2521 const struct smb_filename *new_smb_fname)
2525 START_PROFILE(syscall_link);
2526 result = link(old_smb_fname->base_name, new_smb_fname->base_name);
2527 END_PROFILE(syscall_link);
2531 static int vfswrap_mknod(vfs_handle_struct *handle,
2532 const struct smb_filename *smb_fname,
2538 START_PROFILE(syscall_mknod);
2539 result = sys_mknod(smb_fname->base_name, mode, dev);
2540 END_PROFILE(syscall_mknod);
2544 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2546 const struct smb_filename *smb_fname)
2549 struct smb_filename *result_fname = NULL;
2551 START_PROFILE(syscall_realpath);
2552 result = sys_realpath(smb_fname->base_name);
2553 END_PROFILE(syscall_realpath);
2555 result_fname = synthetic_smb_fname(ctx, result, NULL, NULL, 0);
2558 return result_fname;
2561 static int vfswrap_chflags(vfs_handle_struct *handle,
2562 const struct smb_filename *smb_fname,
2566 return chflags(smb_fname->base_name, flags);
2573 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2574 const SMB_STRUCT_STAT *sbuf)
2578 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2582 key.devid = sbuf->st_ex_dev;
2583 key.inode = sbuf->st_ex_ino;
2584 /* key.extid is unused by default. */
2589 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2590 struct files_struct *fsp,
2591 const struct smb_filename *smb_fname,
2592 TALLOC_CTX *mem_ctx,
2593 unsigned int *pnum_streams,
2594 struct stream_struct **pstreams)
2596 SMB_STRUCT_STAT sbuf;
2597 struct stream_struct *tmp_streams = NULL;
2600 if ((fsp != NULL) && (fsp->is_directory)) {
2602 * No default streams on directories
2607 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2608 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2611 struct smb_filename smb_fname_cp;
2613 ZERO_STRUCT(smb_fname_cp);
2614 smb_fname_cp.base_name = discard_const_p(char,
2615 smb_fname->base_name);
2616 smb_fname_cp.flags = smb_fname->flags;
2618 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
2619 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2621 ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2623 sbuf = smb_fname_cp.st;
2627 return map_nt_error_from_unix(errno);
2630 if (S_ISDIR(sbuf.st_ex_mode)) {
2634 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2635 (*pnum_streams) + 1);
2636 if (tmp_streams == NULL) {
2637 return NT_STATUS_NO_MEMORY;
2639 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2640 if (tmp_streams[*pnum_streams].name == NULL) {
2641 return NT_STATUS_NO_MEMORY;
2643 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2644 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2647 *pstreams = tmp_streams;
2649 return NT_STATUS_OK;
2652 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2655 TALLOC_CTX *mem_ctx,
2659 * Don't fall back to get_real_filename so callers can differentiate
2660 * between a full directory scan and an actual case-insensitive stat.
2666 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2667 const struct smb_filename *smb_fname)
2669 return handle->conn->connectpath;
2672 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2673 struct byte_range_lock *br_lck,
2674 struct lock_struct *plock,
2677 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2679 /* Note: blr is not used in the default implementation. */
2680 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2683 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2684 struct messaging_context *msg_ctx,
2685 struct byte_range_lock *br_lck,
2686 const struct lock_struct *plock)
2688 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2690 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2693 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2694 struct byte_range_lock *br_lck,
2695 struct lock_struct *plock)
2697 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2699 /* Note: blr is not used in the default implementation. */
2700 return brl_lock_cancel_default(br_lck, plock);
2703 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
2705 struct lock_struct *plock)
2707 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2708 plock->lock_type == WRITE_LOCK);
2710 return strict_lock_check_default(fsp, plock);
2713 /* NT ACL operations. */
2715 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2717 uint32_t security_info,
2718 TALLOC_CTX *mem_ctx,
2719 struct security_descriptor **ppdesc)
2723 START_PROFILE(fget_nt_acl);
2724 result = posix_fget_nt_acl(fsp, security_info,
2726 END_PROFILE(fget_nt_acl);
2730 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2731 const struct smb_filename *smb_fname,
2732 uint32_t security_info,
2733 TALLOC_CTX *mem_ctx,
2734 struct security_descriptor **ppdesc)
2738 START_PROFILE(get_nt_acl);
2739 result = posix_get_nt_acl(handle->conn,
2744 END_PROFILE(get_nt_acl);
2748 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2752 START_PROFILE(fset_nt_acl);
2753 result = set_nt_acl(fsp, security_info_sent, psd);
2754 END_PROFILE(fset_nt_acl);
2758 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2759 struct smb_filename *file,
2760 struct security_acl *sacl,
2761 uint32_t access_requested,
2762 uint32_t access_denied)
2764 return NT_STATUS_OK; /* Nothing to do here ... */
2767 static int vfswrap_chmod_acl(vfs_handle_struct *handle,
2768 const struct smb_filename *smb_fname,
2777 START_PROFILE(chmod_acl);
2778 result = chmod_acl(handle->conn, smb_fname, mode);
2779 END_PROFILE(chmod_acl);
2784 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2792 START_PROFILE(fchmod_acl);
2793 result = fchmod_acl(fsp, mode);
2794 END_PROFILE(fchmod_acl);
2799 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2800 const struct smb_filename *smb_fname,
2801 SMB_ACL_TYPE_T type,
2802 TALLOC_CTX *mem_ctx)
2804 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
2807 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2809 TALLOC_CTX *mem_ctx)
2811 return sys_acl_get_fd(handle, fsp, mem_ctx);
2814 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
2815 const struct smb_filename *smb_fname,
2816 SMB_ACL_TYPE_T acltype,
2819 return sys_acl_set_file(handle, smb_fname, acltype, theacl);
2822 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2824 return sys_acl_set_fd(handle, fsp, theacl);
2827 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
2828 const struct smb_filename *smb_fname)
2830 return sys_acl_delete_def_file(handle, smb_fname);
2833 /****************************************************************
2834 Extended attribute operations.
2835 *****************************************************************/
2837 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
2838 const struct smb_filename *smb_fname,
2843 return getxattr(smb_fname->base_name, name, value, size);
2846 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2848 return fgetxattr(fsp->fh->fd, name, value, size);
2851 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
2852 const struct smb_filename *smb_fname,
2856 return listxattr(smb_fname->base_name, list, size);
2859 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2861 return flistxattr(fsp->fh->fd, list, size);
2864 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
2865 const struct smb_filename *smb_fname,
2868 return removexattr(smb_fname->base_name, name);
2871 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2873 return fremovexattr(fsp->fh->fd, name);
2876 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
2877 const struct smb_filename *smb_fname,
2883 return setxattr(smb_fname->base_name, name, value, size, flags);
2886 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2888 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2891 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2896 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2897 const struct smb_filename *fname,
2898 SMB_STRUCT_STAT *sbuf)
2902 bool offline = false;
2904 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2908 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2909 #if defined(ENOTSUP)
2915 status = get_full_smb_filename(talloc_tos(), fname, &path);
2916 if (!NT_STATUS_IS_OK(status)) {
2917 errno = map_errno_from_nt_status(status);
2921 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2928 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2929 struct files_struct *fsp,
2930 TALLOC_CTX *mem_ctx,
2933 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2936 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2937 struct files_struct *fsp,
2938 const DATA_BLOB old_cookie,
2939 TALLOC_CTX *mem_ctx,
2940 DATA_BLOB *new_cookie)
2942 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2946 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2947 struct smb_request *smb1req,
2948 struct smbXsrv_open *op,
2949 const DATA_BLOB old_cookie,
2950 TALLOC_CTX *mem_ctx,
2951 struct files_struct **fsp,
2952 DATA_BLOB *new_cookie)
2954 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2955 old_cookie, mem_ctx,
2959 static struct vfs_fn_pointers vfs_default_fns = {
2960 /* Disk operations */
2962 .connect_fn = vfswrap_connect,
2963 .disconnect_fn = vfswrap_disconnect,
2964 .disk_free_fn = vfswrap_disk_free,
2965 .get_quota_fn = vfswrap_get_quota,
2966 .set_quota_fn = vfswrap_set_quota,
2967 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2968 .statvfs_fn = vfswrap_statvfs,
2969 .fs_capabilities_fn = vfswrap_fs_capabilities,
2970 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2971 .snap_check_path_fn = vfswrap_snap_check_path,
2972 .snap_create_fn = vfswrap_snap_create,
2973 .snap_delete_fn = vfswrap_snap_delete,
2975 /* Directory operations */
2977 .opendir_fn = vfswrap_opendir,
2978 .fdopendir_fn = vfswrap_fdopendir,
2979 .readdir_fn = vfswrap_readdir,
2980 .readdir_attr_fn = vfswrap_readdir_attr,
2981 .seekdir_fn = vfswrap_seekdir,
2982 .telldir_fn = vfswrap_telldir,
2983 .rewind_dir_fn = vfswrap_rewinddir,
2984 .mkdir_fn = vfswrap_mkdir,
2985 .rmdir_fn = vfswrap_rmdir,
2986 .closedir_fn = vfswrap_closedir,
2988 /* File operations */
2990 .open_fn = vfswrap_open,
2991 .create_file_fn = vfswrap_create_file,
2992 .close_fn = vfswrap_close,
2993 .read_fn = vfswrap_read,
2994 .pread_fn = vfswrap_pread,
2995 .pread_send_fn = vfswrap_pread_send,
2996 .pread_recv_fn = vfswrap_pread_recv,
2997 .write_fn = vfswrap_write,
2998 .pwrite_fn = vfswrap_pwrite,
2999 .pwrite_send_fn = vfswrap_pwrite_send,
3000 .pwrite_recv_fn = vfswrap_pwrite_recv,
3001 .lseek_fn = vfswrap_lseek,
3002 .sendfile_fn = vfswrap_sendfile,
3003 .recvfile_fn = vfswrap_recvfile,
3004 .rename_fn = vfswrap_rename,
3005 .fsync_send_fn = vfswrap_fsync_send,
3006 .fsync_recv_fn = vfswrap_fsync_recv,
3007 .stat_fn = vfswrap_stat,
3008 .fstat_fn = vfswrap_fstat,
3009 .lstat_fn = vfswrap_lstat,
3010 .get_alloc_size_fn = vfswrap_get_alloc_size,
3011 .unlink_fn = vfswrap_unlink,
3012 .chmod_fn = vfswrap_chmod,
3013 .fchmod_fn = vfswrap_fchmod,
3014 .chown_fn = vfswrap_chown,
3015 .fchown_fn = vfswrap_fchown,
3016 .lchown_fn = vfswrap_lchown,
3017 .chdir_fn = vfswrap_chdir,
3018 .getwd_fn = vfswrap_getwd,
3019 .ntimes_fn = vfswrap_ntimes,
3020 .ftruncate_fn = vfswrap_ftruncate,
3021 .fallocate_fn = vfswrap_fallocate,
3022 .lock_fn = vfswrap_lock,
3023 .kernel_flock_fn = vfswrap_kernel_flock,
3024 .linux_setlease_fn = vfswrap_linux_setlease,
3025 .getlock_fn = vfswrap_getlock,
3026 .symlink_fn = vfswrap_symlink,
3027 .readlink_fn = vfswrap_readlink,
3028 .link_fn = vfswrap_link,
3029 .mknod_fn = vfswrap_mknod,
3030 .realpath_fn = vfswrap_realpath,
3031 .chflags_fn = vfswrap_chflags,
3032 .file_id_create_fn = vfswrap_file_id_create,
3033 .streaminfo_fn = vfswrap_streaminfo,
3034 .get_real_filename_fn = vfswrap_get_real_filename,
3035 .connectpath_fn = vfswrap_connectpath,
3036 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
3037 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3038 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
3039 .strict_lock_check_fn = vfswrap_strict_lock_check,
3040 .translate_name_fn = vfswrap_translate_name,
3041 .fsctl_fn = vfswrap_fsctl,
3042 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
3043 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
3044 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
3045 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
3046 .offload_read_send_fn = vfswrap_offload_read_send,
3047 .offload_read_recv_fn = vfswrap_offload_read_recv,
3048 .offload_write_send_fn = vfswrap_offload_write_send,
3049 .offload_write_recv_fn = vfswrap_offload_write_recv,
3050 .get_compression_fn = vfswrap_get_compression,
3051 .set_compression_fn = vfswrap_set_compression,
3053 /* NT ACL operations. */
3055 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
3056 .get_nt_acl_fn = vfswrap_get_nt_acl,
3057 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
3058 .audit_file_fn = vfswrap_audit_file,
3060 /* POSIX ACL operations. */
3062 .chmod_acl_fn = vfswrap_chmod_acl,
3063 .fchmod_acl_fn = vfswrap_fchmod_acl,
3065 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
3066 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3067 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
3068 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3069 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
3070 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3071 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
3073 /* EA operations. */
3074 .getxattr_fn = vfswrap_getxattr,
3075 .fgetxattr_fn = vfswrap_fgetxattr,
3076 .listxattr_fn = vfswrap_listxattr,
3077 .flistxattr_fn = vfswrap_flistxattr,
3078 .removexattr_fn = vfswrap_removexattr,
3079 .fremovexattr_fn = vfswrap_fremovexattr,
3080 .setxattr_fn = vfswrap_setxattr,
3081 .fsetxattr_fn = vfswrap_fsetxattr,
3083 /* aio operations */
3084 .aio_force_fn = vfswrap_aio_force,
3086 /* durable handle operations */
3087 .durable_cookie_fn = vfswrap_durable_cookie,
3088 .durable_disconnect_fn = vfswrap_durable_disconnect,
3089 .durable_reconnect_fn = vfswrap_durable_reconnect,
3093 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3095 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3096 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);