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 ZERO_STRUCT(statbuf);
133 ret = sys_statvfs(conn->connectpath, &statbuf);
135 caps = statbuf.FsCapabilities;
138 *p_ts_res = TIMESTAMP_SET_SECONDS;
140 /* Work out what timestamp resolution we can
141 * use when setting a timestamp. */
143 smb_fname_cpath = synthetic_smb_fname(talloc_tos(), conn->connectpath,
145 if (smb_fname_cpath == NULL) {
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 static void vfswrap_init_search_op(vfs_handle_struct *handle,
560 /* Default behavior is a NOOP */
563 /* File operations */
565 static int vfswrap_open(vfs_handle_struct *handle,
566 struct smb_filename *smb_fname,
567 files_struct *fsp, int flags, mode_t mode)
571 START_PROFILE(syscall_open);
573 if (smb_fname->stream_name) {
578 result = open(smb_fname->base_name, flags, mode);
580 END_PROFILE(syscall_open);
584 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
585 struct smb_request *req,
586 uint16_t root_dir_fid,
587 struct smb_filename *smb_fname,
588 uint32_t access_mask,
589 uint32_t share_access,
590 uint32_t create_disposition,
591 uint32_t create_options,
592 uint32_t file_attributes,
593 uint32_t oplock_request,
594 struct smb2_lease *lease,
595 uint64_t allocation_size,
596 uint32_t private_flags,
597 struct security_descriptor *sd,
598 struct ea_list *ea_list,
599 files_struct **result,
601 const struct smb2_create_blobs *in_context_blobs,
602 struct smb2_create_blobs *out_context_blobs)
604 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
605 access_mask, share_access,
606 create_disposition, create_options,
607 file_attributes, oplock_request, lease,
608 allocation_size, private_flags,
610 pinfo, in_context_blobs, out_context_blobs);
613 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
617 START_PROFILE(syscall_close);
618 result = fd_close_posix(fsp);
619 END_PROFILE(syscall_close);
623 static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
627 START_PROFILE_BYTES(syscall_read, n);
628 result = sys_read(fsp->fh->fd, data, n);
629 END_PROFILE_BYTES(syscall_read);
633 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
634 size_t n, off_t offset)
638 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
639 START_PROFILE_BYTES(syscall_pread, n);
640 result = sys_pread(fsp->fh->fd, data, n, offset);
641 END_PROFILE_BYTES(syscall_pread);
643 if (result == -1 && errno == ESPIPE) {
644 /* Maintain the fiction that pipes can be seeked (sought?) on. */
645 result = SMB_VFS_READ(fsp, data, n);
649 #else /* HAVE_PREAD */
653 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
654 if (curr == -1 && errno == ESPIPE) {
655 /* Maintain the fiction that pipes can be seeked (sought?) on. */
656 result = SMB_VFS_READ(fsp, data, n);
661 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
666 result = SMB_VFS_READ(fsp, data, n);
669 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
672 #endif /* HAVE_PREAD */
677 static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
681 START_PROFILE_BYTES(syscall_write, n);
682 result = sys_write(fsp->fh->fd, data, n);
683 END_PROFILE_BYTES(syscall_write);
687 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
688 size_t n, off_t offset)
692 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
693 START_PROFILE_BYTES(syscall_pwrite, n);
694 result = sys_pwrite(fsp->fh->fd, data, n, offset);
695 END_PROFILE_BYTES(syscall_pwrite);
697 if (result == -1 && errno == ESPIPE) {
698 /* Maintain the fiction that pipes can be sought on. */
699 result = SMB_VFS_WRITE(fsp, data, n);
702 #else /* HAVE_PWRITE */
706 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
711 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
715 result = SMB_VFS_WRITE(fsp, data, n);
718 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
721 #endif /* HAVE_PWRITE */
726 static int vfswrap_init_pool(struct smbd_server_connection *conn)
730 if (conn->pool != NULL) {
734 ret = pthreadpool_tevent_init(conn, lp_aio_max_threads(),
739 struct vfswrap_pread_state {
747 struct vfs_aio_state vfs_aio_state;
748 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
751 static void vfs_pread_do(void *private_data);
752 static void vfs_pread_done(struct tevent_req *subreq);
754 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
756 struct tevent_context *ev,
757 struct files_struct *fsp,
759 size_t n, off_t offset)
761 struct tevent_req *req, *subreq;
762 struct vfswrap_pread_state *state;
765 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
770 ret = vfswrap_init_pool(handle->conn->sconn);
771 if (tevent_req_error(req, ret)) {
772 return tevent_req_post(req, ev);
776 state->fd = fsp->fh->fd;
779 state->offset = offset;
781 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
782 state->profile_bytes, n);
783 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
785 subreq = pthreadpool_tevent_job_send(
786 state, ev, handle->conn->sconn->pool,
787 vfs_pread_do, state);
788 if (tevent_req_nomem(subreq, req)) {
789 return tevent_req_post(req, ev);
791 tevent_req_set_callback(subreq, vfs_pread_done, req);
796 static void vfs_pread_do(void *private_data)
798 struct vfswrap_pread_state *state = talloc_get_type_abort(
799 private_data, struct vfswrap_pread_state);
800 struct timespec start_time;
801 struct timespec end_time;
803 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
805 PROFILE_TIMESTAMP(&start_time);
808 state->ret = pread(state->fd, state->buf, state->count,
810 } while ((state->ret == -1) && (errno == EINTR));
814 PROFILE_TIMESTAMP(&end_time);
816 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
818 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
821 static void vfs_pread_done(struct tevent_req *subreq)
823 struct tevent_req *req = tevent_req_callback_data(
824 subreq, struct tevent_req);
826 struct vfswrap_pread_state *state = tevent_req_data(
827 req, struct vfswrap_pread_state);
831 ret = pthreadpool_tevent_job_recv(subreq);
833 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
834 if (tevent_req_error(req, ret)) {
838 tevent_req_done(req);
841 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
842 struct vfs_aio_state *vfs_aio_state)
844 struct vfswrap_pread_state *state = tevent_req_data(
845 req, struct vfswrap_pread_state);
847 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
851 *vfs_aio_state = state->vfs_aio_state;
855 struct vfswrap_pwrite_state {
863 struct vfs_aio_state vfs_aio_state;
864 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
867 static void vfs_pwrite_do(void *private_data);
868 static void vfs_pwrite_done(struct tevent_req *subreq);
870 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
872 struct tevent_context *ev,
873 struct files_struct *fsp,
875 size_t n, off_t offset)
877 struct tevent_req *req, *subreq;
878 struct vfswrap_pwrite_state *state;
881 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
886 ret = vfswrap_init_pool(handle->conn->sconn);
887 if (tevent_req_error(req, ret)) {
888 return tevent_req_post(req, ev);
892 state->fd = fsp->fh->fd;
895 state->offset = offset;
897 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
898 state->profile_bytes, n);
899 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
901 subreq = pthreadpool_tevent_job_send(
902 state, ev, handle->conn->sconn->pool,
903 vfs_pwrite_do, state);
904 if (tevent_req_nomem(subreq, req)) {
905 return tevent_req_post(req, ev);
907 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
912 static void vfs_pwrite_do(void *private_data)
914 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
915 private_data, struct vfswrap_pwrite_state);
916 struct timespec start_time;
917 struct timespec end_time;
919 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
921 PROFILE_TIMESTAMP(&start_time);
924 state->ret = pwrite(state->fd, state->buf, state->count,
926 } while ((state->ret == -1) && (errno == EINTR));
930 PROFILE_TIMESTAMP(&end_time);
932 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
934 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
937 static void vfs_pwrite_done(struct tevent_req *subreq)
939 struct tevent_req *req = tevent_req_callback_data(
940 subreq, struct tevent_req);
942 struct vfswrap_pwrite_state *state = tevent_req_data(
943 req, struct vfswrap_pwrite_state);
947 ret = pthreadpool_tevent_job_recv(subreq);
949 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
950 if (tevent_req_error(req, ret)) {
954 tevent_req_done(req);
957 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
958 struct vfs_aio_state *vfs_aio_state)
960 struct vfswrap_pwrite_state *state = tevent_req_data(
961 req, struct vfswrap_pwrite_state);
963 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
967 *vfs_aio_state = state->vfs_aio_state;
971 struct vfswrap_fsync_state {
976 struct vfs_aio_state vfs_aio_state;
977 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
980 static void vfs_fsync_do(void *private_data);
981 static void vfs_fsync_done(struct tevent_req *subreq);
983 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
985 struct tevent_context *ev,
986 struct files_struct *fsp)
988 struct tevent_req *req, *subreq;
989 struct vfswrap_fsync_state *state;
992 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
997 ret = vfswrap_init_pool(handle->conn->sconn);
998 if (tevent_req_error(req, ret)) {
999 return tevent_req_post(req, ev);
1003 state->fd = fsp->fh->fd;
1005 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
1006 state->profile_basic);
1008 subreq = pthreadpool_tevent_job_send(
1009 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
1010 if (tevent_req_nomem(subreq, req)) {
1011 return tevent_req_post(req, ev);
1013 tevent_req_set_callback(subreq, vfs_fsync_done, req);
1018 static void vfs_fsync_do(void *private_data)
1020 struct vfswrap_fsync_state *state = talloc_get_type_abort(
1021 private_data, struct vfswrap_fsync_state);
1022 struct timespec start_time;
1023 struct timespec end_time;
1025 PROFILE_TIMESTAMP(&start_time);
1028 state->ret = fsync(state->fd);
1029 } while ((state->ret == -1) && (errno == EINTR));
1033 PROFILE_TIMESTAMP(&end_time);
1035 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1038 static void vfs_fsync_done(struct tevent_req *subreq)
1040 struct tevent_req *req = tevent_req_callback_data(
1041 subreq, struct tevent_req);
1043 struct vfswrap_fsync_state *state = tevent_req_data(
1044 req, struct vfswrap_fsync_state);
1048 ret = pthreadpool_tevent_job_recv(subreq);
1049 TALLOC_FREE(subreq);
1050 SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
1051 if (tevent_req_error(req, ret)) {
1055 tevent_req_done(req);
1058 static int vfswrap_fsync_recv(struct tevent_req *req,
1059 struct vfs_aio_state *vfs_aio_state)
1061 struct vfswrap_fsync_state *state = tevent_req_data(
1062 req, struct vfswrap_fsync_state);
1064 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1068 *vfs_aio_state = state->vfs_aio_state;
1072 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1076 START_PROFILE(syscall_lseek);
1078 /* Cope with 'stat' file opens. */
1079 if (fsp->fh->fd != -1)
1080 result = lseek(fsp->fh->fd, offset, whence);
1083 * We want to maintain the fiction that we can seek
1084 * on a fifo for file system purposes. This allows
1085 * people to set up UNIX fifo's that feed data to Windows
1086 * applications. JRA.
1089 if((result == -1) && (errno == ESPIPE)) {
1094 END_PROFILE(syscall_lseek);
1098 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1099 off_t offset, size_t n)
1103 START_PROFILE_BYTES(syscall_sendfile, n);
1104 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
1105 END_PROFILE_BYTES(syscall_sendfile);
1109 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1111 files_struct *tofsp,
1117 START_PROFILE_BYTES(syscall_recvfile, n);
1118 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
1119 END_PROFILE_BYTES(syscall_recvfile);
1123 static int vfswrap_rename(vfs_handle_struct *handle,
1124 const struct smb_filename *smb_fname_src,
1125 const struct smb_filename *smb_fname_dst)
1129 START_PROFILE(syscall_rename);
1131 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
1136 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
1139 END_PROFILE(syscall_rename);
1143 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
1148 START_PROFILE(syscall_fsync);
1149 result = fsync(fsp->fh->fd);
1150 END_PROFILE(syscall_fsync);
1157 static int vfswrap_stat(vfs_handle_struct *handle,
1158 struct smb_filename *smb_fname)
1162 START_PROFILE(syscall_stat);
1164 if (smb_fname->stream_name) {
1169 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1170 lp_fake_directory_create_times(SNUM(handle->conn)));
1172 END_PROFILE(syscall_stat);
1176 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1180 START_PROFILE(syscall_fstat);
1181 result = sys_fstat(fsp->fh->fd,
1182 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1183 END_PROFILE(syscall_fstat);
1187 static int vfswrap_lstat(vfs_handle_struct *handle,
1188 struct smb_filename *smb_fname)
1192 START_PROFILE(syscall_lstat);
1194 if (smb_fname->stream_name) {
1199 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1200 lp_fake_directory_create_times(SNUM(handle->conn)));
1202 END_PROFILE(syscall_lstat);
1206 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1208 enum vfs_translate_direction direction,
1209 TALLOC_CTX *mem_ctx,
1212 return NT_STATUS_NONE_MAPPED;
1216 * Implement the default fsctl operation.
1218 static bool vfswrap_logged_ioctl_message = false;
1220 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1221 struct files_struct *fsp,
1224 uint16_t req_flags, /* Needed for UNICODE ... */
1225 const uint8_t *_in_data,
1227 uint8_t **_out_data,
1228 uint32_t max_out_len,
1231 const char *in_data = (const char *)_in_data;
1232 char **out_data = (char **)_out_data;
1236 case FSCTL_SET_SPARSE:
1238 bool set_sparse = true;
1240 if (in_len >= 1 && in_data[0] == 0) {
1244 status = file_set_sparse(handle->conn, fsp, set_sparse);
1246 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1247 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1248 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1249 nt_errstr(status)));
1254 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1256 unsigned char objid[16];
1257 char *return_data = NULL;
1259 /* This should return the object-id on this file.
1260 * I think I'll make this be the inode+dev. JRA.
1263 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1264 fsp_fnum_dbg(fsp)));
1266 *out_len = MIN(max_out_len, 64);
1268 /* Hmmm, will this cause problems if less data asked for? */
1269 return_data = talloc_array(ctx, char, 64);
1270 if (return_data == NULL) {
1271 return NT_STATUS_NO_MEMORY;
1274 /* For backwards compatibility only store the dev/inode. */
1275 push_file_id_16(return_data, &fsp->file_id);
1276 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1277 push_file_id_16(return_data+32, &fsp->file_id);
1278 memset(return_data+48, 0, 16);
1279 *out_data = return_data;
1280 return NT_STATUS_OK;
1283 case FSCTL_GET_REPARSE_POINT:
1285 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1286 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1287 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1288 return NT_STATUS_NOT_A_REPARSE_POINT;
1291 case FSCTL_SET_REPARSE_POINT:
1293 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1294 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1295 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1296 return NT_STATUS_NOT_A_REPARSE_POINT;
1299 case FSCTL_GET_SHADOW_COPY_DATA:
1302 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1303 * and return their volume names. If max_data_count is 16, then it is just
1304 * asking for the number of volumes and length of the combined names.
1306 * pdata is the data allocated by our caller, but that uses
1307 * total_data_count (which is 0 in our case) rather than max_data_count.
1308 * Allocate the correct amount and return the pointer to let
1309 * it be deallocated when we return.
1311 struct shadow_copy_data *shadow_data = NULL;
1312 bool labels = False;
1313 uint32_t labels_data_count = 0;
1315 char *cur_pdata = NULL;
1317 if (max_out_len < 16) {
1318 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1320 return NT_STATUS_INVALID_PARAMETER;
1323 if (max_out_len > 16) {
1327 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1328 if (shadow_data == NULL) {
1329 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1330 return NT_STATUS_NO_MEMORY;
1334 * Call the VFS routine to actually do the work.
1336 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1339 /* broken module didn't set errno on error */
1340 status = NT_STATUS_UNSUCCESSFUL;
1342 status = map_nt_error_from_unix(errno);
1343 if (NT_STATUS_EQUAL(status,
1344 NT_STATUS_NOT_SUPPORTED)) {
1348 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1349 "connectpath %s, failed - %s.\n",
1350 fsp->conn->connectpath,
1351 nt_errstr(status)));
1352 TALLOC_FREE(shadow_data);
1356 labels_data_count = (shadow_data->num_volumes * 2 *
1357 sizeof(SHADOW_COPY_LABEL)) + 2;
1362 *out_len = 12 + labels_data_count;
1365 if (max_out_len < *out_len) {
1366 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1367 max_out_len, *out_len));
1368 TALLOC_FREE(shadow_data);
1369 return NT_STATUS_BUFFER_TOO_SMALL;
1372 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1373 if (cur_pdata == NULL) {
1374 TALLOC_FREE(shadow_data);
1375 return NT_STATUS_NO_MEMORY;
1378 *out_data = cur_pdata;
1380 /* num_volumes 4 bytes */
1381 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1384 /* num_labels 4 bytes */
1385 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1388 /* needed_data_count 4 bytes */
1389 SIVAL(cur_pdata, 8, labels_data_count);
1393 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1394 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1395 if (labels && shadow_data->labels) {
1396 for (i=0; i<shadow_data->num_volumes; i++) {
1398 status = srvstr_push(cur_pdata, req_flags,
1399 cur_pdata, shadow_data->labels[i],
1400 2 * sizeof(SHADOW_COPY_LABEL),
1401 STR_UNICODE|STR_TERMINATE, &len);
1402 if (!NT_STATUS_IS_OK(status)) {
1403 TALLOC_FREE(*out_data);
1404 TALLOC_FREE(shadow_data);
1407 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1408 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1412 TALLOC_FREE(shadow_data);
1414 return NT_STATUS_OK;
1417 case FSCTL_FIND_FILES_BY_SID:
1419 /* pretend this succeeded -
1421 * we have to send back a list with all files owned by this SID
1423 * but I have to check that --metze
1429 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1430 fsp_fnum_dbg(fsp)));
1433 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1434 return NT_STATUS_INVALID_PARAMETER;
1437 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1439 /* unknown 4 bytes: this is not the length of the sid :-( */
1440 /*unknown = IVAL(pdata,0);*/
1442 if (!sid_parse(_in_data + 4, sid_len, &sid)) {
1443 return NT_STATUS_INVALID_PARAMETER;
1445 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1447 if (!sid_to_uid(&sid, &uid)) {
1448 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1449 sid_string_dbg(&sid),
1450 (unsigned long)sid_len));
1454 /* we can take a look at the find source :-)
1456 * find ./ -uid $uid -name '*' is what we need here
1459 * and send 4bytes len and then NULL terminated unicode strings
1462 * but I don't know how to deal with the paged results
1463 * (maybe we can hang the result anywhere in the fsp struct)
1465 * but I don't know how to deal with the paged results
1466 * (maybe we can hang the result anywhere in the fsp struct)
1468 * we don't send all files at once
1469 * and at the next we should *not* start from the beginning,
1470 * so we have to cache the result
1475 /* this works for now... */
1476 return NT_STATUS_OK;
1479 case FSCTL_QUERY_ALLOCATED_RANGES:
1481 /* FIXME: This is just a dummy reply, telling that all of the
1482 * file is allocated. MKS cp needs that.
1483 * Adding the real allocated ranges via FIEMAP on Linux
1484 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1485 * this FSCTL correct for sparse files.
1487 uint64_t offset, length;
1488 char *out_data_tmp = NULL;
1491 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1493 return NT_STATUS_INVALID_PARAMETER;
1496 if (max_out_len < 16) {
1497 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1499 return NT_STATUS_INVALID_PARAMETER;
1502 offset = BVAL(in_data,0);
1503 length = BVAL(in_data,8);
1505 if (offset + length < offset) {
1506 /* No 64-bit integer wrap. */
1507 return NT_STATUS_INVALID_PARAMETER;
1510 /* Shouldn't this be SMB_VFS_STAT ... ? */
1511 status = vfs_stat_fsp(fsp);
1512 if (!NT_STATUS_IS_OK(status)) {
1517 out_data_tmp = talloc_array(ctx, char, *out_len);
1518 if (out_data_tmp == NULL) {
1519 DEBUG(10, ("unable to allocate memory for response\n"));
1520 return NT_STATUS_NO_MEMORY;
1523 if (offset > fsp->fsp_name->st.st_ex_size ||
1524 fsp->fsp_name->st.st_ex_size == 0 ||
1526 memset(out_data_tmp, 0, *out_len);
1528 uint64_t end = offset + length;
1529 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1530 SBVAL(out_data_tmp, 0, 0);
1531 SBVAL(out_data_tmp, 8, end);
1534 *out_data = out_data_tmp;
1536 return NT_STATUS_OK;
1539 case FSCTL_IS_VOLUME_DIRTY:
1541 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1542 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1544 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1545 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1547 return NT_STATUS_INVALID_PARAMETER;
1552 * Only print once ... unfortunately there could be lots of
1553 * different FSCTLs that are called.
1555 if (!vfswrap_logged_ioctl_message) {
1556 vfswrap_logged_ioctl_message = true;
1557 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1558 __func__, function));
1562 return NT_STATUS_NOT_SUPPORTED;
1565 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
1566 const struct smb_filename *fname,
1567 SMB_STRUCT_STAT *sbuf);
1569 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1570 struct smb_filename *smb_fname,
1575 offline = vfswrap_is_offline(handle, smb_fname, &smb_fname->st);
1577 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1580 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1583 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1584 struct files_struct *fsp,
1589 offline = vfswrap_is_offline(handle, fsp->fsp_name, &fsp->fsp_name->st);
1591 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1594 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1597 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1598 const struct smb_filename *smb_fname,
1601 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1604 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1605 struct files_struct *fsp,
1608 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1611 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1613 struct vfswrap_offload_read_state {
1617 static struct tevent_req *vfswrap_offload_read_send(
1618 TALLOC_CTX *mem_ctx,
1619 struct tevent_context *ev,
1620 struct vfs_handle_struct *handle,
1621 struct files_struct *fsp,
1627 struct tevent_req *req = NULL;
1628 struct vfswrap_offload_read_state *state = NULL;
1631 req = tevent_req_create(mem_ctx, &state,
1632 struct vfswrap_offload_read_state);
1637 status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1638 &vfswrap_offload_ctx);
1639 if (tevent_req_nterror(req, status)) {
1640 return tevent_req_post(req, ev);
1643 if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1644 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1645 return tevent_req_post(req, ev);
1648 status = vfs_offload_token_create_blob(state, fsp, fsctl,
1650 if (tevent_req_nterror(req, status)) {
1651 return tevent_req_post(req, ev);
1654 status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1656 if (tevent_req_nterror(req, status)) {
1657 return tevent_req_post(req, ev);
1660 tevent_req_done(req);
1661 return tevent_req_post(req, ev);
1664 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
1665 struct vfs_handle_struct *handle,
1666 TALLOC_CTX *mem_ctx,
1669 struct vfswrap_offload_read_state *state = tevent_req_data(
1670 req, struct vfswrap_offload_read_state);
1673 if (tevent_req_is_nterror(req, &status)) {
1674 tevent_req_received(req);
1678 token->length = state->token.length;
1679 token->data = talloc_move(mem_ctx, &state->token.data);
1681 tevent_req_received(req);
1682 return NT_STATUS_OK;
1685 struct vfswrap_offload_write_state {
1686 struct tevent_context *ev;
1688 bool read_lck_locked;
1689 struct lock_struct read_lck;
1690 bool write_lck_locked;
1691 struct lock_struct write_lck;
1692 struct files_struct *src_fsp;
1694 struct files_struct *dst_fsp;
1698 size_t next_io_size;
1702 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
1704 static struct tevent_req *vfswrap_offload_write_send(
1705 struct vfs_handle_struct *handle,
1706 TALLOC_CTX *mem_ctx,
1707 struct tevent_context *ev,
1708 struct files_struct *src_fsp,
1710 struct files_struct *dest_fsp,
1715 struct tevent_req *req;
1716 struct vfswrap_offload_write_state *state = NULL;
1717 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
1720 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
1722 req = tevent_req_create(mem_ctx, &state,
1723 struct vfswrap_offload_write_state);
1728 if (flags & ~VFS_OFFLOAD_WRITE_FL_MASK_ALL) {
1729 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1730 return tevent_req_post(req, ev);
1733 if (flags & VFS_OFFLOAD_WRITE_FL_MUST_CLONE) {
1734 DEBUG(10, ("COW clones not supported by vfs_default\n"));
1735 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1736 return tevent_req_post(req, ev);
1739 *state = (struct vfswrap_offload_write_state) {
1743 .dst_fsp = dest_fsp,
1744 .dst_off = dest_off,
1746 .remaining = to_copy,
1749 state->buf = talloc_array(state, uint8_t, num);
1750 if (tevent_req_nomem(state->buf, req)) {
1751 return tevent_req_post(req, ev);
1754 status = vfs_stat_fsp(src_fsp);
1755 if (tevent_req_nterror(req, status)) {
1756 return tevent_req_post(req, ev);
1759 if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
1761 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1762 * If the SourceOffset or SourceOffset + Length extends beyond
1763 * the end of file, the server SHOULD<240> treat this as a
1764 * STATUS_END_OF_FILE error.
1766 * <240> Section 3.3.5.15.6: Windows servers will return
1767 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1769 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1770 return tevent_req_post(req, ev);
1773 if (src_fsp->op == NULL) {
1774 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1775 return tevent_req_post(req, ev);
1778 if (dest_fsp->op == NULL) {
1779 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1780 return tevent_req_post(req, ev);
1783 status = vfswrap_offload_write_loop(req);
1784 if (!NT_STATUS_IS_OK(status)) {
1785 tevent_req_nterror(req, status);
1786 return tevent_req_post(req, ev);
1792 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
1794 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
1796 struct vfswrap_offload_write_state *state = tevent_req_data(
1797 req, struct vfswrap_offload_write_state);
1798 struct tevent_req *subreq = NULL;
1801 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
1803 if (!(state->flags & VFS_OFFLOAD_WRITE_FL_IGNORE_LOCKS)) {
1804 init_strict_lock_struct(state->src_fsp,
1805 state->src_fsp->op->global->open_persistent_id,
1807 state->next_io_size,
1811 ok = SMB_VFS_STRICT_LOCK(state->src_fsp->conn,
1815 return NT_STATUS_FILE_LOCK_CONFLICT;
1819 subreq = SMB_VFS_PREAD_SEND(state,
1820 state->src_fsp->conn->sconn->ev_ctx,
1823 state->next_io_size,
1825 if (subreq == NULL) {
1826 return NT_STATUS_NO_MEMORY;
1828 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
1830 return NT_STATUS_OK;
1833 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
1835 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
1837 struct tevent_req *req = tevent_req_callback_data(
1838 subreq, struct tevent_req);
1839 struct vfswrap_offload_write_state *state = tevent_req_data(
1840 req, struct vfswrap_offload_write_state);
1841 struct vfs_aio_state aio_state;
1845 if (!(state->flags & VFS_OFFLOAD_WRITE_FL_IGNORE_LOCKS)) {
1846 SMB_VFS_STRICT_UNLOCK(state->src_fsp->conn,
1849 ZERO_STRUCT(state->read_lck);
1852 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
1853 TALLOC_FREE(subreq);
1855 DBG_ERR("read failed: %s\n", strerror(errno));
1856 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1859 if (nread != state->next_io_size) {
1860 DBG_ERR("Short read, only %zd of %zu\n",
1861 nread, state->next_io_size);
1862 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1866 state->src_off += nread;
1868 if (!(state->flags & VFS_OFFLOAD_WRITE_FL_IGNORE_LOCKS)) {
1869 init_strict_lock_struct(state->dst_fsp,
1870 state->dst_fsp->op->global->open_persistent_id,
1872 state->next_io_size,
1876 ok = SMB_VFS_STRICT_LOCK(state->dst_fsp->conn,
1880 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1885 subreq = SMB_VFS_PWRITE_SEND(state,
1889 state->next_io_size,
1891 if (subreq == NULL) {
1892 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1895 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
1898 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
1900 struct tevent_req *req = tevent_req_callback_data(
1901 subreq, struct tevent_req);
1902 struct vfswrap_offload_write_state *state = tevent_req_data(
1903 req, struct vfswrap_offload_write_state);
1904 struct vfs_aio_state aio_state;
1908 if (!(state->flags & VFS_OFFLOAD_WRITE_FL_IGNORE_LOCKS)) {
1909 SMB_VFS_STRICT_UNLOCK(state->dst_fsp->conn,
1912 ZERO_STRUCT(state->write_lck);
1915 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
1916 TALLOC_FREE(subreq);
1917 if (nwritten == -1) {
1918 DBG_ERR("write failed: %s\n", strerror(errno));
1919 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1922 if (nwritten != state->next_io_size) {
1923 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
1924 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1928 state->dst_off += nwritten;
1930 if (state->remaining < nwritten) {
1931 /* Paranoia check */
1932 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1935 state->remaining -= nwritten;
1936 if (state->remaining == 0) {
1937 tevent_req_done(req);
1941 status = vfswrap_offload_write_loop(req);
1942 if (!NT_STATUS_IS_OK(status)) {
1943 tevent_req_nterror(req, status);
1950 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
1951 struct tevent_req *req,
1954 struct vfswrap_offload_write_state *state = tevent_req_data(
1955 req, struct vfswrap_offload_write_state);
1958 if (tevent_req_is_nterror(req, &status)) {
1959 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
1961 tevent_req_received(req);
1965 *copied = state->to_copy;
1966 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
1967 tevent_req_received(req);
1969 return NT_STATUS_OK;
1972 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1973 TALLOC_CTX *mem_ctx,
1974 struct files_struct *fsp,
1975 struct smb_filename *smb_fname,
1976 uint16_t *_compression_fmt)
1978 return NT_STATUS_INVALID_DEVICE_REQUEST;
1981 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1982 TALLOC_CTX *mem_ctx,
1983 struct files_struct *fsp,
1984 uint16_t compression_fmt)
1986 return NT_STATUS_INVALID_DEVICE_REQUEST;
1989 /********************************************************************
1990 Given a stat buffer return the allocated size on disk, taking into
1991 account sparse files.
1992 ********************************************************************/
1993 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1994 struct files_struct *fsp,
1995 const SMB_STRUCT_STAT *sbuf)
1999 START_PROFILE(syscall_get_alloc_size);
2001 if(S_ISDIR(sbuf->st_ex_mode)) {
2006 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2007 /* The type of st_blocksize is blkcnt_t which *MUST* be
2008 signed (according to POSIX) and can be less than 64-bits.
2009 Ensure when we're converting to 64 bits wide we don't
2011 #if defined(SIZEOF_BLKCNT_T_8)
2012 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2013 #elif defined(SIZEOF_BLKCNT_T_4)
2015 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2016 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2019 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2023 * Some file systems do not allocate a block for very
2024 * small files. But for non-empty file should report a
2028 uint64_t filesize = get_file_size_stat(sbuf);
2030 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2034 result = get_file_size_stat(sbuf);
2037 if (fsp && fsp->initial_allocation_size)
2038 result = MAX(result,fsp->initial_allocation_size);
2040 result = smb_roundup(handle->conn, result);
2043 END_PROFILE(syscall_get_alloc_size);
2047 static int vfswrap_unlink(vfs_handle_struct *handle,
2048 const struct smb_filename *smb_fname)
2052 START_PROFILE(syscall_unlink);
2054 if (smb_fname->stream_name) {
2058 result = unlink(smb_fname->base_name);
2061 END_PROFILE(syscall_unlink);
2065 static int vfswrap_chmod(vfs_handle_struct *handle,
2066 const struct smb_filename *smb_fname,
2071 START_PROFILE(syscall_chmod);
2074 * We need to do this due to the fact that the default POSIX ACL
2075 * chmod modifies the ACL *mask* for the group owner, not the
2076 * group owner bits directly. JRA.
2081 int saved_errno = errno; /* We might get ENOSYS */
2082 result = SMB_VFS_CHMOD_ACL(handle->conn,
2086 END_PROFILE(syscall_chmod);
2089 /* Error - return the old errno. */
2090 errno = saved_errno;
2093 result = chmod(smb_fname->base_name, mode);
2094 END_PROFILE(syscall_chmod);
2098 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2102 START_PROFILE(syscall_fchmod);
2105 * We need to do this due to the fact that the default POSIX ACL
2106 * chmod modifies the ACL *mask* for the group owner, not the
2107 * group owner bits directly. JRA.
2111 int saved_errno = errno; /* We might get ENOSYS */
2112 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
2113 END_PROFILE(syscall_fchmod);
2116 /* Error - return the old errno. */
2117 errno = saved_errno;
2120 #if defined(HAVE_FCHMOD)
2121 result = fchmod(fsp->fh->fd, mode);
2127 END_PROFILE(syscall_fchmod);
2131 static int vfswrap_chown(vfs_handle_struct *handle,
2132 const struct smb_filename *smb_fname,
2138 START_PROFILE(syscall_chown);
2139 result = chown(smb_fname->base_name, uid, gid);
2140 END_PROFILE(syscall_chown);
2144 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2149 START_PROFILE(syscall_fchown);
2150 result = fchown(fsp->fh->fd, uid, gid);
2151 END_PROFILE(syscall_fchown);
2159 static int vfswrap_lchown(vfs_handle_struct *handle,
2160 const struct smb_filename *smb_fname,
2166 START_PROFILE(syscall_lchown);
2167 result = lchown(smb_fname->base_name, uid, gid);
2168 END_PROFILE(syscall_lchown);
2172 static int vfswrap_chdir(vfs_handle_struct *handle,
2173 const struct smb_filename *smb_fname)
2177 START_PROFILE(syscall_chdir);
2178 result = chdir(smb_fname->base_name);
2179 END_PROFILE(syscall_chdir);
2183 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2187 struct smb_filename *smb_fname = NULL;
2189 START_PROFILE(syscall_getwd);
2190 result = sys_getwd();
2191 END_PROFILE(syscall_getwd);
2192 smb_fname = synthetic_smb_fname(ctx,
2197 if (smb_fname == NULL) {
2203 /*********************************************************************
2204 nsec timestamp resolution call. Convert down to whatever the underlying
2205 system will support.
2206 **********************************************************************/
2208 static int vfswrap_ntimes(vfs_handle_struct *handle,
2209 const struct smb_filename *smb_fname,
2210 struct smb_file_time *ft)
2214 START_PROFILE(syscall_ntimes);
2216 if (smb_fname->stream_name) {
2222 if (null_timespec(ft->atime)) {
2223 ft->atime= smb_fname->st.st_ex_atime;
2226 if (null_timespec(ft->mtime)) {
2227 ft->mtime = smb_fname->st.st_ex_mtime;
2230 if (!null_timespec(ft->create_time)) {
2231 set_create_timespec_ea(handle->conn,
2236 if ((timespec_compare(&ft->atime,
2237 &smb_fname->st.st_ex_atime) == 0) &&
2238 (timespec_compare(&ft->mtime,
2239 &smb_fname->st.st_ex_mtime) == 0)) {
2244 #if defined(HAVE_UTIMENSAT)
2246 struct timespec ts[2];
2249 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2251 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2253 if (!((result == -1) && (errno == ENOSYS))) {
2257 #if defined(HAVE_UTIMES)
2259 struct timeval tv[2];
2260 tv[0] = convert_timespec_to_timeval(ft->atime);
2261 tv[1] = convert_timespec_to_timeval(ft->mtime);
2262 result = utimes(smb_fname->base_name, tv);
2264 result = utimes(smb_fname->base_name, NULL);
2266 if (!((result == -1) && (errno == ENOSYS))) {
2270 #if defined(HAVE_UTIME)
2272 struct utimbuf times;
2273 times.actime = convert_timespec_to_time_t(ft->atime);
2274 times.modtime = convert_timespec_to_time_t(ft->mtime);
2275 result = utime(smb_fname->base_name, ×);
2277 result = utime(smb_fname->base_name, NULL);
2279 if (!((result == -1) && (errno == ENOSYS))) {
2287 END_PROFILE(syscall_ntimes);
2291 /*********************************************************************
2292 A version of ftruncate that will write the space on disk if strict
2294 **********************************************************************/
2296 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2298 off_t space_to_write;
2299 uint64_t space_avail;
2300 uint64_t bsize,dfree,dsize;
2303 SMB_STRUCT_STAT *pst;
2305 status = vfs_stat_fsp(fsp);
2306 if (!NT_STATUS_IS_OK(status)) {
2309 pst = &fsp->fsp_name->st;
2312 if (S_ISFIFO(pst->st_ex_mode))
2316 if (pst->st_ex_size == len)
2319 /* Shrink - just ftruncate. */
2320 if (pst->st_ex_size > len)
2321 return ftruncate(fsp->fh->fd, len);
2323 space_to_write = len - pst->st_ex_size;
2325 /* for allocation try fallocate first. This can fail on some
2326 platforms e.g. when the filesystem doesn't support it and no
2327 emulation is being done by the libc (like on AIX with JFS1). In that
2328 case we do our own emulation. fallocate implementations can
2329 return ENOTSUP or EINVAL in cases like that. */
2330 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2331 if (ret == -1 && errno == ENOSPC) {
2337 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2338 "error %d. Falling back to slow manual allocation\n", errno));
2340 /* available disk space is enough or not? */
2342 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2343 /* space_avail is 1k blocks */
2344 if (space_avail == (uint64_t)-1 ||
2345 ((uint64_t)space_to_write/1024 > space_avail) ) {
2350 /* Write out the real space on disk. */
2351 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2359 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2362 SMB_STRUCT_STAT *pst;
2366 START_PROFILE(syscall_ftruncate);
2368 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2369 result = strict_allocate_ftruncate(handle, fsp, len);
2370 END_PROFILE(syscall_ftruncate);
2374 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2375 ftruncate if the system supports it. Then I discovered that
2376 you can have some filesystems that support ftruncate
2377 expansion and some that don't! On Linux fat can't do
2378 ftruncate extend but ext2 can. */
2380 result = ftruncate(fsp->fh->fd, len);
2382 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2383 extend a file with ftruncate. Provide alternate implementation
2386 /* Do an fstat to see if the file is longer than the requested
2387 size in which case the ftruncate above should have
2388 succeeded or shorter, in which case seek to len - 1 and
2389 write 1 byte of zero */
2390 status = vfs_stat_fsp(fsp);
2391 if (!NT_STATUS_IS_OK(status)) {
2395 /* We need to update the files_struct after successful ftruncate */
2400 pst = &fsp->fsp_name->st;
2403 if (S_ISFIFO(pst->st_ex_mode)) {
2409 if (pst->st_ex_size == len) {
2414 if (pst->st_ex_size > len) {
2415 /* the ftruncate should have worked */
2419 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2427 END_PROFILE(syscall_ftruncate);
2431 static int vfswrap_fallocate(vfs_handle_struct *handle,
2439 START_PROFILE(syscall_fallocate);
2441 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2443 * posix_fallocate returns 0 on success, errno on error
2444 * and doesn't set errno. Make it behave like fallocate()
2445 * which returns -1, and sets errno on failure.
2452 /* sys_fallocate handles filtering of unsupported mode flags */
2453 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2455 END_PROFILE(syscall_fallocate);
2459 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2463 START_PROFILE(syscall_fcntl_lock);
2465 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2467 "force process locks",
2469 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2472 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2473 END_PROFILE(syscall_fcntl_lock);
2477 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2478 uint32_t share_mode, uint32_t access_mask)
2480 START_PROFILE(syscall_kernel_flock);
2481 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2482 END_PROFILE(syscall_kernel_flock);
2486 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2491 START_PROFILE(syscall_fcntl_getlock);
2493 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2495 "force process locks",
2497 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2500 result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2501 END_PROFILE(syscall_fcntl_getlock);
2505 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2510 START_PROFILE(syscall_linux_setlease);
2512 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2513 result = linux_setlease(fsp->fh->fd, leasetype);
2517 END_PROFILE(syscall_linux_setlease);
2521 static int vfswrap_symlink(vfs_handle_struct *handle,
2522 const char *link_target,
2523 const struct smb_filename *new_smb_fname)
2527 START_PROFILE(syscall_symlink);
2528 result = symlink(link_target, new_smb_fname->base_name);
2529 END_PROFILE(syscall_symlink);
2533 static int vfswrap_readlink(vfs_handle_struct *handle,
2534 const struct smb_filename *smb_fname,
2540 START_PROFILE(syscall_readlink);
2541 result = readlink(smb_fname->base_name, buf, bufsiz);
2542 END_PROFILE(syscall_readlink);
2546 static int vfswrap_link(vfs_handle_struct *handle,
2547 const struct smb_filename *old_smb_fname,
2548 const struct smb_filename *new_smb_fname)
2552 START_PROFILE(syscall_link);
2553 result = link(old_smb_fname->base_name, new_smb_fname->base_name);
2554 END_PROFILE(syscall_link);
2558 static int vfswrap_mknod(vfs_handle_struct *handle,
2559 const struct smb_filename *smb_fname,
2565 START_PROFILE(syscall_mknod);
2566 result = sys_mknod(smb_fname->base_name, mode, dev);
2567 END_PROFILE(syscall_mknod);
2571 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2573 const struct smb_filename *smb_fname)
2576 struct smb_filename *result_fname = NULL;
2578 START_PROFILE(syscall_realpath);
2579 result = sys_realpath(smb_fname->base_name);
2580 END_PROFILE(syscall_realpath);
2582 result_fname = synthetic_smb_fname(ctx, result, NULL, NULL, 0);
2585 return result_fname;
2588 static int vfswrap_chflags(vfs_handle_struct *handle,
2589 const struct smb_filename *smb_fname,
2593 return chflags(smb_fname->base_name, flags);
2600 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2601 const SMB_STRUCT_STAT *sbuf)
2605 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2609 key.devid = sbuf->st_ex_dev;
2610 key.inode = sbuf->st_ex_ino;
2611 /* key.extid is unused by default. */
2616 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2617 struct files_struct *fsp,
2618 const struct smb_filename *smb_fname,
2619 TALLOC_CTX *mem_ctx,
2620 unsigned int *pnum_streams,
2621 struct stream_struct **pstreams)
2623 SMB_STRUCT_STAT sbuf;
2624 struct stream_struct *tmp_streams = NULL;
2627 if ((fsp != NULL) && (fsp->is_directory)) {
2629 * No default streams on directories
2634 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2635 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2638 struct smb_filename smb_fname_cp;
2640 ZERO_STRUCT(smb_fname_cp);
2641 smb_fname_cp.base_name = discard_const_p(char,
2642 smb_fname->base_name);
2643 smb_fname_cp.flags = smb_fname->flags;
2645 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
2646 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2648 ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2650 sbuf = smb_fname_cp.st;
2654 return map_nt_error_from_unix(errno);
2657 if (S_ISDIR(sbuf.st_ex_mode)) {
2661 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2662 (*pnum_streams) + 1);
2663 if (tmp_streams == NULL) {
2664 return NT_STATUS_NO_MEMORY;
2666 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2667 if (tmp_streams[*pnum_streams].name == NULL) {
2668 return NT_STATUS_NO_MEMORY;
2670 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2671 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2674 *pstreams = tmp_streams;
2676 return NT_STATUS_OK;
2679 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2682 TALLOC_CTX *mem_ctx,
2686 * Don't fall back to get_real_filename so callers can differentiate
2687 * between a full directory scan and an actual case-insensitive stat.
2693 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2694 const struct smb_filename *smb_fname)
2696 return handle->conn->connectpath;
2699 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2700 struct byte_range_lock *br_lck,
2701 struct lock_struct *plock,
2704 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2706 /* Note: blr is not used in the default implementation. */
2707 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2710 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2711 struct messaging_context *msg_ctx,
2712 struct byte_range_lock *br_lck,
2713 const struct lock_struct *plock)
2715 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2717 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2720 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2721 struct byte_range_lock *br_lck,
2722 struct lock_struct *plock)
2724 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2726 /* Note: blr is not used in the default implementation. */
2727 return brl_lock_cancel_default(br_lck, plock);
2730 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2732 struct lock_struct *plock)
2734 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2735 plock->lock_type == WRITE_LOCK);
2737 return strict_lock_default(fsp, plock);
2740 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2742 struct lock_struct *plock)
2744 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2745 plock->lock_type == WRITE_LOCK);
2747 strict_unlock_default(fsp, plock);
2750 /* NT ACL operations. */
2752 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2754 uint32_t security_info,
2755 TALLOC_CTX *mem_ctx,
2756 struct security_descriptor **ppdesc)
2760 START_PROFILE(fget_nt_acl);
2761 result = posix_fget_nt_acl(fsp, security_info,
2763 END_PROFILE(fget_nt_acl);
2767 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2768 const struct smb_filename *smb_fname,
2769 uint32_t security_info,
2770 TALLOC_CTX *mem_ctx,
2771 struct security_descriptor **ppdesc)
2775 START_PROFILE(get_nt_acl);
2776 result = posix_get_nt_acl(handle->conn,
2781 END_PROFILE(get_nt_acl);
2785 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2789 START_PROFILE(fset_nt_acl);
2790 result = set_nt_acl(fsp, security_info_sent, psd);
2791 END_PROFILE(fset_nt_acl);
2795 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2796 struct smb_filename *file,
2797 struct security_acl *sacl,
2798 uint32_t access_requested,
2799 uint32_t access_denied)
2801 return NT_STATUS_OK; /* Nothing to do here ... */
2804 static int vfswrap_chmod_acl(vfs_handle_struct *handle,
2805 const struct smb_filename *smb_fname,
2814 START_PROFILE(chmod_acl);
2815 result = chmod_acl(handle->conn, smb_fname, mode);
2816 END_PROFILE(chmod_acl);
2821 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2829 START_PROFILE(fchmod_acl);
2830 result = fchmod_acl(fsp, mode);
2831 END_PROFILE(fchmod_acl);
2836 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2837 const struct smb_filename *smb_fname,
2838 SMB_ACL_TYPE_T type,
2839 TALLOC_CTX *mem_ctx)
2841 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
2844 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2846 TALLOC_CTX *mem_ctx)
2848 return sys_acl_get_fd(handle, fsp, mem_ctx);
2851 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
2852 const struct smb_filename *smb_fname,
2853 SMB_ACL_TYPE_T acltype,
2856 return sys_acl_set_file(handle, smb_fname, acltype, theacl);
2859 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2861 return sys_acl_set_fd(handle, fsp, theacl);
2864 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
2865 const struct smb_filename *smb_fname)
2867 return sys_acl_delete_def_file(handle, smb_fname);
2870 /****************************************************************
2871 Extended attribute operations.
2872 *****************************************************************/
2874 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
2875 const struct smb_filename *smb_fname,
2880 return getxattr(smb_fname->base_name, name, value, size);
2883 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2885 return fgetxattr(fsp->fh->fd, name, value, size);
2888 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
2889 const struct smb_filename *smb_fname,
2893 return listxattr(smb_fname->base_name, list, size);
2896 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2898 return flistxattr(fsp->fh->fd, list, size);
2901 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
2902 const struct smb_filename *smb_fname,
2905 return removexattr(smb_fname->base_name, name);
2908 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2910 return fremovexattr(fsp->fh->fd, name);
2913 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
2914 const struct smb_filename *smb_fname,
2920 return setxattr(smb_fname->base_name, name, value, size, flags);
2923 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2925 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2928 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2933 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2934 const struct smb_filename *fname,
2935 SMB_STRUCT_STAT *sbuf)
2939 bool offline = false;
2941 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2945 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2946 #if defined(ENOTSUP)
2952 status = get_full_smb_filename(talloc_tos(), fname, &path);
2953 if (!NT_STATUS_IS_OK(status)) {
2954 errno = map_errno_from_nt_status(status);
2958 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2965 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2966 struct files_struct *fsp,
2967 TALLOC_CTX *mem_ctx,
2970 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2973 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2974 struct files_struct *fsp,
2975 const DATA_BLOB old_cookie,
2976 TALLOC_CTX *mem_ctx,
2977 DATA_BLOB *new_cookie)
2979 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2983 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2984 struct smb_request *smb1req,
2985 struct smbXsrv_open *op,
2986 const DATA_BLOB old_cookie,
2987 TALLOC_CTX *mem_ctx,
2988 struct files_struct **fsp,
2989 DATA_BLOB *new_cookie)
2991 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2992 old_cookie, mem_ctx,
2996 static struct vfs_fn_pointers vfs_default_fns = {
2997 /* Disk operations */
2999 .connect_fn = vfswrap_connect,
3000 .disconnect_fn = vfswrap_disconnect,
3001 .disk_free_fn = vfswrap_disk_free,
3002 .get_quota_fn = vfswrap_get_quota,
3003 .set_quota_fn = vfswrap_set_quota,
3004 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3005 .statvfs_fn = vfswrap_statvfs,
3006 .fs_capabilities_fn = vfswrap_fs_capabilities,
3007 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3008 .snap_check_path_fn = vfswrap_snap_check_path,
3009 .snap_create_fn = vfswrap_snap_create,
3010 .snap_delete_fn = vfswrap_snap_delete,
3012 /* Directory operations */
3014 .opendir_fn = vfswrap_opendir,
3015 .fdopendir_fn = vfswrap_fdopendir,
3016 .readdir_fn = vfswrap_readdir,
3017 .readdir_attr_fn = vfswrap_readdir_attr,
3018 .seekdir_fn = vfswrap_seekdir,
3019 .telldir_fn = vfswrap_telldir,
3020 .rewind_dir_fn = vfswrap_rewinddir,
3021 .mkdir_fn = vfswrap_mkdir,
3022 .rmdir_fn = vfswrap_rmdir,
3023 .closedir_fn = vfswrap_closedir,
3024 .init_search_op_fn = vfswrap_init_search_op,
3026 /* File operations */
3028 .open_fn = vfswrap_open,
3029 .create_file_fn = vfswrap_create_file,
3030 .close_fn = vfswrap_close,
3031 .read_fn = vfswrap_read,
3032 .pread_fn = vfswrap_pread,
3033 .pread_send_fn = vfswrap_pread_send,
3034 .pread_recv_fn = vfswrap_pread_recv,
3035 .write_fn = vfswrap_write,
3036 .pwrite_fn = vfswrap_pwrite,
3037 .pwrite_send_fn = vfswrap_pwrite_send,
3038 .pwrite_recv_fn = vfswrap_pwrite_recv,
3039 .lseek_fn = vfswrap_lseek,
3040 .sendfile_fn = vfswrap_sendfile,
3041 .recvfile_fn = vfswrap_recvfile,
3042 .rename_fn = vfswrap_rename,
3043 .fsync_fn = vfswrap_fsync,
3044 .fsync_send_fn = vfswrap_fsync_send,
3045 .fsync_recv_fn = vfswrap_fsync_recv,
3046 .stat_fn = vfswrap_stat,
3047 .fstat_fn = vfswrap_fstat,
3048 .lstat_fn = vfswrap_lstat,
3049 .get_alloc_size_fn = vfswrap_get_alloc_size,
3050 .unlink_fn = vfswrap_unlink,
3051 .chmod_fn = vfswrap_chmod,
3052 .fchmod_fn = vfswrap_fchmod,
3053 .chown_fn = vfswrap_chown,
3054 .fchown_fn = vfswrap_fchown,
3055 .lchown_fn = vfswrap_lchown,
3056 .chdir_fn = vfswrap_chdir,
3057 .getwd_fn = vfswrap_getwd,
3058 .ntimes_fn = vfswrap_ntimes,
3059 .ftruncate_fn = vfswrap_ftruncate,
3060 .fallocate_fn = vfswrap_fallocate,
3061 .lock_fn = vfswrap_lock,
3062 .kernel_flock_fn = vfswrap_kernel_flock,
3063 .linux_setlease_fn = vfswrap_linux_setlease,
3064 .getlock_fn = vfswrap_getlock,
3065 .symlink_fn = vfswrap_symlink,
3066 .readlink_fn = vfswrap_readlink,
3067 .link_fn = vfswrap_link,
3068 .mknod_fn = vfswrap_mknod,
3069 .realpath_fn = vfswrap_realpath,
3070 .chflags_fn = vfswrap_chflags,
3071 .file_id_create_fn = vfswrap_file_id_create,
3072 .streaminfo_fn = vfswrap_streaminfo,
3073 .get_real_filename_fn = vfswrap_get_real_filename,
3074 .connectpath_fn = vfswrap_connectpath,
3075 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
3076 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3077 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
3078 .strict_lock_fn = vfswrap_strict_lock,
3079 .strict_unlock_fn = vfswrap_strict_unlock,
3080 .translate_name_fn = vfswrap_translate_name,
3081 .fsctl_fn = vfswrap_fsctl,
3082 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
3083 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
3084 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
3085 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
3086 .offload_read_send_fn = vfswrap_offload_read_send,
3087 .offload_read_recv_fn = vfswrap_offload_read_recv,
3088 .offload_write_send_fn = vfswrap_offload_write_send,
3089 .offload_write_recv_fn = vfswrap_offload_write_recv,
3090 .get_compression_fn = vfswrap_get_compression,
3091 .set_compression_fn = vfswrap_set_compression,
3093 /* NT ACL operations. */
3095 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
3096 .get_nt_acl_fn = vfswrap_get_nt_acl,
3097 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
3098 .audit_file_fn = vfswrap_audit_file,
3100 /* POSIX ACL operations. */
3102 .chmod_acl_fn = vfswrap_chmod_acl,
3103 .fchmod_acl_fn = vfswrap_fchmod_acl,
3105 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
3106 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3107 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
3108 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3109 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
3110 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3111 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
3113 /* EA operations. */
3114 .getxattr_fn = vfswrap_getxattr,
3115 .fgetxattr_fn = vfswrap_fgetxattr,
3116 .listxattr_fn = vfswrap_listxattr,
3117 .flistxattr_fn = vfswrap_flistxattr,
3118 .removexattr_fn = vfswrap_removexattr,
3119 .fremovexattr_fn = vfswrap_fremovexattr,
3120 .setxattr_fn = vfswrap_setxattr,
3121 .fsetxattr_fn = vfswrap_fsetxattr,
3123 /* aio operations */
3124 .aio_force_fn = vfswrap_aio_force,
3126 /* durable handle operations */
3127 .durable_cookie_fn = vfswrap_durable_cookie,
3128 .durable_disconnect_fn = vfswrap_durable_disconnect,
3129 .durable_reconnect_fn = vfswrap_durable_reconnect,
3132 NTSTATUS vfs_default_init(TALLOC_CTX *);
3133 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3135 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3136 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);