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;
1693 struct files_struct *src_fsp;
1695 struct files_struct *dst_fsp;
1699 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,
1710 off_t transfer_offset,
1711 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);
1718 files_struct *src_fsp = NULL;
1721 req = tevent_req_create(mem_ctx, &state,
1722 struct vfswrap_offload_write_state);
1727 *state = (struct vfswrap_offload_write_state) {
1730 .src_off = transfer_offset,
1731 .dst_fsp = dest_fsp,
1732 .dst_off = dest_off,
1734 .remaining = to_copy,
1738 case FSCTL_SRV_COPYCHUNK:
1739 case FSCTL_SRV_COPYCHUNK_WRITE:
1742 case FSCTL_OFFLOAD_WRITE:
1743 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
1744 return tevent_req_post(req, ev);
1746 case FSCTL_DUP_EXTENTS_TO_FILE:
1747 DBG_DEBUG("COW clones not supported by vfs_default\n");
1748 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1749 return tevent_req_post(req, ev);
1752 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1753 return tevent_req_post(req, ev);
1757 * From here on we assume a copy-chunk fsctl
1761 tevent_req_done(req);
1762 return tevent_req_post(req, ev);
1765 status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
1767 if (tevent_req_nterror(req, status)) {
1768 return tevent_req_post(req, ev);
1770 state->src_fsp = src_fsp;
1772 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
1774 status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
1775 if (!NT_STATUS_IS_OK(status)) {
1776 tevent_req_nterror(req, status);
1777 return tevent_req_post(req, ev);
1780 state->buf = talloc_array(state, uint8_t, num);
1781 if (tevent_req_nomem(state->buf, req)) {
1782 return tevent_req_post(req, ev);
1785 status = vfs_stat_fsp(src_fsp);
1786 if (tevent_req_nterror(req, status)) {
1787 return tevent_req_post(req, ev);
1790 if (src_fsp->fsp_name->st.st_ex_size < state->src_off + num) {
1792 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1793 * If the SourceOffset or SourceOffset + Length extends beyond
1794 * the end of file, the server SHOULD<240> treat this as a
1795 * STATUS_END_OF_FILE error.
1797 * <240> Section 3.3.5.15.6: Windows servers will return
1798 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1800 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1801 return tevent_req_post(req, ev);
1804 if (src_fsp->op == NULL) {
1805 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1806 return tevent_req_post(req, ev);
1809 if (dest_fsp->op == NULL) {
1810 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1811 return tevent_req_post(req, ev);
1814 status = vfswrap_offload_write_loop(req);
1815 if (!NT_STATUS_IS_OK(status)) {
1816 tevent_req_nterror(req, status);
1817 return tevent_req_post(req, ev);
1823 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
1825 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
1827 struct vfswrap_offload_write_state *state = tevent_req_data(
1828 req, struct vfswrap_offload_write_state);
1829 struct tevent_req *subreq = NULL;
1832 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
1834 init_strict_lock_struct(state->src_fsp,
1835 state->src_fsp->op->global->open_persistent_id,
1837 state->next_io_size,
1841 ok = SMB_VFS_STRICT_LOCK(state->src_fsp->conn,
1845 return NT_STATUS_FILE_LOCK_CONFLICT;
1848 subreq = SMB_VFS_PREAD_SEND(state,
1849 state->src_fsp->conn->sconn->ev_ctx,
1852 state->next_io_size,
1854 if (subreq == NULL) {
1855 return NT_STATUS_NO_MEMORY;
1857 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
1859 return NT_STATUS_OK;
1862 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
1864 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
1866 struct tevent_req *req = tevent_req_callback_data(
1867 subreq, struct tevent_req);
1868 struct vfswrap_offload_write_state *state = tevent_req_data(
1869 req, struct vfswrap_offload_write_state);
1870 struct vfs_aio_state aio_state;
1874 SMB_VFS_STRICT_UNLOCK(state->src_fsp->conn,
1877 ZERO_STRUCT(state->read_lck);
1879 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
1880 TALLOC_FREE(subreq);
1882 DBG_ERR("read failed: %s\n", strerror(errno));
1883 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1886 if (nread != state->next_io_size) {
1887 DBG_ERR("Short read, only %zd of %zu\n",
1888 nread, state->next_io_size);
1889 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1893 state->src_off += nread;
1895 init_strict_lock_struct(state->dst_fsp,
1896 state->dst_fsp->op->global->open_persistent_id,
1898 state->next_io_size,
1902 ok = SMB_VFS_STRICT_LOCK(state->dst_fsp->conn,
1906 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1910 subreq = SMB_VFS_PWRITE_SEND(state,
1914 state->next_io_size,
1916 if (subreq == NULL) {
1917 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1920 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
1923 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
1925 struct tevent_req *req = tevent_req_callback_data(
1926 subreq, struct tevent_req);
1927 struct vfswrap_offload_write_state *state = tevent_req_data(
1928 req, struct vfswrap_offload_write_state);
1929 struct vfs_aio_state aio_state;
1933 SMB_VFS_STRICT_UNLOCK(state->dst_fsp->conn,
1936 ZERO_STRUCT(state->write_lck);
1938 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
1939 TALLOC_FREE(subreq);
1940 if (nwritten == -1) {
1941 DBG_ERR("write failed: %s\n", strerror(errno));
1942 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1945 if (nwritten != state->next_io_size) {
1946 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
1947 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1951 state->dst_off += nwritten;
1953 if (state->remaining < nwritten) {
1954 /* Paranoia check */
1955 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1958 state->remaining -= nwritten;
1959 if (state->remaining == 0) {
1960 tevent_req_done(req);
1964 status = vfswrap_offload_write_loop(req);
1965 if (!NT_STATUS_IS_OK(status)) {
1966 tevent_req_nterror(req, status);
1973 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
1974 struct tevent_req *req,
1977 struct vfswrap_offload_write_state *state = tevent_req_data(
1978 req, struct vfswrap_offload_write_state);
1981 if (tevent_req_is_nterror(req, &status)) {
1982 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
1984 tevent_req_received(req);
1988 *copied = state->to_copy;
1989 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
1990 tevent_req_received(req);
1992 return NT_STATUS_OK;
1995 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1996 TALLOC_CTX *mem_ctx,
1997 struct files_struct *fsp,
1998 struct smb_filename *smb_fname,
1999 uint16_t *_compression_fmt)
2001 return NT_STATUS_INVALID_DEVICE_REQUEST;
2004 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
2005 TALLOC_CTX *mem_ctx,
2006 struct files_struct *fsp,
2007 uint16_t compression_fmt)
2009 return NT_STATUS_INVALID_DEVICE_REQUEST;
2012 /********************************************************************
2013 Given a stat buffer return the allocated size on disk, taking into
2014 account sparse files.
2015 ********************************************************************/
2016 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
2017 struct files_struct *fsp,
2018 const SMB_STRUCT_STAT *sbuf)
2022 START_PROFILE(syscall_get_alloc_size);
2024 if(S_ISDIR(sbuf->st_ex_mode)) {
2029 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2030 /* The type of st_blocksize is blkcnt_t which *MUST* be
2031 signed (according to POSIX) and can be less than 64-bits.
2032 Ensure when we're converting to 64 bits wide we don't
2034 #if defined(SIZEOF_BLKCNT_T_8)
2035 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2036 #elif defined(SIZEOF_BLKCNT_T_4)
2038 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2039 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2042 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2046 * Some file systems do not allocate a block for very
2047 * small files. But for non-empty file should report a
2051 uint64_t filesize = get_file_size_stat(sbuf);
2053 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2057 result = get_file_size_stat(sbuf);
2060 if (fsp && fsp->initial_allocation_size)
2061 result = MAX(result,fsp->initial_allocation_size);
2063 result = smb_roundup(handle->conn, result);
2066 END_PROFILE(syscall_get_alloc_size);
2070 static int vfswrap_unlink(vfs_handle_struct *handle,
2071 const struct smb_filename *smb_fname)
2075 START_PROFILE(syscall_unlink);
2077 if (smb_fname->stream_name) {
2081 result = unlink(smb_fname->base_name);
2084 END_PROFILE(syscall_unlink);
2088 static int vfswrap_chmod(vfs_handle_struct *handle,
2089 const struct smb_filename *smb_fname,
2094 START_PROFILE(syscall_chmod);
2097 * We need to do this due to the fact that the default POSIX ACL
2098 * chmod modifies the ACL *mask* for the group owner, not the
2099 * group owner bits directly. JRA.
2104 int saved_errno = errno; /* We might get ENOSYS */
2105 result = SMB_VFS_CHMOD_ACL(handle->conn,
2109 END_PROFILE(syscall_chmod);
2112 /* Error - return the old errno. */
2113 errno = saved_errno;
2116 result = chmod(smb_fname->base_name, mode);
2117 END_PROFILE(syscall_chmod);
2121 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2125 START_PROFILE(syscall_fchmod);
2128 * We need to do this due to the fact that the default POSIX ACL
2129 * chmod modifies the ACL *mask* for the group owner, not the
2130 * group owner bits directly. JRA.
2134 int saved_errno = errno; /* We might get ENOSYS */
2135 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
2136 END_PROFILE(syscall_fchmod);
2139 /* Error - return the old errno. */
2140 errno = saved_errno;
2143 #if defined(HAVE_FCHMOD)
2144 result = fchmod(fsp->fh->fd, mode);
2150 END_PROFILE(syscall_fchmod);
2154 static int vfswrap_chown(vfs_handle_struct *handle,
2155 const struct smb_filename *smb_fname,
2161 START_PROFILE(syscall_chown);
2162 result = chown(smb_fname->base_name, uid, gid);
2163 END_PROFILE(syscall_chown);
2167 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2172 START_PROFILE(syscall_fchown);
2173 result = fchown(fsp->fh->fd, uid, gid);
2174 END_PROFILE(syscall_fchown);
2182 static int vfswrap_lchown(vfs_handle_struct *handle,
2183 const struct smb_filename *smb_fname,
2189 START_PROFILE(syscall_lchown);
2190 result = lchown(smb_fname->base_name, uid, gid);
2191 END_PROFILE(syscall_lchown);
2195 static int vfswrap_chdir(vfs_handle_struct *handle,
2196 const struct smb_filename *smb_fname)
2200 START_PROFILE(syscall_chdir);
2201 result = chdir(smb_fname->base_name);
2202 END_PROFILE(syscall_chdir);
2206 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2210 struct smb_filename *smb_fname = NULL;
2212 START_PROFILE(syscall_getwd);
2213 result = sys_getwd();
2214 END_PROFILE(syscall_getwd);
2215 smb_fname = synthetic_smb_fname(ctx,
2220 if (smb_fname == NULL) {
2226 /*********************************************************************
2227 nsec timestamp resolution call. Convert down to whatever the underlying
2228 system will support.
2229 **********************************************************************/
2231 static int vfswrap_ntimes(vfs_handle_struct *handle,
2232 const struct smb_filename *smb_fname,
2233 struct smb_file_time *ft)
2237 START_PROFILE(syscall_ntimes);
2239 if (smb_fname->stream_name) {
2245 if (null_timespec(ft->atime)) {
2246 ft->atime= smb_fname->st.st_ex_atime;
2249 if (null_timespec(ft->mtime)) {
2250 ft->mtime = smb_fname->st.st_ex_mtime;
2253 if (!null_timespec(ft->create_time)) {
2254 set_create_timespec_ea(handle->conn,
2259 if ((timespec_compare(&ft->atime,
2260 &smb_fname->st.st_ex_atime) == 0) &&
2261 (timespec_compare(&ft->mtime,
2262 &smb_fname->st.st_ex_mtime) == 0)) {
2267 #if defined(HAVE_UTIMENSAT)
2269 struct timespec ts[2];
2272 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2274 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2276 if (!((result == -1) && (errno == ENOSYS))) {
2280 #if defined(HAVE_UTIMES)
2282 struct timeval tv[2];
2283 tv[0] = convert_timespec_to_timeval(ft->atime);
2284 tv[1] = convert_timespec_to_timeval(ft->mtime);
2285 result = utimes(smb_fname->base_name, tv);
2287 result = utimes(smb_fname->base_name, NULL);
2289 if (!((result == -1) && (errno == ENOSYS))) {
2293 #if defined(HAVE_UTIME)
2295 struct utimbuf times;
2296 times.actime = convert_timespec_to_time_t(ft->atime);
2297 times.modtime = convert_timespec_to_time_t(ft->mtime);
2298 result = utime(smb_fname->base_name, ×);
2300 result = utime(smb_fname->base_name, NULL);
2302 if (!((result == -1) && (errno == ENOSYS))) {
2310 END_PROFILE(syscall_ntimes);
2314 /*********************************************************************
2315 A version of ftruncate that will write the space on disk if strict
2317 **********************************************************************/
2319 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2321 off_t space_to_write;
2322 uint64_t space_avail;
2323 uint64_t bsize,dfree,dsize;
2326 SMB_STRUCT_STAT *pst;
2328 status = vfs_stat_fsp(fsp);
2329 if (!NT_STATUS_IS_OK(status)) {
2332 pst = &fsp->fsp_name->st;
2335 if (S_ISFIFO(pst->st_ex_mode))
2339 if (pst->st_ex_size == len)
2342 /* Shrink - just ftruncate. */
2343 if (pst->st_ex_size > len)
2344 return ftruncate(fsp->fh->fd, len);
2346 space_to_write = len - pst->st_ex_size;
2348 /* for allocation try fallocate first. This can fail on some
2349 platforms e.g. when the filesystem doesn't support it and no
2350 emulation is being done by the libc (like on AIX with JFS1). In that
2351 case we do our own emulation. fallocate implementations can
2352 return ENOTSUP or EINVAL in cases like that. */
2353 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2354 if (ret == -1 && errno == ENOSPC) {
2360 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2361 "error %d. Falling back to slow manual allocation\n", errno));
2363 /* available disk space is enough or not? */
2365 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2366 /* space_avail is 1k blocks */
2367 if (space_avail == (uint64_t)-1 ||
2368 ((uint64_t)space_to_write/1024 > space_avail) ) {
2373 /* Write out the real space on disk. */
2374 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2382 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2385 SMB_STRUCT_STAT *pst;
2389 START_PROFILE(syscall_ftruncate);
2391 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2392 result = strict_allocate_ftruncate(handle, fsp, len);
2393 END_PROFILE(syscall_ftruncate);
2397 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2398 ftruncate if the system supports it. Then I discovered that
2399 you can have some filesystems that support ftruncate
2400 expansion and some that don't! On Linux fat can't do
2401 ftruncate extend but ext2 can. */
2403 result = ftruncate(fsp->fh->fd, len);
2405 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2406 extend a file with ftruncate. Provide alternate implementation
2409 /* Do an fstat to see if the file is longer than the requested
2410 size in which case the ftruncate above should have
2411 succeeded or shorter, in which case seek to len - 1 and
2412 write 1 byte of zero */
2413 status = vfs_stat_fsp(fsp);
2414 if (!NT_STATUS_IS_OK(status)) {
2418 /* We need to update the files_struct after successful ftruncate */
2423 pst = &fsp->fsp_name->st;
2426 if (S_ISFIFO(pst->st_ex_mode)) {
2432 if (pst->st_ex_size == len) {
2437 if (pst->st_ex_size > len) {
2438 /* the ftruncate should have worked */
2442 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2450 END_PROFILE(syscall_ftruncate);
2454 static int vfswrap_fallocate(vfs_handle_struct *handle,
2462 START_PROFILE(syscall_fallocate);
2464 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2466 * posix_fallocate returns 0 on success, errno on error
2467 * and doesn't set errno. Make it behave like fallocate()
2468 * which returns -1, and sets errno on failure.
2475 /* sys_fallocate handles filtering of unsupported mode flags */
2476 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2478 END_PROFILE(syscall_fallocate);
2482 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2486 START_PROFILE(syscall_fcntl_lock);
2488 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2490 "force process locks",
2492 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2495 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2496 END_PROFILE(syscall_fcntl_lock);
2500 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2501 uint32_t share_mode, uint32_t access_mask)
2503 START_PROFILE(syscall_kernel_flock);
2504 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2505 END_PROFILE(syscall_kernel_flock);
2509 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2514 START_PROFILE(syscall_fcntl_getlock);
2516 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2518 "force process locks",
2520 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2523 result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2524 END_PROFILE(syscall_fcntl_getlock);
2528 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2533 START_PROFILE(syscall_linux_setlease);
2535 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2536 result = linux_setlease(fsp->fh->fd, leasetype);
2540 END_PROFILE(syscall_linux_setlease);
2544 static int vfswrap_symlink(vfs_handle_struct *handle,
2545 const char *link_target,
2546 const struct smb_filename *new_smb_fname)
2550 START_PROFILE(syscall_symlink);
2551 result = symlink(link_target, new_smb_fname->base_name);
2552 END_PROFILE(syscall_symlink);
2556 static int vfswrap_readlink(vfs_handle_struct *handle,
2557 const struct smb_filename *smb_fname,
2563 START_PROFILE(syscall_readlink);
2564 result = readlink(smb_fname->base_name, buf, bufsiz);
2565 END_PROFILE(syscall_readlink);
2569 static int vfswrap_link(vfs_handle_struct *handle,
2570 const struct smb_filename *old_smb_fname,
2571 const struct smb_filename *new_smb_fname)
2575 START_PROFILE(syscall_link);
2576 result = link(old_smb_fname->base_name, new_smb_fname->base_name);
2577 END_PROFILE(syscall_link);
2581 static int vfswrap_mknod(vfs_handle_struct *handle,
2582 const struct smb_filename *smb_fname,
2588 START_PROFILE(syscall_mknod);
2589 result = sys_mknod(smb_fname->base_name, mode, dev);
2590 END_PROFILE(syscall_mknod);
2594 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2596 const struct smb_filename *smb_fname)
2599 struct smb_filename *result_fname = NULL;
2601 START_PROFILE(syscall_realpath);
2602 result = sys_realpath(smb_fname->base_name);
2603 END_PROFILE(syscall_realpath);
2605 result_fname = synthetic_smb_fname(ctx, result, NULL, NULL, 0);
2608 return result_fname;
2611 static int vfswrap_chflags(vfs_handle_struct *handle,
2612 const struct smb_filename *smb_fname,
2616 return chflags(smb_fname->base_name, flags);
2623 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2624 const SMB_STRUCT_STAT *sbuf)
2628 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2632 key.devid = sbuf->st_ex_dev;
2633 key.inode = sbuf->st_ex_ino;
2634 /* key.extid is unused by default. */
2639 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2640 struct files_struct *fsp,
2641 const struct smb_filename *smb_fname,
2642 TALLOC_CTX *mem_ctx,
2643 unsigned int *pnum_streams,
2644 struct stream_struct **pstreams)
2646 SMB_STRUCT_STAT sbuf;
2647 struct stream_struct *tmp_streams = NULL;
2650 if ((fsp != NULL) && (fsp->is_directory)) {
2652 * No default streams on directories
2657 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2658 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2661 struct smb_filename smb_fname_cp;
2663 ZERO_STRUCT(smb_fname_cp);
2664 smb_fname_cp.base_name = discard_const_p(char,
2665 smb_fname->base_name);
2666 smb_fname_cp.flags = smb_fname->flags;
2668 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
2669 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2671 ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2673 sbuf = smb_fname_cp.st;
2677 return map_nt_error_from_unix(errno);
2680 if (S_ISDIR(sbuf.st_ex_mode)) {
2684 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2685 (*pnum_streams) + 1);
2686 if (tmp_streams == NULL) {
2687 return NT_STATUS_NO_MEMORY;
2689 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2690 if (tmp_streams[*pnum_streams].name == NULL) {
2691 return NT_STATUS_NO_MEMORY;
2693 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2694 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2697 *pstreams = tmp_streams;
2699 return NT_STATUS_OK;
2702 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2705 TALLOC_CTX *mem_ctx,
2709 * Don't fall back to get_real_filename so callers can differentiate
2710 * between a full directory scan and an actual case-insensitive stat.
2716 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2717 const struct smb_filename *smb_fname)
2719 return handle->conn->connectpath;
2722 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2723 struct byte_range_lock *br_lck,
2724 struct lock_struct *plock,
2727 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2729 /* Note: blr is not used in the default implementation. */
2730 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2733 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2734 struct messaging_context *msg_ctx,
2735 struct byte_range_lock *br_lck,
2736 const struct lock_struct *plock)
2738 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2740 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2743 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2744 struct byte_range_lock *br_lck,
2745 struct lock_struct *plock)
2747 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2749 /* Note: blr is not used in the default implementation. */
2750 return brl_lock_cancel_default(br_lck, plock);
2753 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2755 struct lock_struct *plock)
2757 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2758 plock->lock_type == WRITE_LOCK);
2760 return strict_lock_default(fsp, plock);
2763 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2765 struct lock_struct *plock)
2767 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2768 plock->lock_type == WRITE_LOCK);
2770 strict_unlock_default(fsp, plock);
2773 /* NT ACL operations. */
2775 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2777 uint32_t security_info,
2778 TALLOC_CTX *mem_ctx,
2779 struct security_descriptor **ppdesc)
2783 START_PROFILE(fget_nt_acl);
2784 result = posix_fget_nt_acl(fsp, security_info,
2786 END_PROFILE(fget_nt_acl);
2790 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2791 const struct smb_filename *smb_fname,
2792 uint32_t security_info,
2793 TALLOC_CTX *mem_ctx,
2794 struct security_descriptor **ppdesc)
2798 START_PROFILE(get_nt_acl);
2799 result = posix_get_nt_acl(handle->conn,
2804 END_PROFILE(get_nt_acl);
2808 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2812 START_PROFILE(fset_nt_acl);
2813 result = set_nt_acl(fsp, security_info_sent, psd);
2814 END_PROFILE(fset_nt_acl);
2818 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2819 struct smb_filename *file,
2820 struct security_acl *sacl,
2821 uint32_t access_requested,
2822 uint32_t access_denied)
2824 return NT_STATUS_OK; /* Nothing to do here ... */
2827 static int vfswrap_chmod_acl(vfs_handle_struct *handle,
2828 const struct smb_filename *smb_fname,
2837 START_PROFILE(chmod_acl);
2838 result = chmod_acl(handle->conn, smb_fname, mode);
2839 END_PROFILE(chmod_acl);
2844 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2852 START_PROFILE(fchmod_acl);
2853 result = fchmod_acl(fsp, mode);
2854 END_PROFILE(fchmod_acl);
2859 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2860 const struct smb_filename *smb_fname,
2861 SMB_ACL_TYPE_T type,
2862 TALLOC_CTX *mem_ctx)
2864 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
2867 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2869 TALLOC_CTX *mem_ctx)
2871 return sys_acl_get_fd(handle, fsp, mem_ctx);
2874 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
2875 const struct smb_filename *smb_fname,
2876 SMB_ACL_TYPE_T acltype,
2879 return sys_acl_set_file(handle, smb_fname, acltype, theacl);
2882 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2884 return sys_acl_set_fd(handle, fsp, theacl);
2887 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
2888 const struct smb_filename *smb_fname)
2890 return sys_acl_delete_def_file(handle, smb_fname);
2893 /****************************************************************
2894 Extended attribute operations.
2895 *****************************************************************/
2897 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
2898 const struct smb_filename *smb_fname,
2903 return getxattr(smb_fname->base_name, name, value, size);
2906 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2908 return fgetxattr(fsp->fh->fd, name, value, size);
2911 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
2912 const struct smb_filename *smb_fname,
2916 return listxattr(smb_fname->base_name, list, size);
2919 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2921 return flistxattr(fsp->fh->fd, list, size);
2924 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
2925 const struct smb_filename *smb_fname,
2928 return removexattr(smb_fname->base_name, name);
2931 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2933 return fremovexattr(fsp->fh->fd, name);
2936 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
2937 const struct smb_filename *smb_fname,
2943 return setxattr(smb_fname->base_name, name, value, size, flags);
2946 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2948 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2951 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2956 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2957 const struct smb_filename *fname,
2958 SMB_STRUCT_STAT *sbuf)
2962 bool offline = false;
2964 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2968 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2969 #if defined(ENOTSUP)
2975 status = get_full_smb_filename(talloc_tos(), fname, &path);
2976 if (!NT_STATUS_IS_OK(status)) {
2977 errno = map_errno_from_nt_status(status);
2981 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2988 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2989 struct files_struct *fsp,
2990 TALLOC_CTX *mem_ctx,
2993 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2996 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2997 struct files_struct *fsp,
2998 const DATA_BLOB old_cookie,
2999 TALLOC_CTX *mem_ctx,
3000 DATA_BLOB *new_cookie)
3002 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
3006 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
3007 struct smb_request *smb1req,
3008 struct smbXsrv_open *op,
3009 const DATA_BLOB old_cookie,
3010 TALLOC_CTX *mem_ctx,
3011 struct files_struct **fsp,
3012 DATA_BLOB *new_cookie)
3014 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
3015 old_cookie, mem_ctx,
3019 static struct vfs_fn_pointers vfs_default_fns = {
3020 /* Disk operations */
3022 .connect_fn = vfswrap_connect,
3023 .disconnect_fn = vfswrap_disconnect,
3024 .disk_free_fn = vfswrap_disk_free,
3025 .get_quota_fn = vfswrap_get_quota,
3026 .set_quota_fn = vfswrap_set_quota,
3027 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3028 .statvfs_fn = vfswrap_statvfs,
3029 .fs_capabilities_fn = vfswrap_fs_capabilities,
3030 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3031 .snap_check_path_fn = vfswrap_snap_check_path,
3032 .snap_create_fn = vfswrap_snap_create,
3033 .snap_delete_fn = vfswrap_snap_delete,
3035 /* Directory operations */
3037 .opendir_fn = vfswrap_opendir,
3038 .fdopendir_fn = vfswrap_fdopendir,
3039 .readdir_fn = vfswrap_readdir,
3040 .readdir_attr_fn = vfswrap_readdir_attr,
3041 .seekdir_fn = vfswrap_seekdir,
3042 .telldir_fn = vfswrap_telldir,
3043 .rewind_dir_fn = vfswrap_rewinddir,
3044 .mkdir_fn = vfswrap_mkdir,
3045 .rmdir_fn = vfswrap_rmdir,
3046 .closedir_fn = vfswrap_closedir,
3047 .init_search_op_fn = vfswrap_init_search_op,
3049 /* File operations */
3051 .open_fn = vfswrap_open,
3052 .create_file_fn = vfswrap_create_file,
3053 .close_fn = vfswrap_close,
3054 .read_fn = vfswrap_read,
3055 .pread_fn = vfswrap_pread,
3056 .pread_send_fn = vfswrap_pread_send,
3057 .pread_recv_fn = vfswrap_pread_recv,
3058 .write_fn = vfswrap_write,
3059 .pwrite_fn = vfswrap_pwrite,
3060 .pwrite_send_fn = vfswrap_pwrite_send,
3061 .pwrite_recv_fn = vfswrap_pwrite_recv,
3062 .lseek_fn = vfswrap_lseek,
3063 .sendfile_fn = vfswrap_sendfile,
3064 .recvfile_fn = vfswrap_recvfile,
3065 .rename_fn = vfswrap_rename,
3066 .fsync_fn = vfswrap_fsync,
3067 .fsync_send_fn = vfswrap_fsync_send,
3068 .fsync_recv_fn = vfswrap_fsync_recv,
3069 .stat_fn = vfswrap_stat,
3070 .fstat_fn = vfswrap_fstat,
3071 .lstat_fn = vfswrap_lstat,
3072 .get_alloc_size_fn = vfswrap_get_alloc_size,
3073 .unlink_fn = vfswrap_unlink,
3074 .chmod_fn = vfswrap_chmod,
3075 .fchmod_fn = vfswrap_fchmod,
3076 .chown_fn = vfswrap_chown,
3077 .fchown_fn = vfswrap_fchown,
3078 .lchown_fn = vfswrap_lchown,
3079 .chdir_fn = vfswrap_chdir,
3080 .getwd_fn = vfswrap_getwd,
3081 .ntimes_fn = vfswrap_ntimes,
3082 .ftruncate_fn = vfswrap_ftruncate,
3083 .fallocate_fn = vfswrap_fallocate,
3084 .lock_fn = vfswrap_lock,
3085 .kernel_flock_fn = vfswrap_kernel_flock,
3086 .linux_setlease_fn = vfswrap_linux_setlease,
3087 .getlock_fn = vfswrap_getlock,
3088 .symlink_fn = vfswrap_symlink,
3089 .readlink_fn = vfswrap_readlink,
3090 .link_fn = vfswrap_link,
3091 .mknod_fn = vfswrap_mknod,
3092 .realpath_fn = vfswrap_realpath,
3093 .chflags_fn = vfswrap_chflags,
3094 .file_id_create_fn = vfswrap_file_id_create,
3095 .streaminfo_fn = vfswrap_streaminfo,
3096 .get_real_filename_fn = vfswrap_get_real_filename,
3097 .connectpath_fn = vfswrap_connectpath,
3098 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
3099 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3100 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
3101 .strict_lock_fn = vfswrap_strict_lock,
3102 .strict_unlock_fn = vfswrap_strict_unlock,
3103 .translate_name_fn = vfswrap_translate_name,
3104 .fsctl_fn = vfswrap_fsctl,
3105 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
3106 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
3107 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
3108 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
3109 .offload_read_send_fn = vfswrap_offload_read_send,
3110 .offload_read_recv_fn = vfswrap_offload_read_recv,
3111 .offload_write_send_fn = vfswrap_offload_write_send,
3112 .offload_write_recv_fn = vfswrap_offload_write_recv,
3113 .get_compression_fn = vfswrap_get_compression,
3114 .set_compression_fn = vfswrap_set_compression,
3116 /* NT ACL operations. */
3118 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
3119 .get_nt_acl_fn = vfswrap_get_nt_acl,
3120 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
3121 .audit_file_fn = vfswrap_audit_file,
3123 /* POSIX ACL operations. */
3125 .chmod_acl_fn = vfswrap_chmod_acl,
3126 .fchmod_acl_fn = vfswrap_fchmod_acl,
3128 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
3129 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3130 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
3131 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3132 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
3133 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3134 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
3136 /* EA operations. */
3137 .getxattr_fn = vfswrap_getxattr,
3138 .fgetxattr_fn = vfswrap_fgetxattr,
3139 .listxattr_fn = vfswrap_listxattr,
3140 .flistxattr_fn = vfswrap_flistxattr,
3141 .removexattr_fn = vfswrap_removexattr,
3142 .fremovexattr_fn = vfswrap_fremovexattr,
3143 .setxattr_fn = vfswrap_setxattr,
3144 .fsetxattr_fn = vfswrap_fsetxattr,
3146 /* aio operations */
3147 .aio_force_fn = vfswrap_aio_force,
3149 /* durable handle operations */
3150 .durable_cookie_fn = vfswrap_durable_cookie,
3151 .durable_disconnect_fn = vfswrap_durable_disconnect,
3152 .durable_reconnect_fn = vfswrap_durable_reconnect,
3155 NTSTATUS vfs_default_init(TALLOC_CTX *);
3156 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3158 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3159 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);