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 = sys_write(fsp->fh->fd, data, n);
666 #else /* HAVE_PWRITE */
669 #endif /* HAVE_PWRITE */
674 struct vfswrap_pread_state {
681 struct vfs_aio_state vfs_aio_state;
682 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
685 static void vfs_pread_do(void *private_data);
686 static void vfs_pread_done(struct tevent_req *subreq);
687 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state);
689 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
691 struct tevent_context *ev,
692 struct files_struct *fsp,
694 size_t n, off_t offset)
696 struct tevent_req *req, *subreq;
697 struct vfswrap_pread_state *state;
699 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
705 state->fd = fsp->fh->fd;
708 state->offset = offset;
710 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
711 state->profile_bytes, n);
712 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
714 subreq = pthreadpool_tevent_job_send(
715 state, ev, handle->conn->sconn->pool,
716 vfs_pread_do, state);
717 if (tevent_req_nomem(subreq, req)) {
718 return tevent_req_post(req, ev);
720 tevent_req_set_callback(subreq, vfs_pread_done, req);
722 talloc_set_destructor(state, vfs_pread_state_destructor);
727 static void vfs_pread_do(void *private_data)
729 struct vfswrap_pread_state *state = talloc_get_type_abort(
730 private_data, struct vfswrap_pread_state);
731 struct timespec start_time;
732 struct timespec end_time;
734 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
736 PROFILE_TIMESTAMP(&start_time);
739 state->ret = pread(state->fd, state->buf, state->count,
741 } while ((state->ret == -1) && (errno == EINTR));
743 if (state->ret == -1) {
744 state->vfs_aio_state.error = errno;
747 PROFILE_TIMESTAMP(&end_time);
749 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
751 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
754 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state)
759 static void vfs_pread_done(struct tevent_req *subreq)
761 struct tevent_req *req = tevent_req_callback_data(
762 subreq, struct tevent_req);
763 struct vfswrap_pread_state *state = tevent_req_data(
764 req, struct vfswrap_pread_state);
767 ret = pthreadpool_tevent_job_recv(subreq);
769 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
770 talloc_set_destructor(state, NULL);
771 if (tevent_req_error(req, ret)) {
775 tevent_req_done(req);
778 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
779 struct vfs_aio_state *vfs_aio_state)
781 struct vfswrap_pread_state *state = tevent_req_data(
782 req, struct vfswrap_pread_state);
784 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
788 *vfs_aio_state = state->vfs_aio_state;
792 struct vfswrap_pwrite_state {
799 struct vfs_aio_state vfs_aio_state;
800 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
803 static void vfs_pwrite_do(void *private_data);
804 static void vfs_pwrite_done(struct tevent_req *subreq);
805 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state);
807 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
809 struct tevent_context *ev,
810 struct files_struct *fsp,
812 size_t n, off_t offset)
814 struct tevent_req *req, *subreq;
815 struct vfswrap_pwrite_state *state;
817 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
823 state->fd = fsp->fh->fd;
826 state->offset = offset;
828 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
829 state->profile_bytes, n);
830 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
832 subreq = pthreadpool_tevent_job_send(
833 state, ev, handle->conn->sconn->pool,
834 vfs_pwrite_do, state);
835 if (tevent_req_nomem(subreq, req)) {
836 return tevent_req_post(req, ev);
838 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
840 talloc_set_destructor(state, vfs_pwrite_state_destructor);
845 static void vfs_pwrite_do(void *private_data)
847 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
848 private_data, struct vfswrap_pwrite_state);
849 struct timespec start_time;
850 struct timespec end_time;
852 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
854 PROFILE_TIMESTAMP(&start_time);
857 state->ret = pwrite(state->fd, state->buf, state->count,
859 } while ((state->ret == -1) && (errno == EINTR));
861 if (state->ret == -1) {
862 state->vfs_aio_state.error = errno;
865 PROFILE_TIMESTAMP(&end_time);
867 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
869 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
872 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state)
877 static void vfs_pwrite_done(struct tevent_req *subreq)
879 struct tevent_req *req = tevent_req_callback_data(
880 subreq, struct tevent_req);
881 struct vfswrap_pwrite_state *state = tevent_req_data(
882 req, struct vfswrap_pwrite_state);
885 ret = pthreadpool_tevent_job_recv(subreq);
887 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
888 talloc_set_destructor(state, NULL);
889 if (tevent_req_error(req, ret)) {
893 tevent_req_done(req);
896 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
897 struct vfs_aio_state *vfs_aio_state)
899 struct vfswrap_pwrite_state *state = tevent_req_data(
900 req, struct vfswrap_pwrite_state);
902 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
906 *vfs_aio_state = state->vfs_aio_state;
910 struct vfswrap_fsync_state {
914 struct vfs_aio_state vfs_aio_state;
915 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
918 static void vfs_fsync_do(void *private_data);
919 static void vfs_fsync_done(struct tevent_req *subreq);
920 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state);
922 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
924 struct tevent_context *ev,
925 struct files_struct *fsp)
927 struct tevent_req *req, *subreq;
928 struct vfswrap_fsync_state *state;
930 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
936 state->fd = fsp->fh->fd;
938 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
939 state->profile_basic);
941 subreq = pthreadpool_tevent_job_send(
942 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
943 if (tevent_req_nomem(subreq, req)) {
944 return tevent_req_post(req, ev);
946 tevent_req_set_callback(subreq, vfs_fsync_done, req);
948 talloc_set_destructor(state, vfs_fsync_state_destructor);
953 static void vfs_fsync_do(void *private_data)
955 struct vfswrap_fsync_state *state = talloc_get_type_abort(
956 private_data, struct vfswrap_fsync_state);
957 struct timespec start_time;
958 struct timespec end_time;
960 PROFILE_TIMESTAMP(&start_time);
963 state->ret = fsync(state->fd);
964 } while ((state->ret == -1) && (errno == EINTR));
966 if (state->ret == -1) {
967 state->vfs_aio_state.error = errno;
970 PROFILE_TIMESTAMP(&end_time);
972 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
975 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state)
980 static void vfs_fsync_done(struct tevent_req *subreq)
982 struct tevent_req *req = tevent_req_callback_data(
983 subreq, struct tevent_req);
984 struct vfswrap_fsync_state *state = tevent_req_data(
985 req, struct vfswrap_fsync_state);
988 ret = pthreadpool_tevent_job_recv(subreq);
990 SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
991 talloc_set_destructor(state, NULL);
992 if (tevent_req_error(req, ret)) {
996 tevent_req_done(req);
999 static int vfswrap_fsync_recv(struct tevent_req *req,
1000 struct vfs_aio_state *vfs_aio_state)
1002 struct vfswrap_fsync_state *state = tevent_req_data(
1003 req, struct vfswrap_fsync_state);
1005 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1009 *vfs_aio_state = state->vfs_aio_state;
1013 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1017 START_PROFILE(syscall_lseek);
1019 /* Cope with 'stat' file opens. */
1020 if (fsp->fh->fd != -1)
1021 result = lseek(fsp->fh->fd, offset, whence);
1024 * We want to maintain the fiction that we can seek
1025 * on a fifo for file system purposes. This allows
1026 * people to set up UNIX fifo's that feed data to Windows
1027 * applications. JRA.
1030 if((result == -1) && (errno == ESPIPE)) {
1035 END_PROFILE(syscall_lseek);
1039 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1040 off_t offset, size_t n)
1044 START_PROFILE_BYTES(syscall_sendfile, n);
1045 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
1046 END_PROFILE_BYTES(syscall_sendfile);
1050 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1052 files_struct *tofsp,
1058 START_PROFILE_BYTES(syscall_recvfile, n);
1059 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
1060 END_PROFILE_BYTES(syscall_recvfile);
1064 static int vfswrap_rename(vfs_handle_struct *handle,
1065 const struct smb_filename *smb_fname_src,
1066 const struct smb_filename *smb_fname_dst)
1070 START_PROFILE(syscall_rename);
1072 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
1077 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
1080 END_PROFILE(syscall_rename);
1084 static int vfswrap_stat(vfs_handle_struct *handle,
1085 struct smb_filename *smb_fname)
1089 START_PROFILE(syscall_stat);
1091 if (smb_fname->stream_name) {
1096 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1097 lp_fake_directory_create_times(SNUM(handle->conn)));
1099 END_PROFILE(syscall_stat);
1103 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1107 START_PROFILE(syscall_fstat);
1108 result = sys_fstat(fsp->fh->fd,
1109 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1110 END_PROFILE(syscall_fstat);
1114 static int vfswrap_lstat(vfs_handle_struct *handle,
1115 struct smb_filename *smb_fname)
1119 START_PROFILE(syscall_lstat);
1121 if (smb_fname->stream_name) {
1126 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1127 lp_fake_directory_create_times(SNUM(handle->conn)));
1129 END_PROFILE(syscall_lstat);
1133 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1135 enum vfs_translate_direction direction,
1136 TALLOC_CTX *mem_ctx,
1139 return NT_STATUS_NONE_MAPPED;
1143 * Implement the default fsctl operation.
1145 static bool vfswrap_logged_ioctl_message = false;
1147 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1148 struct files_struct *fsp,
1151 uint16_t req_flags, /* Needed for UNICODE ... */
1152 const uint8_t *_in_data,
1154 uint8_t **_out_data,
1155 uint32_t max_out_len,
1158 const char *in_data = (const char *)_in_data;
1159 char **out_data = (char **)_out_data;
1163 case FSCTL_SET_SPARSE:
1165 bool set_sparse = true;
1167 if (in_len >= 1 && in_data[0] == 0) {
1171 status = file_set_sparse(handle->conn, fsp, set_sparse);
1173 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1174 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1175 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1176 nt_errstr(status)));
1181 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1183 unsigned char objid[16];
1184 char *return_data = NULL;
1186 /* This should return the object-id on this file.
1187 * I think I'll make this be the inode+dev. JRA.
1190 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1191 fsp_fnum_dbg(fsp)));
1193 *out_len = MIN(max_out_len, 64);
1195 /* Hmmm, will this cause problems if less data asked for? */
1196 return_data = talloc_array(ctx, char, 64);
1197 if (return_data == NULL) {
1198 return NT_STATUS_NO_MEMORY;
1201 /* For backwards compatibility only store the dev/inode. */
1202 push_file_id_16(return_data, &fsp->file_id);
1203 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1204 push_file_id_16(return_data+32, &fsp->file_id);
1205 memset(return_data+48, 0, 16);
1206 *out_data = return_data;
1207 return NT_STATUS_OK;
1210 case FSCTL_GET_REPARSE_POINT:
1212 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1213 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1214 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1215 return NT_STATUS_NOT_A_REPARSE_POINT;
1218 case FSCTL_SET_REPARSE_POINT:
1220 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1221 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1222 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1223 return NT_STATUS_NOT_A_REPARSE_POINT;
1226 case FSCTL_GET_SHADOW_COPY_DATA:
1229 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1230 * and return their volume names. If max_data_count is 16, then it is just
1231 * asking for the number of volumes and length of the combined names.
1233 * pdata is the data allocated by our caller, but that uses
1234 * total_data_count (which is 0 in our case) rather than max_data_count.
1235 * Allocate the correct amount and return the pointer to let
1236 * it be deallocated when we return.
1238 struct shadow_copy_data *shadow_data = NULL;
1239 bool labels = False;
1240 uint32_t labels_data_count = 0;
1242 char *cur_pdata = NULL;
1244 if (max_out_len < 16) {
1245 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1247 return NT_STATUS_INVALID_PARAMETER;
1250 if (max_out_len > 16) {
1254 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1255 if (shadow_data == NULL) {
1256 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1257 return NT_STATUS_NO_MEMORY;
1261 * Call the VFS routine to actually do the work.
1263 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1266 /* broken module didn't set errno on error */
1267 status = NT_STATUS_UNSUCCESSFUL;
1269 status = map_nt_error_from_unix(errno);
1270 if (NT_STATUS_EQUAL(status,
1271 NT_STATUS_NOT_SUPPORTED)) {
1275 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1276 "connectpath %s, failed - %s.\n",
1277 fsp->conn->connectpath,
1278 nt_errstr(status)));
1279 TALLOC_FREE(shadow_data);
1283 labels_data_count = (shadow_data->num_volumes * 2 *
1284 sizeof(SHADOW_COPY_LABEL)) + 2;
1289 *out_len = 12 + labels_data_count;
1292 if (max_out_len < *out_len) {
1293 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1294 max_out_len, *out_len));
1295 TALLOC_FREE(shadow_data);
1296 return NT_STATUS_BUFFER_TOO_SMALL;
1299 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1300 if (cur_pdata == NULL) {
1301 TALLOC_FREE(shadow_data);
1302 return NT_STATUS_NO_MEMORY;
1305 *out_data = cur_pdata;
1307 /* num_volumes 4 bytes */
1308 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1311 /* num_labels 4 bytes */
1312 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1315 /* needed_data_count 4 bytes */
1316 SIVAL(cur_pdata, 8, labels_data_count);
1320 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1321 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1322 if (labels && shadow_data->labels) {
1323 for (i=0; i<shadow_data->num_volumes; i++) {
1325 status = srvstr_push(cur_pdata, req_flags,
1326 cur_pdata, shadow_data->labels[i],
1327 2 * sizeof(SHADOW_COPY_LABEL),
1328 STR_UNICODE|STR_TERMINATE, &len);
1329 if (!NT_STATUS_IS_OK(status)) {
1330 TALLOC_FREE(*out_data);
1331 TALLOC_FREE(shadow_data);
1334 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1335 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1339 TALLOC_FREE(shadow_data);
1341 return NT_STATUS_OK;
1344 case FSCTL_FIND_FILES_BY_SID:
1346 /* pretend this succeeded -
1348 * we have to send back a list with all files owned by this SID
1350 * but I have to check that --metze
1356 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1357 fsp_fnum_dbg(fsp)));
1360 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1361 return NT_STATUS_INVALID_PARAMETER;
1364 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1366 /* unknown 4 bytes: this is not the length of the sid :-( */
1367 /*unknown = IVAL(pdata,0);*/
1369 if (!sid_parse(_in_data + 4, sid_len, &sid)) {
1370 return NT_STATUS_INVALID_PARAMETER;
1372 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1374 if (!sid_to_uid(&sid, &uid)) {
1375 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1376 sid_string_dbg(&sid),
1377 (unsigned long)sid_len));
1381 /* we can take a look at the find source :-)
1383 * find ./ -uid $uid -name '*' is what we need here
1386 * and send 4bytes len and then NULL terminated unicode strings
1389 * but I don't know how to deal with the paged results
1390 * (maybe we can hang the result anywhere in the fsp struct)
1392 * but I don't know how to deal with the paged results
1393 * (maybe we can hang the result anywhere in the fsp struct)
1395 * we don't send all files at once
1396 * and at the next we should *not* start from the beginning,
1397 * so we have to cache the result
1402 /* this works for now... */
1403 return NT_STATUS_OK;
1406 case FSCTL_QUERY_ALLOCATED_RANGES:
1408 /* FIXME: This is just a dummy reply, telling that all of the
1409 * file is allocated. MKS cp needs that.
1410 * Adding the real allocated ranges via FIEMAP on Linux
1411 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1412 * this FSCTL correct for sparse files.
1414 uint64_t offset, length;
1415 char *out_data_tmp = NULL;
1418 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1420 return NT_STATUS_INVALID_PARAMETER;
1423 if (max_out_len < 16) {
1424 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1426 return NT_STATUS_INVALID_PARAMETER;
1429 offset = BVAL(in_data,0);
1430 length = BVAL(in_data,8);
1432 if (offset + length < offset) {
1433 /* No 64-bit integer wrap. */
1434 return NT_STATUS_INVALID_PARAMETER;
1437 /* Shouldn't this be SMB_VFS_STAT ... ? */
1438 status = vfs_stat_fsp(fsp);
1439 if (!NT_STATUS_IS_OK(status)) {
1444 out_data_tmp = talloc_array(ctx, char, *out_len);
1445 if (out_data_tmp == NULL) {
1446 DEBUG(10, ("unable to allocate memory for response\n"));
1447 return NT_STATUS_NO_MEMORY;
1450 if (offset > fsp->fsp_name->st.st_ex_size ||
1451 fsp->fsp_name->st.st_ex_size == 0 ||
1453 memset(out_data_tmp, 0, *out_len);
1455 uint64_t end = offset + length;
1456 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1457 SBVAL(out_data_tmp, 0, 0);
1458 SBVAL(out_data_tmp, 8, end);
1461 *out_data = out_data_tmp;
1463 return NT_STATUS_OK;
1466 case FSCTL_IS_VOLUME_DIRTY:
1468 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1469 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1471 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1472 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1474 return NT_STATUS_INVALID_PARAMETER;
1479 * Only print once ... unfortunately there could be lots of
1480 * different FSCTLs that are called.
1482 if (!vfswrap_logged_ioctl_message) {
1483 vfswrap_logged_ioctl_message = true;
1484 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1485 __func__, function));
1489 return NT_STATUS_NOT_SUPPORTED;
1492 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
1493 const struct smb_filename *fname,
1494 SMB_STRUCT_STAT *sbuf);
1496 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1497 struct smb_filename *smb_fname,
1502 offline = vfswrap_is_offline(handle, smb_fname, &smb_fname->st);
1504 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1507 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1510 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1511 struct files_struct *fsp,
1516 offline = vfswrap_is_offline(handle, fsp->fsp_name, &fsp->fsp_name->st);
1518 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1521 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1524 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1525 const struct smb_filename *smb_fname,
1528 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1531 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1532 struct files_struct *fsp,
1535 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1538 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1540 struct vfswrap_offload_read_state {
1544 static struct tevent_req *vfswrap_offload_read_send(
1545 TALLOC_CTX *mem_ctx,
1546 struct tevent_context *ev,
1547 struct vfs_handle_struct *handle,
1548 struct files_struct *fsp,
1554 struct tevent_req *req = NULL;
1555 struct vfswrap_offload_read_state *state = NULL;
1558 req = tevent_req_create(mem_ctx, &state,
1559 struct vfswrap_offload_read_state);
1564 status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1565 &vfswrap_offload_ctx);
1566 if (tevent_req_nterror(req, status)) {
1567 return tevent_req_post(req, ev);
1570 if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1571 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1572 return tevent_req_post(req, ev);
1575 status = vfs_offload_token_create_blob(state, fsp, fsctl,
1577 if (tevent_req_nterror(req, status)) {
1578 return tevent_req_post(req, ev);
1581 status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1583 if (tevent_req_nterror(req, status)) {
1584 return tevent_req_post(req, ev);
1587 tevent_req_done(req);
1588 return tevent_req_post(req, ev);
1591 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
1592 struct vfs_handle_struct *handle,
1593 TALLOC_CTX *mem_ctx,
1596 struct vfswrap_offload_read_state *state = tevent_req_data(
1597 req, struct vfswrap_offload_read_state);
1600 if (tevent_req_is_nterror(req, &status)) {
1601 tevent_req_received(req);
1605 token->length = state->token.length;
1606 token->data = talloc_move(mem_ctx, &state->token.data);
1608 tevent_req_received(req);
1609 return NT_STATUS_OK;
1612 struct vfswrap_offload_write_state {
1613 struct tevent_context *ev;
1615 bool read_lck_locked;
1616 bool write_lck_locked;
1618 struct files_struct *src_fsp;
1620 struct files_struct *dst_fsp;
1624 size_t next_io_size;
1627 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
1629 static struct tevent_req *vfswrap_offload_write_send(
1630 struct vfs_handle_struct *handle,
1631 TALLOC_CTX *mem_ctx,
1632 struct tevent_context *ev,
1635 off_t transfer_offset,
1636 struct files_struct *dest_fsp,
1640 struct tevent_req *req;
1641 struct vfswrap_offload_write_state *state = NULL;
1642 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
1643 files_struct *src_fsp = NULL;
1646 req = tevent_req_create(mem_ctx, &state,
1647 struct vfswrap_offload_write_state);
1652 *state = (struct vfswrap_offload_write_state) {
1655 .src_off = transfer_offset,
1656 .dst_fsp = dest_fsp,
1657 .dst_off = dest_off,
1659 .remaining = to_copy,
1663 case FSCTL_SRV_COPYCHUNK:
1664 case FSCTL_SRV_COPYCHUNK_WRITE:
1667 case FSCTL_OFFLOAD_WRITE:
1668 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
1669 return tevent_req_post(req, ev);
1671 case FSCTL_DUP_EXTENTS_TO_FILE:
1672 DBG_DEBUG("COW clones not supported by vfs_default\n");
1673 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1674 return tevent_req_post(req, ev);
1677 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1678 return tevent_req_post(req, ev);
1682 * From here on we assume a copy-chunk fsctl
1686 tevent_req_done(req);
1687 return tevent_req_post(req, ev);
1690 status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
1692 if (tevent_req_nterror(req, status)) {
1693 return tevent_req_post(req, ev);
1695 state->src_fsp = src_fsp;
1697 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
1699 status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
1700 if (!NT_STATUS_IS_OK(status)) {
1701 tevent_req_nterror(req, status);
1702 return tevent_req_post(req, ev);
1705 state->buf = talloc_array(state, uint8_t, num);
1706 if (tevent_req_nomem(state->buf, req)) {
1707 return tevent_req_post(req, ev);
1710 status = vfs_stat_fsp(src_fsp);
1711 if (tevent_req_nterror(req, status)) {
1712 return tevent_req_post(req, ev);
1715 if (src_fsp->fsp_name->st.st_ex_size < state->src_off + num) {
1717 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1718 * If the SourceOffset or SourceOffset + Length extends beyond
1719 * the end of file, the server SHOULD<240> treat this as a
1720 * STATUS_END_OF_FILE error.
1722 * <240> Section 3.3.5.15.6: Windows servers will return
1723 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1725 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1726 return tevent_req_post(req, ev);
1729 if (src_fsp->op == NULL) {
1730 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1731 return tevent_req_post(req, ev);
1734 if (dest_fsp->op == NULL) {
1735 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1736 return tevent_req_post(req, ev);
1739 status = vfswrap_offload_write_loop(req);
1740 if (!NT_STATUS_IS_OK(status)) {
1741 tevent_req_nterror(req, status);
1742 return tevent_req_post(req, ev);
1748 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
1750 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
1752 struct vfswrap_offload_write_state *state = tevent_req_data(
1753 req, struct vfswrap_offload_write_state);
1754 struct tevent_req *subreq = NULL;
1755 struct lock_struct read_lck;
1758 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
1760 init_strict_lock_struct(state->src_fsp,
1761 state->src_fsp->op->global->open_persistent_id,
1763 state->next_io_size,
1767 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
1771 return NT_STATUS_FILE_LOCK_CONFLICT;
1774 subreq = SMB_VFS_PREAD_SEND(state,
1775 state->src_fsp->conn->sconn->ev_ctx,
1778 state->next_io_size,
1780 if (subreq == NULL) {
1781 return NT_STATUS_NO_MEMORY;
1783 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
1785 return NT_STATUS_OK;
1788 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
1790 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
1792 struct tevent_req *req = tevent_req_callback_data(
1793 subreq, struct tevent_req);
1794 struct vfswrap_offload_write_state *state = tevent_req_data(
1795 req, struct vfswrap_offload_write_state);
1796 struct vfs_aio_state aio_state;
1797 struct lock_struct write_lck;
1801 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
1802 TALLOC_FREE(subreq);
1804 DBG_ERR("read failed: %s\n", strerror(errno));
1805 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1808 if (nread != state->next_io_size) {
1809 DBG_ERR("Short read, only %zd of %zu\n",
1810 nread, state->next_io_size);
1811 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1815 state->src_off += nread;
1817 init_strict_lock_struct(state->dst_fsp,
1818 state->dst_fsp->op->global->open_persistent_id,
1820 state->next_io_size,
1824 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
1828 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1832 subreq = SMB_VFS_PWRITE_SEND(state,
1836 state->next_io_size,
1838 if (subreq == NULL) {
1839 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1842 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
1845 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
1847 struct tevent_req *req = tevent_req_callback_data(
1848 subreq, struct tevent_req);
1849 struct vfswrap_offload_write_state *state = tevent_req_data(
1850 req, struct vfswrap_offload_write_state);
1851 struct vfs_aio_state aio_state;
1855 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
1856 TALLOC_FREE(subreq);
1857 if (nwritten == -1) {
1858 DBG_ERR("write failed: %s\n", strerror(errno));
1859 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1862 if (nwritten != state->next_io_size) {
1863 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
1864 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1868 state->dst_off += nwritten;
1870 if (state->remaining < nwritten) {
1871 /* Paranoia check */
1872 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1875 state->remaining -= nwritten;
1876 if (state->remaining == 0) {
1877 tevent_req_done(req);
1881 status = vfswrap_offload_write_loop(req);
1882 if (!NT_STATUS_IS_OK(status)) {
1883 tevent_req_nterror(req, status);
1890 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
1891 struct tevent_req *req,
1894 struct vfswrap_offload_write_state *state = tevent_req_data(
1895 req, struct vfswrap_offload_write_state);
1898 if (tevent_req_is_nterror(req, &status)) {
1899 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
1901 tevent_req_received(req);
1905 *copied = state->to_copy;
1906 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
1907 tevent_req_received(req);
1909 return NT_STATUS_OK;
1912 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1913 TALLOC_CTX *mem_ctx,
1914 struct files_struct *fsp,
1915 struct smb_filename *smb_fname,
1916 uint16_t *_compression_fmt)
1918 return NT_STATUS_INVALID_DEVICE_REQUEST;
1921 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1922 TALLOC_CTX *mem_ctx,
1923 struct files_struct *fsp,
1924 uint16_t compression_fmt)
1926 return NT_STATUS_INVALID_DEVICE_REQUEST;
1929 /********************************************************************
1930 Given a stat buffer return the allocated size on disk, taking into
1931 account sparse files.
1932 ********************************************************************/
1933 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1934 struct files_struct *fsp,
1935 const SMB_STRUCT_STAT *sbuf)
1939 START_PROFILE(syscall_get_alloc_size);
1941 if(S_ISDIR(sbuf->st_ex_mode)) {
1946 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1947 /* The type of st_blocksize is blkcnt_t which *MUST* be
1948 signed (according to POSIX) and can be less than 64-bits.
1949 Ensure when we're converting to 64 bits wide we don't
1951 #if defined(SIZEOF_BLKCNT_T_8)
1952 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1953 #elif defined(SIZEOF_BLKCNT_T_4)
1955 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1956 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1959 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1963 * Some file systems do not allocate a block for very
1964 * small files. But for non-empty file should report a
1968 uint64_t filesize = get_file_size_stat(sbuf);
1970 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
1974 result = get_file_size_stat(sbuf);
1977 if (fsp && fsp->initial_allocation_size)
1978 result = MAX(result,fsp->initial_allocation_size);
1980 result = smb_roundup(handle->conn, result);
1983 END_PROFILE(syscall_get_alloc_size);
1987 static int vfswrap_unlink(vfs_handle_struct *handle,
1988 const struct smb_filename *smb_fname)
1992 START_PROFILE(syscall_unlink);
1994 if (smb_fname->stream_name) {
1998 result = unlink(smb_fname->base_name);
2001 END_PROFILE(syscall_unlink);
2005 static int vfswrap_chmod(vfs_handle_struct *handle,
2006 const struct smb_filename *smb_fname,
2011 START_PROFILE(syscall_chmod);
2014 * We need to do this due to the fact that the default POSIX ACL
2015 * chmod modifies the ACL *mask* for the group owner, not the
2016 * group owner bits directly. JRA.
2021 int saved_errno = errno; /* We might get ENOSYS */
2022 result = SMB_VFS_CHMOD_ACL(handle->conn,
2026 END_PROFILE(syscall_chmod);
2029 /* Error - return the old errno. */
2030 errno = saved_errno;
2033 result = chmod(smb_fname->base_name, mode);
2034 END_PROFILE(syscall_chmod);
2038 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2042 START_PROFILE(syscall_fchmod);
2045 * We need to do this due to the fact that the default POSIX ACL
2046 * chmod modifies the ACL *mask* for the group owner, not the
2047 * group owner bits directly. JRA.
2051 int saved_errno = errno; /* We might get ENOSYS */
2052 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
2053 END_PROFILE(syscall_fchmod);
2056 /* Error - return the old errno. */
2057 errno = saved_errno;
2060 #if defined(HAVE_FCHMOD)
2061 result = fchmod(fsp->fh->fd, mode);
2067 END_PROFILE(syscall_fchmod);
2071 static int vfswrap_chown(vfs_handle_struct *handle,
2072 const struct smb_filename *smb_fname,
2078 START_PROFILE(syscall_chown);
2079 result = chown(smb_fname->base_name, uid, gid);
2080 END_PROFILE(syscall_chown);
2084 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2089 START_PROFILE(syscall_fchown);
2090 result = fchown(fsp->fh->fd, uid, gid);
2091 END_PROFILE(syscall_fchown);
2099 static int vfswrap_lchown(vfs_handle_struct *handle,
2100 const struct smb_filename *smb_fname,
2106 START_PROFILE(syscall_lchown);
2107 result = lchown(smb_fname->base_name, uid, gid);
2108 END_PROFILE(syscall_lchown);
2112 static int vfswrap_chdir(vfs_handle_struct *handle,
2113 const struct smb_filename *smb_fname)
2117 START_PROFILE(syscall_chdir);
2118 result = chdir(smb_fname->base_name);
2119 END_PROFILE(syscall_chdir);
2123 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2127 struct smb_filename *smb_fname = NULL;
2129 START_PROFILE(syscall_getwd);
2130 result = sys_getwd();
2131 END_PROFILE(syscall_getwd);
2133 if (result == NULL) {
2136 smb_fname = synthetic_smb_fname(ctx,
2142 * sys_getwd() *always* returns malloced memory.
2143 * We must free here to avoid leaks:
2144 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2150 /*********************************************************************
2151 nsec timestamp resolution call. Convert down to whatever the underlying
2152 system will support.
2153 **********************************************************************/
2155 static int vfswrap_ntimes(vfs_handle_struct *handle,
2156 const struct smb_filename *smb_fname,
2157 struct smb_file_time *ft)
2161 START_PROFILE(syscall_ntimes);
2163 if (smb_fname->stream_name) {
2169 if (null_timespec(ft->atime)) {
2170 ft->atime= smb_fname->st.st_ex_atime;
2173 if (null_timespec(ft->mtime)) {
2174 ft->mtime = smb_fname->st.st_ex_mtime;
2177 if (!null_timespec(ft->create_time)) {
2178 set_create_timespec_ea(handle->conn,
2183 if ((timespec_compare(&ft->atime,
2184 &smb_fname->st.st_ex_atime) == 0) &&
2185 (timespec_compare(&ft->mtime,
2186 &smb_fname->st.st_ex_mtime) == 0)) {
2191 #if defined(HAVE_UTIMENSAT)
2193 struct timespec ts[2];
2196 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2198 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2200 if (!((result == -1) && (errno == ENOSYS))) {
2204 #if defined(HAVE_UTIMES)
2206 struct timeval tv[2];
2207 tv[0] = convert_timespec_to_timeval(ft->atime);
2208 tv[1] = convert_timespec_to_timeval(ft->mtime);
2209 result = utimes(smb_fname->base_name, tv);
2211 result = utimes(smb_fname->base_name, NULL);
2213 if (!((result == -1) && (errno == ENOSYS))) {
2217 #if defined(HAVE_UTIME)
2219 struct utimbuf times;
2220 times.actime = convert_timespec_to_time_t(ft->atime);
2221 times.modtime = convert_timespec_to_time_t(ft->mtime);
2222 result = utime(smb_fname->base_name, ×);
2224 result = utime(smb_fname->base_name, NULL);
2226 if (!((result == -1) && (errno == ENOSYS))) {
2234 END_PROFILE(syscall_ntimes);
2238 /*********************************************************************
2239 A version of ftruncate that will write the space on disk if strict
2241 **********************************************************************/
2243 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2245 off_t space_to_write;
2246 uint64_t space_avail;
2247 uint64_t bsize,dfree,dsize;
2250 SMB_STRUCT_STAT *pst;
2252 status = vfs_stat_fsp(fsp);
2253 if (!NT_STATUS_IS_OK(status)) {
2256 pst = &fsp->fsp_name->st;
2259 if (S_ISFIFO(pst->st_ex_mode))
2263 if (pst->st_ex_size == len)
2266 /* Shrink - just ftruncate. */
2267 if (pst->st_ex_size > len)
2268 return ftruncate(fsp->fh->fd, len);
2270 space_to_write = len - pst->st_ex_size;
2272 /* for allocation try fallocate first. This can fail on some
2273 platforms e.g. when the filesystem doesn't support it and no
2274 emulation is being done by the libc (like on AIX with JFS1). In that
2275 case we do our own emulation. fallocate implementations can
2276 return ENOTSUP or EINVAL in cases like that. */
2277 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2278 if (ret == -1 && errno == ENOSPC) {
2284 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2285 "error %d. Falling back to slow manual allocation\n", errno));
2287 /* available disk space is enough or not? */
2289 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2290 /* space_avail is 1k blocks */
2291 if (space_avail == (uint64_t)-1 ||
2292 ((uint64_t)space_to_write/1024 > space_avail) ) {
2297 /* Write out the real space on disk. */
2298 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2306 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2309 SMB_STRUCT_STAT *pst;
2313 START_PROFILE(syscall_ftruncate);
2315 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2316 result = strict_allocate_ftruncate(handle, fsp, len);
2317 END_PROFILE(syscall_ftruncate);
2321 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2322 ftruncate if the system supports it. Then I discovered that
2323 you can have some filesystems that support ftruncate
2324 expansion and some that don't! On Linux fat can't do
2325 ftruncate extend but ext2 can. */
2327 result = ftruncate(fsp->fh->fd, len);
2329 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2330 extend a file with ftruncate. Provide alternate implementation
2333 /* Do an fstat to see if the file is longer than the requested
2334 size in which case the ftruncate above should have
2335 succeeded or shorter, in which case seek to len - 1 and
2336 write 1 byte of zero */
2337 status = vfs_stat_fsp(fsp);
2338 if (!NT_STATUS_IS_OK(status)) {
2342 /* We need to update the files_struct after successful ftruncate */
2347 pst = &fsp->fsp_name->st;
2350 if (S_ISFIFO(pst->st_ex_mode)) {
2356 if (pst->st_ex_size == len) {
2361 if (pst->st_ex_size > len) {
2362 /* the ftruncate should have worked */
2366 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2374 END_PROFILE(syscall_ftruncate);
2378 static int vfswrap_fallocate(vfs_handle_struct *handle,
2386 START_PROFILE(syscall_fallocate);
2388 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2390 * posix_fallocate returns 0 on success, errno on error
2391 * and doesn't set errno. Make it behave like fallocate()
2392 * which returns -1, and sets errno on failure.
2399 /* sys_fallocate handles filtering of unsupported mode flags */
2400 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2402 END_PROFILE(syscall_fallocate);
2406 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2410 START_PROFILE(syscall_fcntl_lock);
2412 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2414 "force process locks",
2416 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2419 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2420 END_PROFILE(syscall_fcntl_lock);
2424 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2425 uint32_t share_mode, uint32_t access_mask)
2427 START_PROFILE(syscall_kernel_flock);
2428 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2429 END_PROFILE(syscall_kernel_flock);
2433 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2438 START_PROFILE(syscall_fcntl_getlock);
2440 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2442 "force process locks",
2444 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2447 result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2448 END_PROFILE(syscall_fcntl_getlock);
2452 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2457 START_PROFILE(syscall_linux_setlease);
2459 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2460 result = linux_setlease(fsp->fh->fd, leasetype);
2464 END_PROFILE(syscall_linux_setlease);
2468 static int vfswrap_symlink(vfs_handle_struct *handle,
2469 const char *link_target,
2470 const struct smb_filename *new_smb_fname)
2474 START_PROFILE(syscall_symlink);
2475 result = symlink(link_target, new_smb_fname->base_name);
2476 END_PROFILE(syscall_symlink);
2480 static int vfswrap_readlink(vfs_handle_struct *handle,
2481 const struct smb_filename *smb_fname,
2487 START_PROFILE(syscall_readlink);
2488 result = readlink(smb_fname->base_name, buf, bufsiz);
2489 END_PROFILE(syscall_readlink);
2493 static int vfswrap_link(vfs_handle_struct *handle,
2494 const struct smb_filename *old_smb_fname,
2495 const struct smb_filename *new_smb_fname)
2499 START_PROFILE(syscall_link);
2500 result = link(old_smb_fname->base_name, new_smb_fname->base_name);
2501 END_PROFILE(syscall_link);
2505 static int vfswrap_mknod(vfs_handle_struct *handle,
2506 const struct smb_filename *smb_fname,
2512 START_PROFILE(syscall_mknod);
2513 result = sys_mknod(smb_fname->base_name, mode, dev);
2514 END_PROFILE(syscall_mknod);
2518 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2520 const struct smb_filename *smb_fname)
2523 struct smb_filename *result_fname = NULL;
2525 START_PROFILE(syscall_realpath);
2526 result = sys_realpath(smb_fname->base_name);
2527 END_PROFILE(syscall_realpath);
2529 result_fname = synthetic_smb_fname(ctx, result, NULL, NULL, 0);
2532 return result_fname;
2535 static int vfswrap_chflags(vfs_handle_struct *handle,
2536 const struct smb_filename *smb_fname,
2540 return chflags(smb_fname->base_name, flags);
2547 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2548 const SMB_STRUCT_STAT *sbuf)
2552 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2556 key.devid = sbuf->st_ex_dev;
2557 key.inode = sbuf->st_ex_ino;
2558 /* key.extid is unused by default. */
2563 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2564 struct files_struct *fsp,
2565 const struct smb_filename *smb_fname,
2566 TALLOC_CTX *mem_ctx,
2567 unsigned int *pnum_streams,
2568 struct stream_struct **pstreams)
2570 SMB_STRUCT_STAT sbuf;
2571 struct stream_struct *tmp_streams = NULL;
2574 if ((fsp != NULL) && (fsp->is_directory)) {
2576 * No default streams on directories
2581 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2582 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2585 struct smb_filename smb_fname_cp;
2587 ZERO_STRUCT(smb_fname_cp);
2588 smb_fname_cp.base_name = discard_const_p(char,
2589 smb_fname->base_name);
2590 smb_fname_cp.flags = smb_fname->flags;
2592 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
2593 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2595 ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2597 sbuf = smb_fname_cp.st;
2601 return map_nt_error_from_unix(errno);
2604 if (S_ISDIR(sbuf.st_ex_mode)) {
2608 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2609 (*pnum_streams) + 1);
2610 if (tmp_streams == NULL) {
2611 return NT_STATUS_NO_MEMORY;
2613 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2614 if (tmp_streams[*pnum_streams].name == NULL) {
2615 return NT_STATUS_NO_MEMORY;
2617 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2618 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2621 *pstreams = tmp_streams;
2623 return NT_STATUS_OK;
2626 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2629 TALLOC_CTX *mem_ctx,
2633 * Don't fall back to get_real_filename so callers can differentiate
2634 * between a full directory scan and an actual case-insensitive stat.
2640 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2641 const struct smb_filename *smb_fname)
2643 return handle->conn->connectpath;
2646 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2647 struct byte_range_lock *br_lck,
2648 struct lock_struct *plock,
2651 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2653 /* Note: blr is not used in the default implementation. */
2654 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2657 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2658 struct messaging_context *msg_ctx,
2659 struct byte_range_lock *br_lck,
2660 const struct lock_struct *plock)
2662 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2664 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2667 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2668 struct byte_range_lock *br_lck,
2669 struct lock_struct *plock)
2671 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2673 /* Note: blr is not used in the default implementation. */
2674 return brl_lock_cancel_default(br_lck, plock);
2677 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
2679 struct lock_struct *plock)
2681 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2682 plock->lock_type == WRITE_LOCK);
2684 return strict_lock_check_default(fsp, plock);
2687 /* NT ACL operations. */
2689 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2691 uint32_t security_info,
2692 TALLOC_CTX *mem_ctx,
2693 struct security_descriptor **ppdesc)
2697 START_PROFILE(fget_nt_acl);
2698 result = posix_fget_nt_acl(fsp, security_info,
2700 END_PROFILE(fget_nt_acl);
2704 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2705 const struct smb_filename *smb_fname,
2706 uint32_t security_info,
2707 TALLOC_CTX *mem_ctx,
2708 struct security_descriptor **ppdesc)
2712 START_PROFILE(get_nt_acl);
2713 result = posix_get_nt_acl(handle->conn,
2718 END_PROFILE(get_nt_acl);
2722 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2726 START_PROFILE(fset_nt_acl);
2727 result = set_nt_acl(fsp, security_info_sent, psd);
2728 END_PROFILE(fset_nt_acl);
2732 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2733 struct smb_filename *file,
2734 struct security_acl *sacl,
2735 uint32_t access_requested,
2736 uint32_t access_denied)
2738 return NT_STATUS_OK; /* Nothing to do here ... */
2741 static int vfswrap_chmod_acl(vfs_handle_struct *handle,
2742 const struct smb_filename *smb_fname,
2751 START_PROFILE(chmod_acl);
2752 result = chmod_acl(handle->conn, smb_fname, mode);
2753 END_PROFILE(chmod_acl);
2758 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2766 START_PROFILE(fchmod_acl);
2767 result = fchmod_acl(fsp, mode);
2768 END_PROFILE(fchmod_acl);
2773 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2774 const struct smb_filename *smb_fname,
2775 SMB_ACL_TYPE_T type,
2776 TALLOC_CTX *mem_ctx)
2778 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
2781 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2783 TALLOC_CTX *mem_ctx)
2785 return sys_acl_get_fd(handle, fsp, mem_ctx);
2788 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
2789 const struct smb_filename *smb_fname,
2790 SMB_ACL_TYPE_T acltype,
2793 return sys_acl_set_file(handle, smb_fname, acltype, theacl);
2796 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2798 return sys_acl_set_fd(handle, fsp, theacl);
2801 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
2802 const struct smb_filename *smb_fname)
2804 return sys_acl_delete_def_file(handle, smb_fname);
2807 /****************************************************************
2808 Extended attribute operations.
2809 *****************************************************************/
2811 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
2812 const struct smb_filename *smb_fname,
2817 return getxattr(smb_fname->base_name, name, value, size);
2820 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2822 return fgetxattr(fsp->fh->fd, name, value, size);
2825 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
2826 const struct smb_filename *smb_fname,
2830 return listxattr(smb_fname->base_name, list, size);
2833 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2835 return flistxattr(fsp->fh->fd, list, size);
2838 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
2839 const struct smb_filename *smb_fname,
2842 return removexattr(smb_fname->base_name, name);
2845 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2847 return fremovexattr(fsp->fh->fd, name);
2850 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
2851 const struct smb_filename *smb_fname,
2857 return setxattr(smb_fname->base_name, name, value, size, flags);
2860 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2862 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2865 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2870 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2871 const struct smb_filename *fname,
2872 SMB_STRUCT_STAT *sbuf)
2876 bool offline = false;
2878 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2882 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2883 #if defined(ENOTSUP)
2889 status = get_full_smb_filename(talloc_tos(), fname, &path);
2890 if (!NT_STATUS_IS_OK(status)) {
2891 errno = map_errno_from_nt_status(status);
2895 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2902 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2903 struct files_struct *fsp,
2904 TALLOC_CTX *mem_ctx,
2907 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2910 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2911 struct files_struct *fsp,
2912 const DATA_BLOB old_cookie,
2913 TALLOC_CTX *mem_ctx,
2914 DATA_BLOB *new_cookie)
2916 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2920 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2921 struct smb_request *smb1req,
2922 struct smbXsrv_open *op,
2923 const DATA_BLOB old_cookie,
2924 TALLOC_CTX *mem_ctx,
2925 struct files_struct **fsp,
2926 DATA_BLOB *new_cookie)
2928 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2929 old_cookie, mem_ctx,
2933 static struct vfs_fn_pointers vfs_default_fns = {
2934 /* Disk operations */
2936 .connect_fn = vfswrap_connect,
2937 .disconnect_fn = vfswrap_disconnect,
2938 .disk_free_fn = vfswrap_disk_free,
2939 .get_quota_fn = vfswrap_get_quota,
2940 .set_quota_fn = vfswrap_set_quota,
2941 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2942 .statvfs_fn = vfswrap_statvfs,
2943 .fs_capabilities_fn = vfswrap_fs_capabilities,
2944 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2945 .snap_check_path_fn = vfswrap_snap_check_path,
2946 .snap_create_fn = vfswrap_snap_create,
2947 .snap_delete_fn = vfswrap_snap_delete,
2949 /* Directory operations */
2951 .opendir_fn = vfswrap_opendir,
2952 .fdopendir_fn = vfswrap_fdopendir,
2953 .readdir_fn = vfswrap_readdir,
2954 .readdir_attr_fn = vfswrap_readdir_attr,
2955 .seekdir_fn = vfswrap_seekdir,
2956 .telldir_fn = vfswrap_telldir,
2957 .rewind_dir_fn = vfswrap_rewinddir,
2958 .mkdir_fn = vfswrap_mkdir,
2959 .rmdir_fn = vfswrap_rmdir,
2960 .closedir_fn = vfswrap_closedir,
2962 /* File operations */
2964 .open_fn = vfswrap_open,
2965 .create_file_fn = vfswrap_create_file,
2966 .close_fn = vfswrap_close,
2967 .pread_fn = vfswrap_pread,
2968 .pread_send_fn = vfswrap_pread_send,
2969 .pread_recv_fn = vfswrap_pread_recv,
2970 .write_fn = vfswrap_write,
2971 .pwrite_fn = vfswrap_pwrite,
2972 .pwrite_send_fn = vfswrap_pwrite_send,
2973 .pwrite_recv_fn = vfswrap_pwrite_recv,
2974 .lseek_fn = vfswrap_lseek,
2975 .sendfile_fn = vfswrap_sendfile,
2976 .recvfile_fn = vfswrap_recvfile,
2977 .rename_fn = vfswrap_rename,
2978 .fsync_send_fn = vfswrap_fsync_send,
2979 .fsync_recv_fn = vfswrap_fsync_recv,
2980 .stat_fn = vfswrap_stat,
2981 .fstat_fn = vfswrap_fstat,
2982 .lstat_fn = vfswrap_lstat,
2983 .get_alloc_size_fn = vfswrap_get_alloc_size,
2984 .unlink_fn = vfswrap_unlink,
2985 .chmod_fn = vfswrap_chmod,
2986 .fchmod_fn = vfswrap_fchmod,
2987 .chown_fn = vfswrap_chown,
2988 .fchown_fn = vfswrap_fchown,
2989 .lchown_fn = vfswrap_lchown,
2990 .chdir_fn = vfswrap_chdir,
2991 .getwd_fn = vfswrap_getwd,
2992 .ntimes_fn = vfswrap_ntimes,
2993 .ftruncate_fn = vfswrap_ftruncate,
2994 .fallocate_fn = vfswrap_fallocate,
2995 .lock_fn = vfswrap_lock,
2996 .kernel_flock_fn = vfswrap_kernel_flock,
2997 .linux_setlease_fn = vfswrap_linux_setlease,
2998 .getlock_fn = vfswrap_getlock,
2999 .symlink_fn = vfswrap_symlink,
3000 .readlink_fn = vfswrap_readlink,
3001 .link_fn = vfswrap_link,
3002 .mknod_fn = vfswrap_mknod,
3003 .realpath_fn = vfswrap_realpath,
3004 .chflags_fn = vfswrap_chflags,
3005 .file_id_create_fn = vfswrap_file_id_create,
3006 .streaminfo_fn = vfswrap_streaminfo,
3007 .get_real_filename_fn = vfswrap_get_real_filename,
3008 .connectpath_fn = vfswrap_connectpath,
3009 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
3010 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3011 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
3012 .strict_lock_check_fn = vfswrap_strict_lock_check,
3013 .translate_name_fn = vfswrap_translate_name,
3014 .fsctl_fn = vfswrap_fsctl,
3015 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
3016 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
3017 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
3018 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
3019 .offload_read_send_fn = vfswrap_offload_read_send,
3020 .offload_read_recv_fn = vfswrap_offload_read_recv,
3021 .offload_write_send_fn = vfswrap_offload_write_send,
3022 .offload_write_recv_fn = vfswrap_offload_write_recv,
3023 .get_compression_fn = vfswrap_get_compression,
3024 .set_compression_fn = vfswrap_set_compression,
3026 /* NT ACL operations. */
3028 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
3029 .get_nt_acl_fn = vfswrap_get_nt_acl,
3030 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
3031 .audit_file_fn = vfswrap_audit_file,
3033 /* POSIX ACL operations. */
3035 .chmod_acl_fn = vfswrap_chmod_acl,
3036 .fchmod_acl_fn = vfswrap_fchmod_acl,
3038 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
3039 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3040 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
3041 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3042 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
3043 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3044 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
3046 /* EA operations. */
3047 .getxattr_fn = vfswrap_getxattr,
3048 .fgetxattr_fn = vfswrap_fgetxattr,
3049 .listxattr_fn = vfswrap_listxattr,
3050 .flistxattr_fn = vfswrap_flistxattr,
3051 .removexattr_fn = vfswrap_removexattr,
3052 .fremovexattr_fn = vfswrap_fremovexattr,
3053 .setxattr_fn = vfswrap_setxattr,
3054 .fsetxattr_fn = vfswrap_fsetxattr,
3056 /* aio operations */
3057 .aio_force_fn = vfswrap_aio_force,
3059 /* durable handle operations */
3060 .durable_cookie_fn = vfswrap_durable_cookie,
3061 .durable_disconnect_fn = vfswrap_durable_disconnect,
3062 .durable_reconnect_fn = vfswrap_durable_reconnect,
3066 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3068 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3069 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);