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,
1751 tevent_req_done(req);
1752 return tevent_req_post(req, ev);
1755 state->buf = talloc_array(state, uint8_t, num);
1756 if (tevent_req_nomem(state->buf, req)) {
1757 return tevent_req_post(req, ev);
1760 status = vfs_stat_fsp(src_fsp);
1761 if (tevent_req_nterror(req, status)) {
1762 return tevent_req_post(req, ev);
1765 if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
1767 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1768 * If the SourceOffset or SourceOffset + Length extends beyond
1769 * the end of file, the server SHOULD<240> treat this as a
1770 * STATUS_END_OF_FILE error.
1772 * <240> Section 3.3.5.15.6: Windows servers will return
1773 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1775 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1776 return tevent_req_post(req, ev);
1779 if (src_fsp->op == NULL) {
1780 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1781 return tevent_req_post(req, ev);
1784 if (dest_fsp->op == NULL) {
1785 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1786 return tevent_req_post(req, ev);
1789 status = vfswrap_offload_write_loop(req);
1790 if (!NT_STATUS_IS_OK(status)) {
1791 tevent_req_nterror(req, status);
1792 return tevent_req_post(req, ev);
1798 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
1800 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
1802 struct vfswrap_offload_write_state *state = tevent_req_data(
1803 req, struct vfswrap_offload_write_state);
1804 struct tevent_req *subreq = NULL;
1807 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
1809 if (!(state->flags & VFS_OFFLOAD_WRITE_FL_IGNORE_LOCKS)) {
1810 init_strict_lock_struct(state->src_fsp,
1811 state->src_fsp->op->global->open_persistent_id,
1813 state->next_io_size,
1817 ok = SMB_VFS_STRICT_LOCK(state->src_fsp->conn,
1821 return NT_STATUS_FILE_LOCK_CONFLICT;
1825 subreq = SMB_VFS_PREAD_SEND(state,
1826 state->src_fsp->conn->sconn->ev_ctx,
1829 state->next_io_size,
1831 if (subreq == NULL) {
1832 return NT_STATUS_NO_MEMORY;
1834 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
1836 return NT_STATUS_OK;
1839 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
1841 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
1843 struct tevent_req *req = tevent_req_callback_data(
1844 subreq, struct tevent_req);
1845 struct vfswrap_offload_write_state *state = tevent_req_data(
1846 req, struct vfswrap_offload_write_state);
1847 struct vfs_aio_state aio_state;
1851 if (!(state->flags & VFS_OFFLOAD_WRITE_FL_IGNORE_LOCKS)) {
1852 SMB_VFS_STRICT_UNLOCK(state->src_fsp->conn,
1855 ZERO_STRUCT(state->read_lck);
1858 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
1859 TALLOC_FREE(subreq);
1861 DBG_ERR("read failed: %s\n", strerror(errno));
1862 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1865 if (nread != state->next_io_size) {
1866 DBG_ERR("Short read, only %zd of %zu\n",
1867 nread, state->next_io_size);
1868 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1872 state->src_off += nread;
1874 if (!(state->flags & VFS_OFFLOAD_WRITE_FL_IGNORE_LOCKS)) {
1875 init_strict_lock_struct(state->dst_fsp,
1876 state->dst_fsp->op->global->open_persistent_id,
1878 state->next_io_size,
1882 ok = SMB_VFS_STRICT_LOCK(state->dst_fsp->conn,
1886 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1891 subreq = SMB_VFS_PWRITE_SEND(state,
1895 state->next_io_size,
1897 if (subreq == NULL) {
1898 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1901 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
1904 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
1906 struct tevent_req *req = tevent_req_callback_data(
1907 subreq, struct tevent_req);
1908 struct vfswrap_offload_write_state *state = tevent_req_data(
1909 req, struct vfswrap_offload_write_state);
1910 struct vfs_aio_state aio_state;
1914 if (!(state->flags & VFS_OFFLOAD_WRITE_FL_IGNORE_LOCKS)) {
1915 SMB_VFS_STRICT_UNLOCK(state->dst_fsp->conn,
1918 ZERO_STRUCT(state->write_lck);
1921 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
1922 TALLOC_FREE(subreq);
1923 if (nwritten == -1) {
1924 DBG_ERR("write failed: %s\n", strerror(errno));
1925 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1928 if (nwritten != state->next_io_size) {
1929 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
1930 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1934 state->dst_off += nwritten;
1936 if (state->remaining < nwritten) {
1937 /* Paranoia check */
1938 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1941 state->remaining -= nwritten;
1942 if (state->remaining == 0) {
1943 tevent_req_done(req);
1947 status = vfswrap_offload_write_loop(req);
1948 if (!NT_STATUS_IS_OK(status)) {
1949 tevent_req_nterror(req, status);
1956 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
1957 struct tevent_req *req,
1960 struct vfswrap_offload_write_state *state = tevent_req_data(
1961 req, struct vfswrap_offload_write_state);
1964 if (tevent_req_is_nterror(req, &status)) {
1965 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
1967 tevent_req_received(req);
1971 *copied = state->to_copy;
1972 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
1973 tevent_req_received(req);
1975 return NT_STATUS_OK;
1978 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1979 TALLOC_CTX *mem_ctx,
1980 struct files_struct *fsp,
1981 struct smb_filename *smb_fname,
1982 uint16_t *_compression_fmt)
1984 return NT_STATUS_INVALID_DEVICE_REQUEST;
1987 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1988 TALLOC_CTX *mem_ctx,
1989 struct files_struct *fsp,
1990 uint16_t compression_fmt)
1992 return NT_STATUS_INVALID_DEVICE_REQUEST;
1995 /********************************************************************
1996 Given a stat buffer return the allocated size on disk, taking into
1997 account sparse files.
1998 ********************************************************************/
1999 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
2000 struct files_struct *fsp,
2001 const SMB_STRUCT_STAT *sbuf)
2005 START_PROFILE(syscall_get_alloc_size);
2007 if(S_ISDIR(sbuf->st_ex_mode)) {
2012 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2013 /* The type of st_blocksize is blkcnt_t which *MUST* be
2014 signed (according to POSIX) and can be less than 64-bits.
2015 Ensure when we're converting to 64 bits wide we don't
2017 #if defined(SIZEOF_BLKCNT_T_8)
2018 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2019 #elif defined(SIZEOF_BLKCNT_T_4)
2021 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2022 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2025 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2029 * Some file systems do not allocate a block for very
2030 * small files. But for non-empty file should report a
2034 uint64_t filesize = get_file_size_stat(sbuf);
2036 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2040 result = get_file_size_stat(sbuf);
2043 if (fsp && fsp->initial_allocation_size)
2044 result = MAX(result,fsp->initial_allocation_size);
2046 result = smb_roundup(handle->conn, result);
2049 END_PROFILE(syscall_get_alloc_size);
2053 static int vfswrap_unlink(vfs_handle_struct *handle,
2054 const struct smb_filename *smb_fname)
2058 START_PROFILE(syscall_unlink);
2060 if (smb_fname->stream_name) {
2064 result = unlink(smb_fname->base_name);
2067 END_PROFILE(syscall_unlink);
2071 static int vfswrap_chmod(vfs_handle_struct *handle,
2072 const struct smb_filename *smb_fname,
2077 START_PROFILE(syscall_chmod);
2080 * We need to do this due to the fact that the default POSIX ACL
2081 * chmod modifies the ACL *mask* for the group owner, not the
2082 * group owner bits directly. JRA.
2087 int saved_errno = errno; /* We might get ENOSYS */
2088 result = SMB_VFS_CHMOD_ACL(handle->conn,
2092 END_PROFILE(syscall_chmod);
2095 /* Error - return the old errno. */
2096 errno = saved_errno;
2099 result = chmod(smb_fname->base_name, mode);
2100 END_PROFILE(syscall_chmod);
2104 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2108 START_PROFILE(syscall_fchmod);
2111 * We need to do this due to the fact that the default POSIX ACL
2112 * chmod modifies the ACL *mask* for the group owner, not the
2113 * group owner bits directly. JRA.
2117 int saved_errno = errno; /* We might get ENOSYS */
2118 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
2119 END_PROFILE(syscall_fchmod);
2122 /* Error - return the old errno. */
2123 errno = saved_errno;
2126 #if defined(HAVE_FCHMOD)
2127 result = fchmod(fsp->fh->fd, mode);
2133 END_PROFILE(syscall_fchmod);
2137 static int vfswrap_chown(vfs_handle_struct *handle,
2138 const struct smb_filename *smb_fname,
2144 START_PROFILE(syscall_chown);
2145 result = chown(smb_fname->base_name, uid, gid);
2146 END_PROFILE(syscall_chown);
2150 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2155 START_PROFILE(syscall_fchown);
2156 result = fchown(fsp->fh->fd, uid, gid);
2157 END_PROFILE(syscall_fchown);
2165 static int vfswrap_lchown(vfs_handle_struct *handle,
2166 const struct smb_filename *smb_fname,
2172 START_PROFILE(syscall_lchown);
2173 result = lchown(smb_fname->base_name, uid, gid);
2174 END_PROFILE(syscall_lchown);
2178 static int vfswrap_chdir(vfs_handle_struct *handle,
2179 const struct smb_filename *smb_fname)
2183 START_PROFILE(syscall_chdir);
2184 result = chdir(smb_fname->base_name);
2185 END_PROFILE(syscall_chdir);
2189 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2193 struct smb_filename *smb_fname = NULL;
2195 START_PROFILE(syscall_getwd);
2196 result = sys_getwd();
2197 END_PROFILE(syscall_getwd);
2198 smb_fname = synthetic_smb_fname(ctx,
2203 if (smb_fname == NULL) {
2209 /*********************************************************************
2210 nsec timestamp resolution call. Convert down to whatever the underlying
2211 system will support.
2212 **********************************************************************/
2214 static int vfswrap_ntimes(vfs_handle_struct *handle,
2215 const struct smb_filename *smb_fname,
2216 struct smb_file_time *ft)
2220 START_PROFILE(syscall_ntimes);
2222 if (smb_fname->stream_name) {
2228 if (null_timespec(ft->atime)) {
2229 ft->atime= smb_fname->st.st_ex_atime;
2232 if (null_timespec(ft->mtime)) {
2233 ft->mtime = smb_fname->st.st_ex_mtime;
2236 if (!null_timespec(ft->create_time)) {
2237 set_create_timespec_ea(handle->conn,
2242 if ((timespec_compare(&ft->atime,
2243 &smb_fname->st.st_ex_atime) == 0) &&
2244 (timespec_compare(&ft->mtime,
2245 &smb_fname->st.st_ex_mtime) == 0)) {
2250 #if defined(HAVE_UTIMENSAT)
2252 struct timespec ts[2];
2255 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2257 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2259 if (!((result == -1) && (errno == ENOSYS))) {
2263 #if defined(HAVE_UTIMES)
2265 struct timeval tv[2];
2266 tv[0] = convert_timespec_to_timeval(ft->atime);
2267 tv[1] = convert_timespec_to_timeval(ft->mtime);
2268 result = utimes(smb_fname->base_name, tv);
2270 result = utimes(smb_fname->base_name, NULL);
2272 if (!((result == -1) && (errno == ENOSYS))) {
2276 #if defined(HAVE_UTIME)
2278 struct utimbuf times;
2279 times.actime = convert_timespec_to_time_t(ft->atime);
2280 times.modtime = convert_timespec_to_time_t(ft->mtime);
2281 result = utime(smb_fname->base_name, ×);
2283 result = utime(smb_fname->base_name, NULL);
2285 if (!((result == -1) && (errno == ENOSYS))) {
2293 END_PROFILE(syscall_ntimes);
2297 /*********************************************************************
2298 A version of ftruncate that will write the space on disk if strict
2300 **********************************************************************/
2302 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2304 off_t space_to_write;
2305 uint64_t space_avail;
2306 uint64_t bsize,dfree,dsize;
2309 SMB_STRUCT_STAT *pst;
2311 status = vfs_stat_fsp(fsp);
2312 if (!NT_STATUS_IS_OK(status)) {
2315 pst = &fsp->fsp_name->st;
2318 if (S_ISFIFO(pst->st_ex_mode))
2322 if (pst->st_ex_size == len)
2325 /* Shrink - just ftruncate. */
2326 if (pst->st_ex_size > len)
2327 return ftruncate(fsp->fh->fd, len);
2329 space_to_write = len - pst->st_ex_size;
2331 /* for allocation try fallocate first. This can fail on some
2332 platforms e.g. when the filesystem doesn't support it and no
2333 emulation is being done by the libc (like on AIX with JFS1). In that
2334 case we do our own emulation. fallocate implementations can
2335 return ENOTSUP or EINVAL in cases like that. */
2336 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2337 if (ret == -1 && errno == ENOSPC) {
2343 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2344 "error %d. Falling back to slow manual allocation\n", errno));
2346 /* available disk space is enough or not? */
2348 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2349 /* space_avail is 1k blocks */
2350 if (space_avail == (uint64_t)-1 ||
2351 ((uint64_t)space_to_write/1024 > space_avail) ) {
2356 /* Write out the real space on disk. */
2357 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2365 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2368 SMB_STRUCT_STAT *pst;
2372 START_PROFILE(syscall_ftruncate);
2374 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2375 result = strict_allocate_ftruncate(handle, fsp, len);
2376 END_PROFILE(syscall_ftruncate);
2380 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2381 ftruncate if the system supports it. Then I discovered that
2382 you can have some filesystems that support ftruncate
2383 expansion and some that don't! On Linux fat can't do
2384 ftruncate extend but ext2 can. */
2386 result = ftruncate(fsp->fh->fd, len);
2388 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2389 extend a file with ftruncate. Provide alternate implementation
2392 /* Do an fstat to see if the file is longer than the requested
2393 size in which case the ftruncate above should have
2394 succeeded or shorter, in which case seek to len - 1 and
2395 write 1 byte of zero */
2396 status = vfs_stat_fsp(fsp);
2397 if (!NT_STATUS_IS_OK(status)) {
2401 /* We need to update the files_struct after successful ftruncate */
2406 pst = &fsp->fsp_name->st;
2409 if (S_ISFIFO(pst->st_ex_mode)) {
2415 if (pst->st_ex_size == len) {
2420 if (pst->st_ex_size > len) {
2421 /* the ftruncate should have worked */
2425 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2433 END_PROFILE(syscall_ftruncate);
2437 static int vfswrap_fallocate(vfs_handle_struct *handle,
2445 START_PROFILE(syscall_fallocate);
2447 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2449 * posix_fallocate returns 0 on success, errno on error
2450 * and doesn't set errno. Make it behave like fallocate()
2451 * which returns -1, and sets errno on failure.
2458 /* sys_fallocate handles filtering of unsupported mode flags */
2459 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2461 END_PROFILE(syscall_fallocate);
2465 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2469 START_PROFILE(syscall_fcntl_lock);
2471 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2473 "force process locks",
2475 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2478 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2479 END_PROFILE(syscall_fcntl_lock);
2483 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2484 uint32_t share_mode, uint32_t access_mask)
2486 START_PROFILE(syscall_kernel_flock);
2487 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2488 END_PROFILE(syscall_kernel_flock);
2492 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2497 START_PROFILE(syscall_fcntl_getlock);
2499 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2501 "force process locks",
2503 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2506 result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2507 END_PROFILE(syscall_fcntl_getlock);
2511 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2516 START_PROFILE(syscall_linux_setlease);
2518 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2519 result = linux_setlease(fsp->fh->fd, leasetype);
2523 END_PROFILE(syscall_linux_setlease);
2527 static int vfswrap_symlink(vfs_handle_struct *handle,
2528 const char *link_target,
2529 const struct smb_filename *new_smb_fname)
2533 START_PROFILE(syscall_symlink);
2534 result = symlink(link_target, new_smb_fname->base_name);
2535 END_PROFILE(syscall_symlink);
2539 static int vfswrap_readlink(vfs_handle_struct *handle,
2540 const struct smb_filename *smb_fname,
2546 START_PROFILE(syscall_readlink);
2547 result = readlink(smb_fname->base_name, buf, bufsiz);
2548 END_PROFILE(syscall_readlink);
2552 static int vfswrap_link(vfs_handle_struct *handle,
2553 const struct smb_filename *old_smb_fname,
2554 const struct smb_filename *new_smb_fname)
2558 START_PROFILE(syscall_link);
2559 result = link(old_smb_fname->base_name, new_smb_fname->base_name);
2560 END_PROFILE(syscall_link);
2564 static int vfswrap_mknod(vfs_handle_struct *handle,
2565 const struct smb_filename *smb_fname,
2571 START_PROFILE(syscall_mknod);
2572 result = sys_mknod(smb_fname->base_name, mode, dev);
2573 END_PROFILE(syscall_mknod);
2577 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2579 const struct smb_filename *smb_fname)
2582 struct smb_filename *result_fname = NULL;
2584 START_PROFILE(syscall_realpath);
2585 result = sys_realpath(smb_fname->base_name);
2586 END_PROFILE(syscall_realpath);
2588 result_fname = synthetic_smb_fname(ctx, result, NULL, NULL, 0);
2591 return result_fname;
2594 static int vfswrap_chflags(vfs_handle_struct *handle,
2595 const struct smb_filename *smb_fname,
2599 return chflags(smb_fname->base_name, flags);
2606 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2607 const SMB_STRUCT_STAT *sbuf)
2611 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2615 key.devid = sbuf->st_ex_dev;
2616 key.inode = sbuf->st_ex_ino;
2617 /* key.extid is unused by default. */
2622 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2623 struct files_struct *fsp,
2624 const struct smb_filename *smb_fname,
2625 TALLOC_CTX *mem_ctx,
2626 unsigned int *pnum_streams,
2627 struct stream_struct **pstreams)
2629 SMB_STRUCT_STAT sbuf;
2630 struct stream_struct *tmp_streams = NULL;
2633 if ((fsp != NULL) && (fsp->is_directory)) {
2635 * No default streams on directories
2640 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2641 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2644 struct smb_filename smb_fname_cp;
2646 ZERO_STRUCT(smb_fname_cp);
2647 smb_fname_cp.base_name = discard_const_p(char,
2648 smb_fname->base_name);
2649 smb_fname_cp.flags = smb_fname->flags;
2651 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
2652 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2654 ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2656 sbuf = smb_fname_cp.st;
2660 return map_nt_error_from_unix(errno);
2663 if (S_ISDIR(sbuf.st_ex_mode)) {
2667 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2668 (*pnum_streams) + 1);
2669 if (tmp_streams == NULL) {
2670 return NT_STATUS_NO_MEMORY;
2672 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2673 if (tmp_streams[*pnum_streams].name == NULL) {
2674 return NT_STATUS_NO_MEMORY;
2676 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2677 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2680 *pstreams = tmp_streams;
2682 return NT_STATUS_OK;
2685 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2688 TALLOC_CTX *mem_ctx,
2692 * Don't fall back to get_real_filename so callers can differentiate
2693 * between a full directory scan and an actual case-insensitive stat.
2699 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2700 const struct smb_filename *smb_fname)
2702 return handle->conn->connectpath;
2705 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2706 struct byte_range_lock *br_lck,
2707 struct lock_struct *plock,
2710 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2712 /* Note: blr is not used in the default implementation. */
2713 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2716 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2717 struct messaging_context *msg_ctx,
2718 struct byte_range_lock *br_lck,
2719 const struct lock_struct *plock)
2721 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2723 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2726 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2727 struct byte_range_lock *br_lck,
2728 struct lock_struct *plock)
2730 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2732 /* Note: blr is not used in the default implementation. */
2733 return brl_lock_cancel_default(br_lck, plock);
2736 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2738 struct lock_struct *plock)
2740 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2741 plock->lock_type == WRITE_LOCK);
2743 return strict_lock_default(fsp, plock);
2746 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2748 struct lock_struct *plock)
2750 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2751 plock->lock_type == WRITE_LOCK);
2753 strict_unlock_default(fsp, plock);
2756 /* NT ACL operations. */
2758 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2760 uint32_t security_info,
2761 TALLOC_CTX *mem_ctx,
2762 struct security_descriptor **ppdesc)
2766 START_PROFILE(fget_nt_acl);
2767 result = posix_fget_nt_acl(fsp, security_info,
2769 END_PROFILE(fget_nt_acl);
2773 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2774 const struct smb_filename *smb_fname,
2775 uint32_t security_info,
2776 TALLOC_CTX *mem_ctx,
2777 struct security_descriptor **ppdesc)
2781 START_PROFILE(get_nt_acl);
2782 result = posix_get_nt_acl(handle->conn,
2787 END_PROFILE(get_nt_acl);
2791 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2795 START_PROFILE(fset_nt_acl);
2796 result = set_nt_acl(fsp, security_info_sent, psd);
2797 END_PROFILE(fset_nt_acl);
2801 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2802 struct smb_filename *file,
2803 struct security_acl *sacl,
2804 uint32_t access_requested,
2805 uint32_t access_denied)
2807 return NT_STATUS_OK; /* Nothing to do here ... */
2810 static int vfswrap_chmod_acl(vfs_handle_struct *handle,
2811 const struct smb_filename *smb_fname,
2820 START_PROFILE(chmod_acl);
2821 result = chmod_acl(handle->conn, smb_fname, mode);
2822 END_PROFILE(chmod_acl);
2827 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2835 START_PROFILE(fchmod_acl);
2836 result = fchmod_acl(fsp, mode);
2837 END_PROFILE(fchmod_acl);
2842 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2843 const struct smb_filename *smb_fname,
2844 SMB_ACL_TYPE_T type,
2845 TALLOC_CTX *mem_ctx)
2847 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
2850 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2852 TALLOC_CTX *mem_ctx)
2854 return sys_acl_get_fd(handle, fsp, mem_ctx);
2857 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
2858 const struct smb_filename *smb_fname,
2859 SMB_ACL_TYPE_T acltype,
2862 return sys_acl_set_file(handle, smb_fname, acltype, theacl);
2865 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2867 return sys_acl_set_fd(handle, fsp, theacl);
2870 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
2871 const struct smb_filename *smb_fname)
2873 return sys_acl_delete_def_file(handle, smb_fname);
2876 /****************************************************************
2877 Extended attribute operations.
2878 *****************************************************************/
2880 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
2881 const struct smb_filename *smb_fname,
2886 return getxattr(smb_fname->base_name, name, value, size);
2889 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2891 return fgetxattr(fsp->fh->fd, name, value, size);
2894 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
2895 const struct smb_filename *smb_fname,
2899 return listxattr(smb_fname->base_name, list, size);
2902 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2904 return flistxattr(fsp->fh->fd, list, size);
2907 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
2908 const struct smb_filename *smb_fname,
2911 return removexattr(smb_fname->base_name, name);
2914 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2916 return fremovexattr(fsp->fh->fd, name);
2919 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
2920 const struct smb_filename *smb_fname,
2926 return setxattr(smb_fname->base_name, name, value, size, flags);
2929 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2931 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2934 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2939 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2940 const struct smb_filename *fname,
2941 SMB_STRUCT_STAT *sbuf)
2945 bool offline = false;
2947 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2951 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2952 #if defined(ENOTSUP)
2958 status = get_full_smb_filename(talloc_tos(), fname, &path);
2959 if (!NT_STATUS_IS_OK(status)) {
2960 errno = map_errno_from_nt_status(status);
2964 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2971 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2972 struct files_struct *fsp,
2973 TALLOC_CTX *mem_ctx,
2976 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2979 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2980 struct files_struct *fsp,
2981 const DATA_BLOB old_cookie,
2982 TALLOC_CTX *mem_ctx,
2983 DATA_BLOB *new_cookie)
2985 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2989 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2990 struct smb_request *smb1req,
2991 struct smbXsrv_open *op,
2992 const DATA_BLOB old_cookie,
2993 TALLOC_CTX *mem_ctx,
2994 struct files_struct **fsp,
2995 DATA_BLOB *new_cookie)
2997 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2998 old_cookie, mem_ctx,
3002 static struct vfs_fn_pointers vfs_default_fns = {
3003 /* Disk operations */
3005 .connect_fn = vfswrap_connect,
3006 .disconnect_fn = vfswrap_disconnect,
3007 .disk_free_fn = vfswrap_disk_free,
3008 .get_quota_fn = vfswrap_get_quota,
3009 .set_quota_fn = vfswrap_set_quota,
3010 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3011 .statvfs_fn = vfswrap_statvfs,
3012 .fs_capabilities_fn = vfswrap_fs_capabilities,
3013 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3014 .snap_check_path_fn = vfswrap_snap_check_path,
3015 .snap_create_fn = vfswrap_snap_create,
3016 .snap_delete_fn = vfswrap_snap_delete,
3018 /* Directory operations */
3020 .opendir_fn = vfswrap_opendir,
3021 .fdopendir_fn = vfswrap_fdopendir,
3022 .readdir_fn = vfswrap_readdir,
3023 .readdir_attr_fn = vfswrap_readdir_attr,
3024 .seekdir_fn = vfswrap_seekdir,
3025 .telldir_fn = vfswrap_telldir,
3026 .rewind_dir_fn = vfswrap_rewinddir,
3027 .mkdir_fn = vfswrap_mkdir,
3028 .rmdir_fn = vfswrap_rmdir,
3029 .closedir_fn = vfswrap_closedir,
3030 .init_search_op_fn = vfswrap_init_search_op,
3032 /* File operations */
3034 .open_fn = vfswrap_open,
3035 .create_file_fn = vfswrap_create_file,
3036 .close_fn = vfswrap_close,
3037 .read_fn = vfswrap_read,
3038 .pread_fn = vfswrap_pread,
3039 .pread_send_fn = vfswrap_pread_send,
3040 .pread_recv_fn = vfswrap_pread_recv,
3041 .write_fn = vfswrap_write,
3042 .pwrite_fn = vfswrap_pwrite,
3043 .pwrite_send_fn = vfswrap_pwrite_send,
3044 .pwrite_recv_fn = vfswrap_pwrite_recv,
3045 .lseek_fn = vfswrap_lseek,
3046 .sendfile_fn = vfswrap_sendfile,
3047 .recvfile_fn = vfswrap_recvfile,
3048 .rename_fn = vfswrap_rename,
3049 .fsync_fn = vfswrap_fsync,
3050 .fsync_send_fn = vfswrap_fsync_send,
3051 .fsync_recv_fn = vfswrap_fsync_recv,
3052 .stat_fn = vfswrap_stat,
3053 .fstat_fn = vfswrap_fstat,
3054 .lstat_fn = vfswrap_lstat,
3055 .get_alloc_size_fn = vfswrap_get_alloc_size,
3056 .unlink_fn = vfswrap_unlink,
3057 .chmod_fn = vfswrap_chmod,
3058 .fchmod_fn = vfswrap_fchmod,
3059 .chown_fn = vfswrap_chown,
3060 .fchown_fn = vfswrap_fchown,
3061 .lchown_fn = vfswrap_lchown,
3062 .chdir_fn = vfswrap_chdir,
3063 .getwd_fn = vfswrap_getwd,
3064 .ntimes_fn = vfswrap_ntimes,
3065 .ftruncate_fn = vfswrap_ftruncate,
3066 .fallocate_fn = vfswrap_fallocate,
3067 .lock_fn = vfswrap_lock,
3068 .kernel_flock_fn = vfswrap_kernel_flock,
3069 .linux_setlease_fn = vfswrap_linux_setlease,
3070 .getlock_fn = vfswrap_getlock,
3071 .symlink_fn = vfswrap_symlink,
3072 .readlink_fn = vfswrap_readlink,
3073 .link_fn = vfswrap_link,
3074 .mknod_fn = vfswrap_mknod,
3075 .realpath_fn = vfswrap_realpath,
3076 .chflags_fn = vfswrap_chflags,
3077 .file_id_create_fn = vfswrap_file_id_create,
3078 .streaminfo_fn = vfswrap_streaminfo,
3079 .get_real_filename_fn = vfswrap_get_real_filename,
3080 .connectpath_fn = vfswrap_connectpath,
3081 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
3082 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3083 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
3084 .strict_lock_fn = vfswrap_strict_lock,
3085 .strict_unlock_fn = vfswrap_strict_unlock,
3086 .translate_name_fn = vfswrap_translate_name,
3087 .fsctl_fn = vfswrap_fsctl,
3088 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
3089 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
3090 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
3091 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
3092 .offload_read_send_fn = vfswrap_offload_read_send,
3093 .offload_read_recv_fn = vfswrap_offload_read_recv,
3094 .offload_write_send_fn = vfswrap_offload_write_send,
3095 .offload_write_recv_fn = vfswrap_offload_write_recv,
3096 .get_compression_fn = vfswrap_get_compression,
3097 .set_compression_fn = vfswrap_set_compression,
3099 /* NT ACL operations. */
3101 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
3102 .get_nt_acl_fn = vfswrap_get_nt_acl,
3103 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
3104 .audit_file_fn = vfswrap_audit_file,
3106 /* POSIX ACL operations. */
3108 .chmod_acl_fn = vfswrap_chmod_acl,
3109 .fchmod_acl_fn = vfswrap_fchmod_acl,
3111 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
3112 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3113 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
3114 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3115 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
3116 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3117 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
3119 /* EA operations. */
3120 .getxattr_fn = vfswrap_getxattr,
3121 .fgetxattr_fn = vfswrap_fgetxattr,
3122 .listxattr_fn = vfswrap_listxattr,
3123 .flistxattr_fn = vfswrap_flistxattr,
3124 .removexattr_fn = vfswrap_removexattr,
3125 .fremovexattr_fn = vfswrap_fremovexattr,
3126 .setxattr_fn = vfswrap_setxattr,
3127 .fsetxattr_fn = vfswrap_fsetxattr,
3129 /* aio operations */
3130 .aio_force_fn = vfswrap_aio_force,
3132 /* durable handle operations */
3133 .durable_cookie_fn = vfswrap_durable_cookie,
3134 .durable_disconnect_fn = vfswrap_durable_disconnect,
3135 .durable_reconnect_fn = vfswrap_durable_reconnect,
3138 NTSTATUS vfs_default_init(TALLOC_CTX *);
3139 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3141 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3142 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);