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_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
618 size_t n, off_t offset)
622 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
623 START_PROFILE_BYTES(syscall_pread, n);
624 result = sys_pread(fsp->fh->fd, data, n, offset);
625 END_PROFILE_BYTES(syscall_pread);
627 if (result == -1 && errno == ESPIPE) {
628 /* Maintain the fiction that pipes can be seeked (sought?) on. */
629 result = sys_read(fsp->fh->fd, data, n);
633 #else /* HAVE_PREAD */
636 #endif /* HAVE_PREAD */
641 static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
645 START_PROFILE_BYTES(syscall_write, n);
646 result = sys_write(fsp->fh->fd, data, n);
647 END_PROFILE_BYTES(syscall_write);
651 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
652 size_t n, off_t offset)
656 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
657 START_PROFILE_BYTES(syscall_pwrite, n);
658 result = sys_pwrite(fsp->fh->fd, data, n, offset);
659 END_PROFILE_BYTES(syscall_pwrite);
661 if (result == -1 && errno == ESPIPE) {
662 /* Maintain the fiction that pipes can be sought on. */
663 result = SMB_VFS_WRITE(fsp, data, n);
666 #else /* HAVE_PWRITE */
670 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
675 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
679 result = SMB_VFS_WRITE(fsp, data, n);
682 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
685 #endif /* HAVE_PWRITE */
690 struct vfswrap_pread_state {
697 struct vfs_aio_state vfs_aio_state;
698 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
701 static void vfs_pread_do(void *private_data);
702 static void vfs_pread_done(struct tevent_req *subreq);
703 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state);
705 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
707 struct tevent_context *ev,
708 struct files_struct *fsp,
710 size_t n, off_t offset)
712 struct tevent_req *req, *subreq;
713 struct vfswrap_pread_state *state;
715 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
721 state->fd = fsp->fh->fd;
724 state->offset = offset;
726 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
727 state->profile_bytes, n);
728 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
730 subreq = pthreadpool_tevent_job_send(
731 state, ev, handle->conn->sconn->pool,
732 vfs_pread_do, state);
733 if (tevent_req_nomem(subreq, req)) {
734 return tevent_req_post(req, ev);
736 tevent_req_set_callback(subreq, vfs_pread_done, req);
738 talloc_set_destructor(state, vfs_pread_state_destructor);
743 static void vfs_pread_do(void *private_data)
745 struct vfswrap_pread_state *state = talloc_get_type_abort(
746 private_data, struct vfswrap_pread_state);
747 struct timespec start_time;
748 struct timespec end_time;
750 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
752 PROFILE_TIMESTAMP(&start_time);
755 state->ret = pread(state->fd, state->buf, state->count,
757 } while ((state->ret == -1) && (errno == EINTR));
759 if (state->ret == -1) {
760 state->vfs_aio_state.error = errno;
763 PROFILE_TIMESTAMP(&end_time);
765 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
767 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
770 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state)
775 static void vfs_pread_done(struct tevent_req *subreq)
777 struct tevent_req *req = tevent_req_callback_data(
778 subreq, struct tevent_req);
779 struct vfswrap_pread_state *state = tevent_req_data(
780 req, struct vfswrap_pread_state);
783 ret = pthreadpool_tevent_job_recv(subreq);
785 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
786 talloc_set_destructor(state, NULL);
787 if (tevent_req_error(req, ret)) {
791 tevent_req_done(req);
794 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
795 struct vfs_aio_state *vfs_aio_state)
797 struct vfswrap_pread_state *state = tevent_req_data(
798 req, struct vfswrap_pread_state);
800 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
804 *vfs_aio_state = state->vfs_aio_state;
808 struct vfswrap_pwrite_state {
815 struct vfs_aio_state vfs_aio_state;
816 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
819 static void vfs_pwrite_do(void *private_data);
820 static void vfs_pwrite_done(struct tevent_req *subreq);
821 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state);
823 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
825 struct tevent_context *ev,
826 struct files_struct *fsp,
828 size_t n, off_t offset)
830 struct tevent_req *req, *subreq;
831 struct vfswrap_pwrite_state *state;
833 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
839 state->fd = fsp->fh->fd;
842 state->offset = offset;
844 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
845 state->profile_bytes, n);
846 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
848 subreq = pthreadpool_tevent_job_send(
849 state, ev, handle->conn->sconn->pool,
850 vfs_pwrite_do, state);
851 if (tevent_req_nomem(subreq, req)) {
852 return tevent_req_post(req, ev);
854 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
856 talloc_set_destructor(state, vfs_pwrite_state_destructor);
861 static void vfs_pwrite_do(void *private_data)
863 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
864 private_data, struct vfswrap_pwrite_state);
865 struct timespec start_time;
866 struct timespec end_time;
868 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
870 PROFILE_TIMESTAMP(&start_time);
873 state->ret = pwrite(state->fd, state->buf, state->count,
875 } while ((state->ret == -1) && (errno == EINTR));
877 if (state->ret == -1) {
878 state->vfs_aio_state.error = errno;
881 PROFILE_TIMESTAMP(&end_time);
883 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
885 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
888 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state)
893 static void vfs_pwrite_done(struct tevent_req *subreq)
895 struct tevent_req *req = tevent_req_callback_data(
896 subreq, struct tevent_req);
897 struct vfswrap_pwrite_state *state = tevent_req_data(
898 req, struct vfswrap_pwrite_state);
901 ret = pthreadpool_tevent_job_recv(subreq);
903 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
904 talloc_set_destructor(state, NULL);
905 if (tevent_req_error(req, ret)) {
909 tevent_req_done(req);
912 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
913 struct vfs_aio_state *vfs_aio_state)
915 struct vfswrap_pwrite_state *state = tevent_req_data(
916 req, struct vfswrap_pwrite_state);
918 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
922 *vfs_aio_state = state->vfs_aio_state;
926 struct vfswrap_fsync_state {
930 struct vfs_aio_state vfs_aio_state;
931 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
934 static void vfs_fsync_do(void *private_data);
935 static void vfs_fsync_done(struct tevent_req *subreq);
936 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state);
938 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
940 struct tevent_context *ev,
941 struct files_struct *fsp)
943 struct tevent_req *req, *subreq;
944 struct vfswrap_fsync_state *state;
946 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
952 state->fd = fsp->fh->fd;
954 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
955 state->profile_basic);
957 subreq = pthreadpool_tevent_job_send(
958 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
959 if (tevent_req_nomem(subreq, req)) {
960 return tevent_req_post(req, ev);
962 tevent_req_set_callback(subreq, vfs_fsync_done, req);
964 talloc_set_destructor(state, vfs_fsync_state_destructor);
969 static void vfs_fsync_do(void *private_data)
971 struct vfswrap_fsync_state *state = talloc_get_type_abort(
972 private_data, struct vfswrap_fsync_state);
973 struct timespec start_time;
974 struct timespec end_time;
976 PROFILE_TIMESTAMP(&start_time);
979 state->ret = fsync(state->fd);
980 } while ((state->ret == -1) && (errno == EINTR));
982 if (state->ret == -1) {
983 state->vfs_aio_state.error = errno;
986 PROFILE_TIMESTAMP(&end_time);
988 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
991 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state)
996 static void vfs_fsync_done(struct tevent_req *subreq)
998 struct tevent_req *req = tevent_req_callback_data(
999 subreq, struct tevent_req);
1000 struct vfswrap_fsync_state *state = tevent_req_data(
1001 req, struct vfswrap_fsync_state);
1004 ret = pthreadpool_tevent_job_recv(subreq);
1005 TALLOC_FREE(subreq);
1006 SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
1007 talloc_set_destructor(state, NULL);
1008 if (tevent_req_error(req, ret)) {
1012 tevent_req_done(req);
1015 static int vfswrap_fsync_recv(struct tevent_req *req,
1016 struct vfs_aio_state *vfs_aio_state)
1018 struct vfswrap_fsync_state *state = tevent_req_data(
1019 req, struct vfswrap_fsync_state);
1021 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1025 *vfs_aio_state = state->vfs_aio_state;
1029 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1033 START_PROFILE(syscall_lseek);
1035 /* Cope with 'stat' file opens. */
1036 if (fsp->fh->fd != -1)
1037 result = lseek(fsp->fh->fd, offset, whence);
1040 * We want to maintain the fiction that we can seek
1041 * on a fifo for file system purposes. This allows
1042 * people to set up UNIX fifo's that feed data to Windows
1043 * applications. JRA.
1046 if((result == -1) && (errno == ESPIPE)) {
1051 END_PROFILE(syscall_lseek);
1055 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1056 off_t offset, size_t n)
1060 START_PROFILE_BYTES(syscall_sendfile, n);
1061 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
1062 END_PROFILE_BYTES(syscall_sendfile);
1066 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1068 files_struct *tofsp,
1074 START_PROFILE_BYTES(syscall_recvfile, n);
1075 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
1076 END_PROFILE_BYTES(syscall_recvfile);
1080 static int vfswrap_rename(vfs_handle_struct *handle,
1081 const struct smb_filename *smb_fname_src,
1082 const struct smb_filename *smb_fname_dst)
1086 START_PROFILE(syscall_rename);
1088 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
1093 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
1096 END_PROFILE(syscall_rename);
1100 static int vfswrap_stat(vfs_handle_struct *handle,
1101 struct smb_filename *smb_fname)
1105 START_PROFILE(syscall_stat);
1107 if (smb_fname->stream_name) {
1112 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1113 lp_fake_directory_create_times(SNUM(handle->conn)));
1115 END_PROFILE(syscall_stat);
1119 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1123 START_PROFILE(syscall_fstat);
1124 result = sys_fstat(fsp->fh->fd,
1125 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1126 END_PROFILE(syscall_fstat);
1130 static int vfswrap_lstat(vfs_handle_struct *handle,
1131 struct smb_filename *smb_fname)
1135 START_PROFILE(syscall_lstat);
1137 if (smb_fname->stream_name) {
1142 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1143 lp_fake_directory_create_times(SNUM(handle->conn)));
1145 END_PROFILE(syscall_lstat);
1149 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1151 enum vfs_translate_direction direction,
1152 TALLOC_CTX *mem_ctx,
1155 return NT_STATUS_NONE_MAPPED;
1159 * Implement the default fsctl operation.
1161 static bool vfswrap_logged_ioctl_message = false;
1163 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1164 struct files_struct *fsp,
1167 uint16_t req_flags, /* Needed for UNICODE ... */
1168 const uint8_t *_in_data,
1170 uint8_t **_out_data,
1171 uint32_t max_out_len,
1174 const char *in_data = (const char *)_in_data;
1175 char **out_data = (char **)_out_data;
1179 case FSCTL_SET_SPARSE:
1181 bool set_sparse = true;
1183 if (in_len >= 1 && in_data[0] == 0) {
1187 status = file_set_sparse(handle->conn, fsp, set_sparse);
1189 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1190 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1191 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1192 nt_errstr(status)));
1197 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1199 unsigned char objid[16];
1200 char *return_data = NULL;
1202 /* This should return the object-id on this file.
1203 * I think I'll make this be the inode+dev. JRA.
1206 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1207 fsp_fnum_dbg(fsp)));
1209 *out_len = MIN(max_out_len, 64);
1211 /* Hmmm, will this cause problems if less data asked for? */
1212 return_data = talloc_array(ctx, char, 64);
1213 if (return_data == NULL) {
1214 return NT_STATUS_NO_MEMORY;
1217 /* For backwards compatibility only store the dev/inode. */
1218 push_file_id_16(return_data, &fsp->file_id);
1219 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1220 push_file_id_16(return_data+32, &fsp->file_id);
1221 memset(return_data+48, 0, 16);
1222 *out_data = return_data;
1223 return NT_STATUS_OK;
1226 case FSCTL_GET_REPARSE_POINT:
1228 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1229 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1230 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1231 return NT_STATUS_NOT_A_REPARSE_POINT;
1234 case FSCTL_SET_REPARSE_POINT:
1236 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1237 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1238 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1239 return NT_STATUS_NOT_A_REPARSE_POINT;
1242 case FSCTL_GET_SHADOW_COPY_DATA:
1245 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1246 * and return their volume names. If max_data_count is 16, then it is just
1247 * asking for the number of volumes and length of the combined names.
1249 * pdata is the data allocated by our caller, but that uses
1250 * total_data_count (which is 0 in our case) rather than max_data_count.
1251 * Allocate the correct amount and return the pointer to let
1252 * it be deallocated when we return.
1254 struct shadow_copy_data *shadow_data = NULL;
1255 bool labels = False;
1256 uint32_t labels_data_count = 0;
1258 char *cur_pdata = NULL;
1260 if (max_out_len < 16) {
1261 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1263 return NT_STATUS_INVALID_PARAMETER;
1266 if (max_out_len > 16) {
1270 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1271 if (shadow_data == NULL) {
1272 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1273 return NT_STATUS_NO_MEMORY;
1277 * Call the VFS routine to actually do the work.
1279 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1282 /* broken module didn't set errno on error */
1283 status = NT_STATUS_UNSUCCESSFUL;
1285 status = map_nt_error_from_unix(errno);
1286 if (NT_STATUS_EQUAL(status,
1287 NT_STATUS_NOT_SUPPORTED)) {
1291 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1292 "connectpath %s, failed - %s.\n",
1293 fsp->conn->connectpath,
1294 nt_errstr(status)));
1295 TALLOC_FREE(shadow_data);
1299 labels_data_count = (shadow_data->num_volumes * 2 *
1300 sizeof(SHADOW_COPY_LABEL)) + 2;
1305 *out_len = 12 + labels_data_count;
1308 if (max_out_len < *out_len) {
1309 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1310 max_out_len, *out_len));
1311 TALLOC_FREE(shadow_data);
1312 return NT_STATUS_BUFFER_TOO_SMALL;
1315 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1316 if (cur_pdata == NULL) {
1317 TALLOC_FREE(shadow_data);
1318 return NT_STATUS_NO_MEMORY;
1321 *out_data = cur_pdata;
1323 /* num_volumes 4 bytes */
1324 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1327 /* num_labels 4 bytes */
1328 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1331 /* needed_data_count 4 bytes */
1332 SIVAL(cur_pdata, 8, labels_data_count);
1336 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1337 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1338 if (labels && shadow_data->labels) {
1339 for (i=0; i<shadow_data->num_volumes; i++) {
1341 status = srvstr_push(cur_pdata, req_flags,
1342 cur_pdata, shadow_data->labels[i],
1343 2 * sizeof(SHADOW_COPY_LABEL),
1344 STR_UNICODE|STR_TERMINATE, &len);
1345 if (!NT_STATUS_IS_OK(status)) {
1346 TALLOC_FREE(*out_data);
1347 TALLOC_FREE(shadow_data);
1350 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1351 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1355 TALLOC_FREE(shadow_data);
1357 return NT_STATUS_OK;
1360 case FSCTL_FIND_FILES_BY_SID:
1362 /* pretend this succeeded -
1364 * we have to send back a list with all files owned by this SID
1366 * but I have to check that --metze
1372 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1373 fsp_fnum_dbg(fsp)));
1376 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1377 return NT_STATUS_INVALID_PARAMETER;
1380 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1382 /* unknown 4 bytes: this is not the length of the sid :-( */
1383 /*unknown = IVAL(pdata,0);*/
1385 if (!sid_parse(_in_data + 4, sid_len, &sid)) {
1386 return NT_STATUS_INVALID_PARAMETER;
1388 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1390 if (!sid_to_uid(&sid, &uid)) {
1391 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1392 sid_string_dbg(&sid),
1393 (unsigned long)sid_len));
1397 /* we can take a look at the find source :-)
1399 * find ./ -uid $uid -name '*' is what we need here
1402 * and send 4bytes len and then NULL terminated unicode strings
1405 * but I don't know how to deal with the paged results
1406 * (maybe we can hang the result anywhere in the fsp struct)
1408 * but I don't know how to deal with the paged results
1409 * (maybe we can hang the result anywhere in the fsp struct)
1411 * we don't send all files at once
1412 * and at the next we should *not* start from the beginning,
1413 * so we have to cache the result
1418 /* this works for now... */
1419 return NT_STATUS_OK;
1422 case FSCTL_QUERY_ALLOCATED_RANGES:
1424 /* FIXME: This is just a dummy reply, telling that all of the
1425 * file is allocated. MKS cp needs that.
1426 * Adding the real allocated ranges via FIEMAP on Linux
1427 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1428 * this FSCTL correct for sparse files.
1430 uint64_t offset, length;
1431 char *out_data_tmp = NULL;
1434 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1436 return NT_STATUS_INVALID_PARAMETER;
1439 if (max_out_len < 16) {
1440 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1442 return NT_STATUS_INVALID_PARAMETER;
1445 offset = BVAL(in_data,0);
1446 length = BVAL(in_data,8);
1448 if (offset + length < offset) {
1449 /* No 64-bit integer wrap. */
1450 return NT_STATUS_INVALID_PARAMETER;
1453 /* Shouldn't this be SMB_VFS_STAT ... ? */
1454 status = vfs_stat_fsp(fsp);
1455 if (!NT_STATUS_IS_OK(status)) {
1460 out_data_tmp = talloc_array(ctx, char, *out_len);
1461 if (out_data_tmp == NULL) {
1462 DEBUG(10, ("unable to allocate memory for response\n"));
1463 return NT_STATUS_NO_MEMORY;
1466 if (offset > fsp->fsp_name->st.st_ex_size ||
1467 fsp->fsp_name->st.st_ex_size == 0 ||
1469 memset(out_data_tmp, 0, *out_len);
1471 uint64_t end = offset + length;
1472 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1473 SBVAL(out_data_tmp, 0, 0);
1474 SBVAL(out_data_tmp, 8, end);
1477 *out_data = out_data_tmp;
1479 return NT_STATUS_OK;
1482 case FSCTL_IS_VOLUME_DIRTY:
1484 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1485 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1487 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1488 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1490 return NT_STATUS_INVALID_PARAMETER;
1495 * Only print once ... unfortunately there could be lots of
1496 * different FSCTLs that are called.
1498 if (!vfswrap_logged_ioctl_message) {
1499 vfswrap_logged_ioctl_message = true;
1500 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1501 __func__, function));
1505 return NT_STATUS_NOT_SUPPORTED;
1508 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
1509 const struct smb_filename *fname,
1510 SMB_STRUCT_STAT *sbuf);
1512 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1513 struct smb_filename *smb_fname,
1518 offline = vfswrap_is_offline(handle, smb_fname, &smb_fname->st);
1520 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1523 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1526 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1527 struct files_struct *fsp,
1532 offline = vfswrap_is_offline(handle, fsp->fsp_name, &fsp->fsp_name->st);
1534 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1537 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1540 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1541 const struct smb_filename *smb_fname,
1544 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1547 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1548 struct files_struct *fsp,
1551 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1554 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1556 struct vfswrap_offload_read_state {
1560 static struct tevent_req *vfswrap_offload_read_send(
1561 TALLOC_CTX *mem_ctx,
1562 struct tevent_context *ev,
1563 struct vfs_handle_struct *handle,
1564 struct files_struct *fsp,
1570 struct tevent_req *req = NULL;
1571 struct vfswrap_offload_read_state *state = NULL;
1574 req = tevent_req_create(mem_ctx, &state,
1575 struct vfswrap_offload_read_state);
1580 status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1581 &vfswrap_offload_ctx);
1582 if (tevent_req_nterror(req, status)) {
1583 return tevent_req_post(req, ev);
1586 if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1587 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1588 return tevent_req_post(req, ev);
1591 status = vfs_offload_token_create_blob(state, fsp, fsctl,
1593 if (tevent_req_nterror(req, status)) {
1594 return tevent_req_post(req, ev);
1597 status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1599 if (tevent_req_nterror(req, status)) {
1600 return tevent_req_post(req, ev);
1603 tevent_req_done(req);
1604 return tevent_req_post(req, ev);
1607 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
1608 struct vfs_handle_struct *handle,
1609 TALLOC_CTX *mem_ctx,
1612 struct vfswrap_offload_read_state *state = tevent_req_data(
1613 req, struct vfswrap_offload_read_state);
1616 if (tevent_req_is_nterror(req, &status)) {
1617 tevent_req_received(req);
1621 token->length = state->token.length;
1622 token->data = talloc_move(mem_ctx, &state->token.data);
1624 tevent_req_received(req);
1625 return NT_STATUS_OK;
1628 struct vfswrap_offload_write_state {
1629 struct tevent_context *ev;
1631 bool read_lck_locked;
1632 bool write_lck_locked;
1634 struct files_struct *src_fsp;
1636 struct files_struct *dst_fsp;
1640 size_t next_io_size;
1643 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
1645 static struct tevent_req *vfswrap_offload_write_send(
1646 struct vfs_handle_struct *handle,
1647 TALLOC_CTX *mem_ctx,
1648 struct tevent_context *ev,
1651 off_t transfer_offset,
1652 struct files_struct *dest_fsp,
1656 struct tevent_req *req;
1657 struct vfswrap_offload_write_state *state = NULL;
1658 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
1659 files_struct *src_fsp = NULL;
1662 req = tevent_req_create(mem_ctx, &state,
1663 struct vfswrap_offload_write_state);
1668 *state = (struct vfswrap_offload_write_state) {
1671 .src_off = transfer_offset,
1672 .dst_fsp = dest_fsp,
1673 .dst_off = dest_off,
1675 .remaining = to_copy,
1679 case FSCTL_SRV_COPYCHUNK:
1680 case FSCTL_SRV_COPYCHUNK_WRITE:
1683 case FSCTL_OFFLOAD_WRITE:
1684 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
1685 return tevent_req_post(req, ev);
1687 case FSCTL_DUP_EXTENTS_TO_FILE:
1688 DBG_DEBUG("COW clones not supported by vfs_default\n");
1689 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1690 return tevent_req_post(req, ev);
1693 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1694 return tevent_req_post(req, ev);
1698 * From here on we assume a copy-chunk fsctl
1702 tevent_req_done(req);
1703 return tevent_req_post(req, ev);
1706 status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
1708 if (tevent_req_nterror(req, status)) {
1709 return tevent_req_post(req, ev);
1711 state->src_fsp = src_fsp;
1713 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
1715 status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
1716 if (!NT_STATUS_IS_OK(status)) {
1717 tevent_req_nterror(req, status);
1718 return tevent_req_post(req, ev);
1721 state->buf = talloc_array(state, uint8_t, num);
1722 if (tevent_req_nomem(state->buf, req)) {
1723 return tevent_req_post(req, ev);
1726 status = vfs_stat_fsp(src_fsp);
1727 if (tevent_req_nterror(req, status)) {
1728 return tevent_req_post(req, ev);
1731 if (src_fsp->fsp_name->st.st_ex_size < state->src_off + num) {
1733 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1734 * If the SourceOffset or SourceOffset + Length extends beyond
1735 * the end of file, the server SHOULD<240> treat this as a
1736 * STATUS_END_OF_FILE error.
1738 * <240> Section 3.3.5.15.6: Windows servers will return
1739 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1741 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1742 return tevent_req_post(req, ev);
1745 if (src_fsp->op == NULL) {
1746 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1747 return tevent_req_post(req, ev);
1750 if (dest_fsp->op == NULL) {
1751 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1752 return tevent_req_post(req, ev);
1755 status = vfswrap_offload_write_loop(req);
1756 if (!NT_STATUS_IS_OK(status)) {
1757 tevent_req_nterror(req, status);
1758 return tevent_req_post(req, ev);
1764 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
1766 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
1768 struct vfswrap_offload_write_state *state = tevent_req_data(
1769 req, struct vfswrap_offload_write_state);
1770 struct tevent_req *subreq = NULL;
1771 struct lock_struct read_lck;
1774 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
1776 init_strict_lock_struct(state->src_fsp,
1777 state->src_fsp->op->global->open_persistent_id,
1779 state->next_io_size,
1783 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
1787 return NT_STATUS_FILE_LOCK_CONFLICT;
1790 subreq = SMB_VFS_PREAD_SEND(state,
1791 state->src_fsp->conn->sconn->ev_ctx,
1794 state->next_io_size,
1796 if (subreq == NULL) {
1797 return NT_STATUS_NO_MEMORY;
1799 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
1801 return NT_STATUS_OK;
1804 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
1806 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
1808 struct tevent_req *req = tevent_req_callback_data(
1809 subreq, struct tevent_req);
1810 struct vfswrap_offload_write_state *state = tevent_req_data(
1811 req, struct vfswrap_offload_write_state);
1812 struct vfs_aio_state aio_state;
1813 struct lock_struct write_lck;
1817 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
1818 TALLOC_FREE(subreq);
1820 DBG_ERR("read failed: %s\n", strerror(errno));
1821 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1824 if (nread != state->next_io_size) {
1825 DBG_ERR("Short read, only %zd of %zu\n",
1826 nread, state->next_io_size);
1827 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1831 state->src_off += nread;
1833 init_strict_lock_struct(state->dst_fsp,
1834 state->dst_fsp->op->global->open_persistent_id,
1836 state->next_io_size,
1840 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
1844 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1848 subreq = SMB_VFS_PWRITE_SEND(state,
1852 state->next_io_size,
1854 if (subreq == NULL) {
1855 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1858 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
1861 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
1863 struct tevent_req *req = tevent_req_callback_data(
1864 subreq, struct tevent_req);
1865 struct vfswrap_offload_write_state *state = tevent_req_data(
1866 req, struct vfswrap_offload_write_state);
1867 struct vfs_aio_state aio_state;
1871 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
1872 TALLOC_FREE(subreq);
1873 if (nwritten == -1) {
1874 DBG_ERR("write failed: %s\n", strerror(errno));
1875 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1878 if (nwritten != state->next_io_size) {
1879 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
1880 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1884 state->dst_off += nwritten;
1886 if (state->remaining < nwritten) {
1887 /* Paranoia check */
1888 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1891 state->remaining -= nwritten;
1892 if (state->remaining == 0) {
1893 tevent_req_done(req);
1897 status = vfswrap_offload_write_loop(req);
1898 if (!NT_STATUS_IS_OK(status)) {
1899 tevent_req_nterror(req, status);
1906 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
1907 struct tevent_req *req,
1910 struct vfswrap_offload_write_state *state = tevent_req_data(
1911 req, struct vfswrap_offload_write_state);
1914 if (tevent_req_is_nterror(req, &status)) {
1915 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
1917 tevent_req_received(req);
1921 *copied = state->to_copy;
1922 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
1923 tevent_req_received(req);
1925 return NT_STATUS_OK;
1928 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1929 TALLOC_CTX *mem_ctx,
1930 struct files_struct *fsp,
1931 struct smb_filename *smb_fname,
1932 uint16_t *_compression_fmt)
1934 return NT_STATUS_INVALID_DEVICE_REQUEST;
1937 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1938 TALLOC_CTX *mem_ctx,
1939 struct files_struct *fsp,
1940 uint16_t compression_fmt)
1942 return NT_STATUS_INVALID_DEVICE_REQUEST;
1945 /********************************************************************
1946 Given a stat buffer return the allocated size on disk, taking into
1947 account sparse files.
1948 ********************************************************************/
1949 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1950 struct files_struct *fsp,
1951 const SMB_STRUCT_STAT *sbuf)
1955 START_PROFILE(syscall_get_alloc_size);
1957 if(S_ISDIR(sbuf->st_ex_mode)) {
1962 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1963 /* The type of st_blocksize is blkcnt_t which *MUST* be
1964 signed (according to POSIX) and can be less than 64-bits.
1965 Ensure when we're converting to 64 bits wide we don't
1967 #if defined(SIZEOF_BLKCNT_T_8)
1968 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1969 #elif defined(SIZEOF_BLKCNT_T_4)
1971 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1972 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1975 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1979 * Some file systems do not allocate a block for very
1980 * small files. But for non-empty file should report a
1984 uint64_t filesize = get_file_size_stat(sbuf);
1986 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
1990 result = get_file_size_stat(sbuf);
1993 if (fsp && fsp->initial_allocation_size)
1994 result = MAX(result,fsp->initial_allocation_size);
1996 result = smb_roundup(handle->conn, result);
1999 END_PROFILE(syscall_get_alloc_size);
2003 static int vfswrap_unlink(vfs_handle_struct *handle,
2004 const struct smb_filename *smb_fname)
2008 START_PROFILE(syscall_unlink);
2010 if (smb_fname->stream_name) {
2014 result = unlink(smb_fname->base_name);
2017 END_PROFILE(syscall_unlink);
2021 static int vfswrap_chmod(vfs_handle_struct *handle,
2022 const struct smb_filename *smb_fname,
2027 START_PROFILE(syscall_chmod);
2030 * We need to do this due to the fact that the default POSIX ACL
2031 * chmod modifies the ACL *mask* for the group owner, not the
2032 * group owner bits directly. JRA.
2037 int saved_errno = errno; /* We might get ENOSYS */
2038 result = SMB_VFS_CHMOD_ACL(handle->conn,
2042 END_PROFILE(syscall_chmod);
2045 /* Error - return the old errno. */
2046 errno = saved_errno;
2049 result = chmod(smb_fname->base_name, mode);
2050 END_PROFILE(syscall_chmod);
2054 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2058 START_PROFILE(syscall_fchmod);
2061 * We need to do this due to the fact that the default POSIX ACL
2062 * chmod modifies the ACL *mask* for the group owner, not the
2063 * group owner bits directly. JRA.
2067 int saved_errno = errno; /* We might get ENOSYS */
2068 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
2069 END_PROFILE(syscall_fchmod);
2072 /* Error - return the old errno. */
2073 errno = saved_errno;
2076 #if defined(HAVE_FCHMOD)
2077 result = fchmod(fsp->fh->fd, mode);
2083 END_PROFILE(syscall_fchmod);
2087 static int vfswrap_chown(vfs_handle_struct *handle,
2088 const struct smb_filename *smb_fname,
2094 START_PROFILE(syscall_chown);
2095 result = chown(smb_fname->base_name, uid, gid);
2096 END_PROFILE(syscall_chown);
2100 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2105 START_PROFILE(syscall_fchown);
2106 result = fchown(fsp->fh->fd, uid, gid);
2107 END_PROFILE(syscall_fchown);
2115 static int vfswrap_lchown(vfs_handle_struct *handle,
2116 const struct smb_filename *smb_fname,
2122 START_PROFILE(syscall_lchown);
2123 result = lchown(smb_fname->base_name, uid, gid);
2124 END_PROFILE(syscall_lchown);
2128 static int vfswrap_chdir(vfs_handle_struct *handle,
2129 const struct smb_filename *smb_fname)
2133 START_PROFILE(syscall_chdir);
2134 result = chdir(smb_fname->base_name);
2135 END_PROFILE(syscall_chdir);
2139 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2143 struct smb_filename *smb_fname = NULL;
2145 START_PROFILE(syscall_getwd);
2146 result = sys_getwd();
2147 END_PROFILE(syscall_getwd);
2149 if (result == NULL) {
2152 smb_fname = synthetic_smb_fname(ctx,
2158 * sys_getwd() *always* returns malloced memory.
2159 * We must free here to avoid leaks:
2160 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2166 /*********************************************************************
2167 nsec timestamp resolution call. Convert down to whatever the underlying
2168 system will support.
2169 **********************************************************************/
2171 static int vfswrap_ntimes(vfs_handle_struct *handle,
2172 const struct smb_filename *smb_fname,
2173 struct smb_file_time *ft)
2177 START_PROFILE(syscall_ntimes);
2179 if (smb_fname->stream_name) {
2185 if (null_timespec(ft->atime)) {
2186 ft->atime= smb_fname->st.st_ex_atime;
2189 if (null_timespec(ft->mtime)) {
2190 ft->mtime = smb_fname->st.st_ex_mtime;
2193 if (!null_timespec(ft->create_time)) {
2194 set_create_timespec_ea(handle->conn,
2199 if ((timespec_compare(&ft->atime,
2200 &smb_fname->st.st_ex_atime) == 0) &&
2201 (timespec_compare(&ft->mtime,
2202 &smb_fname->st.st_ex_mtime) == 0)) {
2207 #if defined(HAVE_UTIMENSAT)
2209 struct timespec ts[2];
2212 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2214 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2216 if (!((result == -1) && (errno == ENOSYS))) {
2220 #if defined(HAVE_UTIMES)
2222 struct timeval tv[2];
2223 tv[0] = convert_timespec_to_timeval(ft->atime);
2224 tv[1] = convert_timespec_to_timeval(ft->mtime);
2225 result = utimes(smb_fname->base_name, tv);
2227 result = utimes(smb_fname->base_name, NULL);
2229 if (!((result == -1) && (errno == ENOSYS))) {
2233 #if defined(HAVE_UTIME)
2235 struct utimbuf times;
2236 times.actime = convert_timespec_to_time_t(ft->atime);
2237 times.modtime = convert_timespec_to_time_t(ft->mtime);
2238 result = utime(smb_fname->base_name, ×);
2240 result = utime(smb_fname->base_name, NULL);
2242 if (!((result == -1) && (errno == ENOSYS))) {
2250 END_PROFILE(syscall_ntimes);
2254 /*********************************************************************
2255 A version of ftruncate that will write the space on disk if strict
2257 **********************************************************************/
2259 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2261 off_t space_to_write;
2262 uint64_t space_avail;
2263 uint64_t bsize,dfree,dsize;
2266 SMB_STRUCT_STAT *pst;
2268 status = vfs_stat_fsp(fsp);
2269 if (!NT_STATUS_IS_OK(status)) {
2272 pst = &fsp->fsp_name->st;
2275 if (S_ISFIFO(pst->st_ex_mode))
2279 if (pst->st_ex_size == len)
2282 /* Shrink - just ftruncate. */
2283 if (pst->st_ex_size > len)
2284 return ftruncate(fsp->fh->fd, len);
2286 space_to_write = len - pst->st_ex_size;
2288 /* for allocation try fallocate first. This can fail on some
2289 platforms e.g. when the filesystem doesn't support it and no
2290 emulation is being done by the libc (like on AIX with JFS1). In that
2291 case we do our own emulation. fallocate implementations can
2292 return ENOTSUP or EINVAL in cases like that. */
2293 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2294 if (ret == -1 && errno == ENOSPC) {
2300 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2301 "error %d. Falling back to slow manual allocation\n", errno));
2303 /* available disk space is enough or not? */
2305 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2306 /* space_avail is 1k blocks */
2307 if (space_avail == (uint64_t)-1 ||
2308 ((uint64_t)space_to_write/1024 > space_avail) ) {
2313 /* Write out the real space on disk. */
2314 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2322 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2325 SMB_STRUCT_STAT *pst;
2329 START_PROFILE(syscall_ftruncate);
2331 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2332 result = strict_allocate_ftruncate(handle, fsp, len);
2333 END_PROFILE(syscall_ftruncate);
2337 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2338 ftruncate if the system supports it. Then I discovered that
2339 you can have some filesystems that support ftruncate
2340 expansion and some that don't! On Linux fat can't do
2341 ftruncate extend but ext2 can. */
2343 result = ftruncate(fsp->fh->fd, len);
2345 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2346 extend a file with ftruncate. Provide alternate implementation
2349 /* Do an fstat to see if the file is longer than the requested
2350 size in which case the ftruncate above should have
2351 succeeded or shorter, in which case seek to len - 1 and
2352 write 1 byte of zero */
2353 status = vfs_stat_fsp(fsp);
2354 if (!NT_STATUS_IS_OK(status)) {
2358 /* We need to update the files_struct after successful ftruncate */
2363 pst = &fsp->fsp_name->st;
2366 if (S_ISFIFO(pst->st_ex_mode)) {
2372 if (pst->st_ex_size == len) {
2377 if (pst->st_ex_size > len) {
2378 /* the ftruncate should have worked */
2382 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2390 END_PROFILE(syscall_ftruncate);
2394 static int vfswrap_fallocate(vfs_handle_struct *handle,
2402 START_PROFILE(syscall_fallocate);
2404 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2406 * posix_fallocate returns 0 on success, errno on error
2407 * and doesn't set errno. Make it behave like fallocate()
2408 * which returns -1, and sets errno on failure.
2415 /* sys_fallocate handles filtering of unsupported mode flags */
2416 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2418 END_PROFILE(syscall_fallocate);
2422 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2426 START_PROFILE(syscall_fcntl_lock);
2428 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2430 "force process locks",
2432 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2435 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2436 END_PROFILE(syscall_fcntl_lock);
2440 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2441 uint32_t share_mode, uint32_t access_mask)
2443 START_PROFILE(syscall_kernel_flock);
2444 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2445 END_PROFILE(syscall_kernel_flock);
2449 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2454 START_PROFILE(syscall_fcntl_getlock);
2456 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2458 "force process locks",
2460 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2463 result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2464 END_PROFILE(syscall_fcntl_getlock);
2468 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2473 START_PROFILE(syscall_linux_setlease);
2475 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2476 result = linux_setlease(fsp->fh->fd, leasetype);
2480 END_PROFILE(syscall_linux_setlease);
2484 static int vfswrap_symlink(vfs_handle_struct *handle,
2485 const char *link_target,
2486 const struct smb_filename *new_smb_fname)
2490 START_PROFILE(syscall_symlink);
2491 result = symlink(link_target, new_smb_fname->base_name);
2492 END_PROFILE(syscall_symlink);
2496 static int vfswrap_readlink(vfs_handle_struct *handle,
2497 const struct smb_filename *smb_fname,
2503 START_PROFILE(syscall_readlink);
2504 result = readlink(smb_fname->base_name, buf, bufsiz);
2505 END_PROFILE(syscall_readlink);
2509 static int vfswrap_link(vfs_handle_struct *handle,
2510 const struct smb_filename *old_smb_fname,
2511 const struct smb_filename *new_smb_fname)
2515 START_PROFILE(syscall_link);
2516 result = link(old_smb_fname->base_name, new_smb_fname->base_name);
2517 END_PROFILE(syscall_link);
2521 static int vfswrap_mknod(vfs_handle_struct *handle,
2522 const struct smb_filename *smb_fname,
2528 START_PROFILE(syscall_mknod);
2529 result = sys_mknod(smb_fname->base_name, mode, dev);
2530 END_PROFILE(syscall_mknod);
2534 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2536 const struct smb_filename *smb_fname)
2539 struct smb_filename *result_fname = NULL;
2541 START_PROFILE(syscall_realpath);
2542 result = sys_realpath(smb_fname->base_name);
2543 END_PROFILE(syscall_realpath);
2545 result_fname = synthetic_smb_fname(ctx, result, NULL, NULL, 0);
2548 return result_fname;
2551 static int vfswrap_chflags(vfs_handle_struct *handle,
2552 const struct smb_filename *smb_fname,
2556 return chflags(smb_fname->base_name, flags);
2563 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2564 const SMB_STRUCT_STAT *sbuf)
2568 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2572 key.devid = sbuf->st_ex_dev;
2573 key.inode = sbuf->st_ex_ino;
2574 /* key.extid is unused by default. */
2579 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2580 struct files_struct *fsp,
2581 const struct smb_filename *smb_fname,
2582 TALLOC_CTX *mem_ctx,
2583 unsigned int *pnum_streams,
2584 struct stream_struct **pstreams)
2586 SMB_STRUCT_STAT sbuf;
2587 struct stream_struct *tmp_streams = NULL;
2590 if ((fsp != NULL) && (fsp->is_directory)) {
2592 * No default streams on directories
2597 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2598 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2601 struct smb_filename smb_fname_cp;
2603 ZERO_STRUCT(smb_fname_cp);
2604 smb_fname_cp.base_name = discard_const_p(char,
2605 smb_fname->base_name);
2606 smb_fname_cp.flags = smb_fname->flags;
2608 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
2609 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2611 ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2613 sbuf = smb_fname_cp.st;
2617 return map_nt_error_from_unix(errno);
2620 if (S_ISDIR(sbuf.st_ex_mode)) {
2624 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2625 (*pnum_streams) + 1);
2626 if (tmp_streams == NULL) {
2627 return NT_STATUS_NO_MEMORY;
2629 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2630 if (tmp_streams[*pnum_streams].name == NULL) {
2631 return NT_STATUS_NO_MEMORY;
2633 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2634 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2637 *pstreams = tmp_streams;
2639 return NT_STATUS_OK;
2642 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2645 TALLOC_CTX *mem_ctx,
2649 * Don't fall back to get_real_filename so callers can differentiate
2650 * between a full directory scan and an actual case-insensitive stat.
2656 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2657 const struct smb_filename *smb_fname)
2659 return handle->conn->connectpath;
2662 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2663 struct byte_range_lock *br_lck,
2664 struct lock_struct *plock,
2667 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2669 /* Note: blr is not used in the default implementation. */
2670 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2673 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2674 struct messaging_context *msg_ctx,
2675 struct byte_range_lock *br_lck,
2676 const struct lock_struct *plock)
2678 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2680 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2683 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2684 struct byte_range_lock *br_lck,
2685 struct lock_struct *plock)
2687 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2689 /* Note: blr is not used in the default implementation. */
2690 return brl_lock_cancel_default(br_lck, plock);
2693 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
2695 struct lock_struct *plock)
2697 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2698 plock->lock_type == WRITE_LOCK);
2700 return strict_lock_check_default(fsp, plock);
2703 /* NT ACL operations. */
2705 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2707 uint32_t security_info,
2708 TALLOC_CTX *mem_ctx,
2709 struct security_descriptor **ppdesc)
2713 START_PROFILE(fget_nt_acl);
2714 result = posix_fget_nt_acl(fsp, security_info,
2716 END_PROFILE(fget_nt_acl);
2720 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2721 const struct smb_filename *smb_fname,
2722 uint32_t security_info,
2723 TALLOC_CTX *mem_ctx,
2724 struct security_descriptor **ppdesc)
2728 START_PROFILE(get_nt_acl);
2729 result = posix_get_nt_acl(handle->conn,
2734 END_PROFILE(get_nt_acl);
2738 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2742 START_PROFILE(fset_nt_acl);
2743 result = set_nt_acl(fsp, security_info_sent, psd);
2744 END_PROFILE(fset_nt_acl);
2748 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2749 struct smb_filename *file,
2750 struct security_acl *sacl,
2751 uint32_t access_requested,
2752 uint32_t access_denied)
2754 return NT_STATUS_OK; /* Nothing to do here ... */
2757 static int vfswrap_chmod_acl(vfs_handle_struct *handle,
2758 const struct smb_filename *smb_fname,
2767 START_PROFILE(chmod_acl);
2768 result = chmod_acl(handle->conn, smb_fname, mode);
2769 END_PROFILE(chmod_acl);
2774 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2782 START_PROFILE(fchmod_acl);
2783 result = fchmod_acl(fsp, mode);
2784 END_PROFILE(fchmod_acl);
2789 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2790 const struct smb_filename *smb_fname,
2791 SMB_ACL_TYPE_T type,
2792 TALLOC_CTX *mem_ctx)
2794 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
2797 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2799 TALLOC_CTX *mem_ctx)
2801 return sys_acl_get_fd(handle, fsp, mem_ctx);
2804 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
2805 const struct smb_filename *smb_fname,
2806 SMB_ACL_TYPE_T acltype,
2809 return sys_acl_set_file(handle, smb_fname, acltype, theacl);
2812 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2814 return sys_acl_set_fd(handle, fsp, theacl);
2817 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
2818 const struct smb_filename *smb_fname)
2820 return sys_acl_delete_def_file(handle, smb_fname);
2823 /****************************************************************
2824 Extended attribute operations.
2825 *****************************************************************/
2827 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
2828 const struct smb_filename *smb_fname,
2833 return getxattr(smb_fname->base_name, name, value, size);
2836 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2838 return fgetxattr(fsp->fh->fd, name, value, size);
2841 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
2842 const struct smb_filename *smb_fname,
2846 return listxattr(smb_fname->base_name, list, size);
2849 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2851 return flistxattr(fsp->fh->fd, list, size);
2854 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
2855 const struct smb_filename *smb_fname,
2858 return removexattr(smb_fname->base_name, name);
2861 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2863 return fremovexattr(fsp->fh->fd, name);
2866 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
2867 const struct smb_filename *smb_fname,
2873 return setxattr(smb_fname->base_name, name, value, size, flags);
2876 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2878 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2881 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2886 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2887 const struct smb_filename *fname,
2888 SMB_STRUCT_STAT *sbuf)
2892 bool offline = false;
2894 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2898 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2899 #if defined(ENOTSUP)
2905 status = get_full_smb_filename(talloc_tos(), fname, &path);
2906 if (!NT_STATUS_IS_OK(status)) {
2907 errno = map_errno_from_nt_status(status);
2911 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2918 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2919 struct files_struct *fsp,
2920 TALLOC_CTX *mem_ctx,
2923 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2926 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2927 struct files_struct *fsp,
2928 const DATA_BLOB old_cookie,
2929 TALLOC_CTX *mem_ctx,
2930 DATA_BLOB *new_cookie)
2932 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2936 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2937 struct smb_request *smb1req,
2938 struct smbXsrv_open *op,
2939 const DATA_BLOB old_cookie,
2940 TALLOC_CTX *mem_ctx,
2941 struct files_struct **fsp,
2942 DATA_BLOB *new_cookie)
2944 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2945 old_cookie, mem_ctx,
2949 static struct vfs_fn_pointers vfs_default_fns = {
2950 /* Disk operations */
2952 .connect_fn = vfswrap_connect,
2953 .disconnect_fn = vfswrap_disconnect,
2954 .disk_free_fn = vfswrap_disk_free,
2955 .get_quota_fn = vfswrap_get_quota,
2956 .set_quota_fn = vfswrap_set_quota,
2957 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2958 .statvfs_fn = vfswrap_statvfs,
2959 .fs_capabilities_fn = vfswrap_fs_capabilities,
2960 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2961 .snap_check_path_fn = vfswrap_snap_check_path,
2962 .snap_create_fn = vfswrap_snap_create,
2963 .snap_delete_fn = vfswrap_snap_delete,
2965 /* Directory operations */
2967 .opendir_fn = vfswrap_opendir,
2968 .fdopendir_fn = vfswrap_fdopendir,
2969 .readdir_fn = vfswrap_readdir,
2970 .readdir_attr_fn = vfswrap_readdir_attr,
2971 .seekdir_fn = vfswrap_seekdir,
2972 .telldir_fn = vfswrap_telldir,
2973 .rewind_dir_fn = vfswrap_rewinddir,
2974 .mkdir_fn = vfswrap_mkdir,
2975 .rmdir_fn = vfswrap_rmdir,
2976 .closedir_fn = vfswrap_closedir,
2978 /* File operations */
2980 .open_fn = vfswrap_open,
2981 .create_file_fn = vfswrap_create_file,
2982 .close_fn = vfswrap_close,
2983 .pread_fn = vfswrap_pread,
2984 .pread_send_fn = vfswrap_pread_send,
2985 .pread_recv_fn = vfswrap_pread_recv,
2986 .write_fn = vfswrap_write,
2987 .pwrite_fn = vfswrap_pwrite,
2988 .pwrite_send_fn = vfswrap_pwrite_send,
2989 .pwrite_recv_fn = vfswrap_pwrite_recv,
2990 .lseek_fn = vfswrap_lseek,
2991 .sendfile_fn = vfswrap_sendfile,
2992 .recvfile_fn = vfswrap_recvfile,
2993 .rename_fn = vfswrap_rename,
2994 .fsync_send_fn = vfswrap_fsync_send,
2995 .fsync_recv_fn = vfswrap_fsync_recv,
2996 .stat_fn = vfswrap_stat,
2997 .fstat_fn = vfswrap_fstat,
2998 .lstat_fn = vfswrap_lstat,
2999 .get_alloc_size_fn = vfswrap_get_alloc_size,
3000 .unlink_fn = vfswrap_unlink,
3001 .chmod_fn = vfswrap_chmod,
3002 .fchmod_fn = vfswrap_fchmod,
3003 .chown_fn = vfswrap_chown,
3004 .fchown_fn = vfswrap_fchown,
3005 .lchown_fn = vfswrap_lchown,
3006 .chdir_fn = vfswrap_chdir,
3007 .getwd_fn = vfswrap_getwd,
3008 .ntimes_fn = vfswrap_ntimes,
3009 .ftruncate_fn = vfswrap_ftruncate,
3010 .fallocate_fn = vfswrap_fallocate,
3011 .lock_fn = vfswrap_lock,
3012 .kernel_flock_fn = vfswrap_kernel_flock,
3013 .linux_setlease_fn = vfswrap_linux_setlease,
3014 .getlock_fn = vfswrap_getlock,
3015 .symlink_fn = vfswrap_symlink,
3016 .readlink_fn = vfswrap_readlink,
3017 .link_fn = vfswrap_link,
3018 .mknod_fn = vfswrap_mknod,
3019 .realpath_fn = vfswrap_realpath,
3020 .chflags_fn = vfswrap_chflags,
3021 .file_id_create_fn = vfswrap_file_id_create,
3022 .streaminfo_fn = vfswrap_streaminfo,
3023 .get_real_filename_fn = vfswrap_get_real_filename,
3024 .connectpath_fn = vfswrap_connectpath,
3025 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
3026 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3027 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
3028 .strict_lock_check_fn = vfswrap_strict_lock_check,
3029 .translate_name_fn = vfswrap_translate_name,
3030 .fsctl_fn = vfswrap_fsctl,
3031 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
3032 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
3033 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
3034 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
3035 .offload_read_send_fn = vfswrap_offload_read_send,
3036 .offload_read_recv_fn = vfswrap_offload_read_recv,
3037 .offload_write_send_fn = vfswrap_offload_write_send,
3038 .offload_write_recv_fn = vfswrap_offload_write_recv,
3039 .get_compression_fn = vfswrap_get_compression,
3040 .set_compression_fn = vfswrap_set_compression,
3042 /* NT ACL operations. */
3044 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
3045 .get_nt_acl_fn = vfswrap_get_nt_acl,
3046 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
3047 .audit_file_fn = vfswrap_audit_file,
3049 /* POSIX ACL operations. */
3051 .chmod_acl_fn = vfswrap_chmod_acl,
3052 .fchmod_acl_fn = vfswrap_fchmod_acl,
3054 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
3055 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3056 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
3057 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3058 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
3059 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3060 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
3062 /* EA operations. */
3063 .getxattr_fn = vfswrap_getxattr,
3064 .fgetxattr_fn = vfswrap_fgetxattr,
3065 .listxattr_fn = vfswrap_listxattr,
3066 .flistxattr_fn = vfswrap_flistxattr,
3067 .removexattr_fn = vfswrap_removexattr,
3068 .fremovexattr_fn = vfswrap_fremovexattr,
3069 .setxattr_fn = vfswrap_setxattr,
3070 .fsetxattr_fn = vfswrap_fsetxattr,
3072 /* aio operations */
3073 .aio_force_fn = vfswrap_aio_force,
3075 /* durable handle operations */
3076 .durable_cookie_fn = vfswrap_durable_cookie,
3077 .durable_disconnect_fn = vfswrap_durable_disconnect,
3078 .durable_reconnect_fn = vfswrap_durable_reconnect,
3082 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3084 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3085 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);