2 Unix SMB/CIFS implementation.
3 Wrap disk only vfs functions to sidestep dodgy compilers.
4 Copyright (C) Tim Potter 1998
5 Copyright (C) Jeremy Allison 2007
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "system/time.h"
23 #include "system/filesys.h"
24 #include "smbd/smbd.h"
25 #include "smbd/globals.h"
27 #include "smbprofile.h"
28 #include "../libcli/security/security.h"
29 #include "passdb/lookup_sid.h"
30 #include "source3/include/msdfs.h"
31 #include "librpc/gen_ndr/ndr_dfsblobs.h"
32 #include "lib/util/tevent_unix.h"
33 #include "lib/util/tevent_ntstatus.h"
34 #include "lib/util/sys_rw.h"
35 #include "lib/pthreadpool/pthreadpool_tevent.h"
36 #include "librpc/gen_ndr/ndr_ioctl.h"
37 #include "offload_token.h"
40 #define DBGC_CLASS DBGC_VFS
42 /* Check for NULL pointer parameters in vfswrap_* functions */
44 /* We don't want to have NULL function pointers lying around. Someone
45 is sure to try and execute them. These stubs are used to prevent
48 static int vfswrap_connect(vfs_handle_struct *handle, const char *service, const char *user)
50 return 0; /* Return >= 0 for success */
53 static void vfswrap_disconnect(vfs_handle_struct *handle)
59 static uint64_t vfswrap_disk_free(vfs_handle_struct *handle,
60 const struct smb_filename *smb_fname,
65 if (sys_fsusage(smb_fname->base_name, dfree, dsize) != 0) {
73 static int vfswrap_get_quota(struct vfs_handle_struct *handle,
74 const struct smb_filename *smb_fname,
75 enum SMB_QUOTA_TYPE qtype,
79 #ifdef HAVE_SYS_QUOTAS
82 START_PROFILE(syscall_get_quota);
83 result = sys_get_quota(smb_fname->base_name, qtype, id, qt);
84 END_PROFILE(syscall_get_quota);
92 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
94 #ifdef HAVE_SYS_QUOTAS
97 START_PROFILE(syscall_set_quota);
98 result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
99 END_PROFILE(syscall_set_quota);
107 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
108 struct files_struct *fsp,
109 struct shadow_copy_data *shadow_copy_data,
113 return -1; /* Not implemented. */
116 static int vfswrap_statvfs(struct vfs_handle_struct *handle,
117 const struct smb_filename *smb_fname,
118 vfs_statvfs_struct *statbuf)
120 return sys_statvfs(smb_fname->base_name, statbuf);
123 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
124 enum timestamp_set_resolution *p_ts_res)
126 connection_struct *conn = handle->conn;
127 uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
128 struct smb_filename *smb_fname_cpath = NULL;
129 struct vfs_statvfs_struct statbuf;
132 smb_fname_cpath = synthetic_smb_fname(talloc_tos(), conn->connectpath,
134 if (smb_fname_cpath == NULL) {
138 ZERO_STRUCT(statbuf);
139 ret = SMB_VFS_STATVFS(conn, smb_fname_cpath, &statbuf);
141 caps = statbuf.FsCapabilities;
144 *p_ts_res = TIMESTAMP_SET_SECONDS;
146 /* Work out what timestamp resolution we can
147 * use when setting a timestamp. */
149 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
151 TALLOC_FREE(smb_fname_cpath);
155 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
156 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
157 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
158 /* If any of the normal UNIX directory timestamps
159 * have a non-zero tv_nsec component assume
160 * we might be able to set sub-second timestamps.
161 * See what filetime set primitives we have.
163 #if defined(HAVE_UTIMENSAT)
164 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
165 #elif defined(HAVE_UTIMES)
166 /* utimes allows msec timestamps to be set. */
167 *p_ts_res = TIMESTAMP_SET_MSEC;
168 #elif defined(HAVE_UTIME)
169 /* utime only allows sec timestamps to be set. */
170 *p_ts_res = TIMESTAMP_SET_SECONDS;
173 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
175 "available on share %s, directory %s\n",
176 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
177 lp_servicename(talloc_tos(), conn->params->service),
178 conn->connectpath ));
180 TALLOC_FREE(smb_fname_cpath);
184 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
185 struct dfs_GetDFSReferral *r)
187 struct junction_map *junction = NULL;
189 bool self_referral = false;
190 char *pathnamep = NULL;
191 char *local_dfs_path = NULL;
194 uint16_t max_referral_level = r->in.req.max_referral_level;
197 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
200 /* get the junction entry */
201 if (r->in.req.servername == NULL) {
202 return NT_STATUS_NOT_FOUND;
206 * Trim pathname sent by client so it begins with only one backslash.
207 * Two backslashes confuse some dfs clients
210 local_dfs_path = talloc_strdup(r, r->in.req.servername);
211 if (local_dfs_path == NULL) {
212 return NT_STATUS_NO_MEMORY;
214 pathnamep = local_dfs_path;
215 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
216 IS_DIRECTORY_SEP(pathnamep[1])) {
220 junction = talloc_zero(r, struct junction_map);
221 if (junction == NULL) {
222 return NT_STATUS_NO_MEMORY;
225 /* The following call can change cwd. */
226 status = get_referred_path(r, pathnamep,
227 handle->conn->sconn->remote_address,
228 handle->conn->sconn->local_address,
229 !handle->conn->sconn->using_smb2,
230 junction, &consumedcnt, &self_referral);
231 if (!NT_STATUS_IS_OK(status)) {
232 struct smb_filename connectpath_fname = {
233 .base_name = handle->conn->connectpath
235 vfs_ChDir(handle->conn, &connectpath_fname);
239 struct smb_filename connectpath_fname = {
240 .base_name = handle->conn->connectpath
242 vfs_ChDir(handle->conn, &connectpath_fname);
245 if (!self_referral) {
246 pathnamep[consumedcnt] = '\0';
249 dbgtext("Path %s to alternate path(s):",
251 for (i=0; i < junction->referral_count; i++) {
253 junction->referral_list[i].alternate_path);
259 if (r->in.req.max_referral_level <= 2) {
260 max_referral_level = 2;
262 if (r->in.req.max_referral_level >= 3) {
263 max_referral_level = 3;
266 r->out.resp = talloc_zero(r, struct dfs_referral_resp);
267 if (r->out.resp == NULL) {
268 return NT_STATUS_NO_MEMORY;
271 r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
272 r->out.resp->nb_referrals = junction->referral_count;
274 r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
276 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
279 r->out.resp->referral_entries = talloc_zero_array(r,
280 struct dfs_referral_type,
281 r->out.resp->nb_referrals);
282 if (r->out.resp->referral_entries == NULL) {
283 return NT_STATUS_NO_MEMORY;
286 switch (max_referral_level) {
288 for(i=0; i < junction->referral_count; i++) {
289 struct referral *ref = &junction->referral_list[i];
290 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
291 struct dfs_referral_type *t =
292 &r->out.resp->referral_entries[i];
293 struct dfs_referral_v2 *v2 = &t->referral.v2;
296 v2->size = VERSION2_REFERRAL_SIZE;
298 v2->server_type = DFS_SERVER_ROOT;
300 v2->server_type = DFS_SERVER_NON_ROOT;
303 v2->proximity = ref->proximity;
305 v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
306 if (v2->DFS_path == NULL) {
307 return NT_STATUS_NO_MEMORY;
309 v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
310 if (v2->DFS_alt_path == NULL) {
311 return NT_STATUS_NO_MEMORY;
313 v2->netw_address = talloc_strdup(mem_ctx,
314 ref->alternate_path);
315 if (v2->netw_address == NULL) {
316 return NT_STATUS_NO_MEMORY;
322 for(i=0; i < junction->referral_count; i++) {
323 struct referral *ref = &junction->referral_list[i];
324 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
325 struct dfs_referral_type *t =
326 &r->out.resp->referral_entries[i];
327 struct dfs_referral_v3 *v3 = &t->referral.v3;
328 struct dfs_normal_referral *r1 = &v3->referrals.r1;
331 v3->size = VERSION3_REFERRAL_SIZE;
333 v3->server_type = DFS_SERVER_ROOT;
335 v3->server_type = DFS_SERVER_NON_ROOT;
339 r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
340 if (r1->DFS_path == NULL) {
341 return NT_STATUS_NO_MEMORY;
343 r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
344 if (r1->DFS_alt_path == NULL) {
345 return NT_STATUS_NO_MEMORY;
347 r1->netw_address = talloc_strdup(mem_ctx,
348 ref->alternate_path);
349 if (r1->netw_address == NULL) {
350 return NT_STATUS_NO_MEMORY;
355 DEBUG(0,("Invalid dfs referral version: %d\n",
356 max_referral_level));
357 return NT_STATUS_INVALID_LEVEL;
361 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
367 static NTSTATUS vfswrap_snap_check_path(struct vfs_handle_struct *handle,
369 const char *service_path,
372 return NT_STATUS_NOT_SUPPORTED;
375 static NTSTATUS vfswrap_snap_create(struct vfs_handle_struct *handle,
377 const char *base_volume,
383 return NT_STATUS_NOT_SUPPORTED;
386 static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle,
391 return NT_STATUS_NOT_SUPPORTED;
394 /* Directory operations */
396 static DIR *vfswrap_opendir(vfs_handle_struct *handle,
397 const struct smb_filename *smb_fname,
403 START_PROFILE(syscall_opendir);
404 result = opendir(smb_fname->base_name);
405 END_PROFILE(syscall_opendir);
409 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
416 START_PROFILE(syscall_fdopendir);
417 result = sys_fdopendir(fsp->fh->fd);
418 END_PROFILE(syscall_fdopendir);
423 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
425 SMB_STRUCT_STAT *sbuf)
427 struct dirent *result;
429 START_PROFILE(syscall_readdir);
430 result = readdir(dirp);
431 END_PROFILE(syscall_readdir);
433 /* Default Posix readdir() does not give us stat info.
434 * Set to invalid to indicate we didn't return this info. */
435 SET_STAT_INVALID(*sbuf);
436 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
437 if (result != NULL) {
438 /* See if we can efficiently return this. */
440 int flags = AT_SYMLINK_NOFOLLOW;
441 int ret = fstatat(dirfd(dirp),
446 * As this is an optimization,
447 * ignore it if we stat'ed a
448 * symlink. Make the caller
449 * do it again as we don't
450 * know if they wanted the link
451 * info, or its target info.
453 if ((ret == 0) && (!S_ISLNK(st.st_mode))) {
454 init_stat_ex_from_stat(sbuf,
456 lp_fake_directory_create_times(
457 SNUM(handle->conn)));
465 static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
466 const struct smb_filename *fname,
468 struct readdir_attr_data **attr_data)
470 return NT_STATUS_NOT_SUPPORTED;
473 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
475 START_PROFILE(syscall_seekdir);
476 seekdir(dirp, offset);
477 END_PROFILE(syscall_seekdir);
480 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
483 START_PROFILE(syscall_telldir);
484 result = telldir(dirp);
485 END_PROFILE(syscall_telldir);
489 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
491 START_PROFILE(syscall_rewinddir);
493 END_PROFILE(syscall_rewinddir);
496 static int vfswrap_mkdir(vfs_handle_struct *handle,
497 const struct smb_filename *smb_fname,
501 const char *path = smb_fname->base_name;
504 START_PROFILE(syscall_mkdir);
506 if (lp_inherit_acls(SNUM(handle->conn))
507 && parent_dirname(talloc_tos(), path, &parent, NULL)
508 && directory_has_default_acl(handle->conn, parent)) {
509 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
514 result = mkdir(path, mode);
516 END_PROFILE(syscall_mkdir);
520 static int vfswrap_rmdir(vfs_handle_struct *handle,
521 const struct smb_filename *smb_fname)
525 START_PROFILE(syscall_rmdir);
526 result = rmdir(smb_fname->base_name);
527 END_PROFILE(syscall_rmdir);
531 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
535 START_PROFILE(syscall_closedir);
536 result = closedir(dirp);
537 END_PROFILE(syscall_closedir);
541 /* File operations */
543 static int vfswrap_open(vfs_handle_struct *handle,
544 struct smb_filename *smb_fname,
545 files_struct *fsp, int flags, mode_t mode)
549 START_PROFILE(syscall_open);
551 if (smb_fname->stream_name) {
556 result = open(smb_fname->base_name, flags, mode);
558 END_PROFILE(syscall_open);
562 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
563 struct smb_request *req,
564 uint16_t root_dir_fid,
565 struct smb_filename *smb_fname,
566 uint32_t access_mask,
567 uint32_t share_access,
568 uint32_t create_disposition,
569 uint32_t create_options,
570 uint32_t file_attributes,
571 uint32_t oplock_request,
572 struct smb2_lease *lease,
573 uint64_t allocation_size,
574 uint32_t private_flags,
575 struct security_descriptor *sd,
576 struct ea_list *ea_list,
577 files_struct **result,
579 const struct smb2_create_blobs *in_context_blobs,
580 struct smb2_create_blobs *out_context_blobs)
582 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
583 access_mask, share_access,
584 create_disposition, create_options,
585 file_attributes, oplock_request, lease,
586 allocation_size, private_flags,
588 pinfo, in_context_blobs, out_context_blobs);
591 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
595 START_PROFILE(syscall_close);
596 result = fd_close_posix(fsp);
597 END_PROFILE(syscall_close);
601 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
602 size_t n, off_t offset)
606 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
607 START_PROFILE_BYTES(syscall_pread, n);
608 result = sys_pread(fsp->fh->fd, data, n, offset);
609 END_PROFILE_BYTES(syscall_pread);
611 if (result == -1 && errno == ESPIPE) {
612 /* Maintain the fiction that pipes can be seeked (sought?) on. */
613 result = sys_read(fsp->fh->fd, data, n);
617 #else /* HAVE_PREAD */
620 #endif /* HAVE_PREAD */
625 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
626 size_t n, off_t offset)
630 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
631 START_PROFILE_BYTES(syscall_pwrite, n);
632 result = sys_pwrite(fsp->fh->fd, data, n, offset);
633 END_PROFILE_BYTES(syscall_pwrite);
635 if (result == -1 && errno == ESPIPE) {
636 /* Maintain the fiction that pipes can be sought on. */
637 result = sys_write(fsp->fh->fd, data, n);
640 #else /* HAVE_PWRITE */
643 #endif /* HAVE_PWRITE */
648 struct vfswrap_pread_state {
655 struct vfs_aio_state vfs_aio_state;
656 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
659 static void vfs_pread_do(void *private_data);
660 static void vfs_pread_done(struct tevent_req *subreq);
661 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state);
663 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
665 struct tevent_context *ev,
666 struct files_struct *fsp,
668 size_t n, off_t offset)
670 struct tevent_req *req, *subreq;
671 struct vfswrap_pread_state *state;
673 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
679 state->fd = fsp->fh->fd;
682 state->offset = offset;
684 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
685 state->profile_bytes, n);
686 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
688 subreq = pthreadpool_tevent_job_send(
689 state, ev, handle->conn->sconn->pool,
690 vfs_pread_do, state);
691 if (tevent_req_nomem(subreq, req)) {
692 return tevent_req_post(req, ev);
694 tevent_req_set_callback(subreq, vfs_pread_done, req);
696 talloc_set_destructor(state, vfs_pread_state_destructor);
701 static void vfs_pread_do(void *private_data)
703 struct vfswrap_pread_state *state = talloc_get_type_abort(
704 private_data, struct vfswrap_pread_state);
705 struct timespec start_time;
706 struct timespec end_time;
708 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
710 PROFILE_TIMESTAMP(&start_time);
713 state->ret = pread(state->fd, state->buf, state->count,
715 } while ((state->ret == -1) && (errno == EINTR));
717 if (state->ret == -1) {
718 state->vfs_aio_state.error = errno;
721 PROFILE_TIMESTAMP(&end_time);
723 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
725 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
728 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state)
733 static void vfs_pread_done(struct tevent_req *subreq)
735 struct tevent_req *req = tevent_req_callback_data(
736 subreq, struct tevent_req);
737 struct vfswrap_pread_state *state = tevent_req_data(
738 req, struct vfswrap_pread_state);
741 ret = pthreadpool_tevent_job_recv(subreq);
743 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
744 talloc_set_destructor(state, NULL);
745 if (tevent_req_error(req, ret)) {
749 tevent_req_done(req);
752 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
753 struct vfs_aio_state *vfs_aio_state)
755 struct vfswrap_pread_state *state = tevent_req_data(
756 req, struct vfswrap_pread_state);
758 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
762 *vfs_aio_state = state->vfs_aio_state;
766 struct vfswrap_pwrite_state {
773 struct vfs_aio_state vfs_aio_state;
774 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
777 static void vfs_pwrite_do(void *private_data);
778 static void vfs_pwrite_done(struct tevent_req *subreq);
779 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state);
781 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
783 struct tevent_context *ev,
784 struct files_struct *fsp,
786 size_t n, off_t offset)
788 struct tevent_req *req, *subreq;
789 struct vfswrap_pwrite_state *state;
791 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
797 state->fd = fsp->fh->fd;
800 state->offset = offset;
802 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
803 state->profile_bytes, n);
804 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
806 subreq = pthreadpool_tevent_job_send(
807 state, ev, handle->conn->sconn->pool,
808 vfs_pwrite_do, state);
809 if (tevent_req_nomem(subreq, req)) {
810 return tevent_req_post(req, ev);
812 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
814 talloc_set_destructor(state, vfs_pwrite_state_destructor);
819 static void vfs_pwrite_do(void *private_data)
821 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
822 private_data, struct vfswrap_pwrite_state);
823 struct timespec start_time;
824 struct timespec end_time;
826 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
828 PROFILE_TIMESTAMP(&start_time);
831 state->ret = pwrite(state->fd, state->buf, state->count,
833 } while ((state->ret == -1) && (errno == EINTR));
835 if (state->ret == -1) {
836 state->vfs_aio_state.error = errno;
839 PROFILE_TIMESTAMP(&end_time);
841 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
843 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
846 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state)
851 static void vfs_pwrite_done(struct tevent_req *subreq)
853 struct tevent_req *req = tevent_req_callback_data(
854 subreq, struct tevent_req);
855 struct vfswrap_pwrite_state *state = tevent_req_data(
856 req, struct vfswrap_pwrite_state);
859 ret = pthreadpool_tevent_job_recv(subreq);
861 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
862 talloc_set_destructor(state, NULL);
863 if (tevent_req_error(req, ret)) {
867 tevent_req_done(req);
870 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
871 struct vfs_aio_state *vfs_aio_state)
873 struct vfswrap_pwrite_state *state = tevent_req_data(
874 req, struct vfswrap_pwrite_state);
876 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
880 *vfs_aio_state = state->vfs_aio_state;
884 struct vfswrap_fsync_state {
888 struct vfs_aio_state vfs_aio_state;
889 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
892 static void vfs_fsync_do(void *private_data);
893 static void vfs_fsync_done(struct tevent_req *subreq);
894 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state);
896 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
898 struct tevent_context *ev,
899 struct files_struct *fsp)
901 struct tevent_req *req, *subreq;
902 struct vfswrap_fsync_state *state;
904 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
910 state->fd = fsp->fh->fd;
912 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
913 state->profile_basic);
915 subreq = pthreadpool_tevent_job_send(
916 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
917 if (tevent_req_nomem(subreq, req)) {
918 return tevent_req_post(req, ev);
920 tevent_req_set_callback(subreq, vfs_fsync_done, req);
922 talloc_set_destructor(state, vfs_fsync_state_destructor);
927 static void vfs_fsync_do(void *private_data)
929 struct vfswrap_fsync_state *state = talloc_get_type_abort(
930 private_data, struct vfswrap_fsync_state);
931 struct timespec start_time;
932 struct timespec end_time;
934 PROFILE_TIMESTAMP(&start_time);
937 state->ret = fsync(state->fd);
938 } while ((state->ret == -1) && (errno == EINTR));
940 if (state->ret == -1) {
941 state->vfs_aio_state.error = errno;
944 PROFILE_TIMESTAMP(&end_time);
946 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
949 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state)
954 static void vfs_fsync_done(struct tevent_req *subreq)
956 struct tevent_req *req = tevent_req_callback_data(
957 subreq, struct tevent_req);
958 struct vfswrap_fsync_state *state = tevent_req_data(
959 req, struct vfswrap_fsync_state);
962 ret = pthreadpool_tevent_job_recv(subreq);
964 SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
965 talloc_set_destructor(state, NULL);
966 if (tevent_req_error(req, ret)) {
970 tevent_req_done(req);
973 static int vfswrap_fsync_recv(struct tevent_req *req,
974 struct vfs_aio_state *vfs_aio_state)
976 struct vfswrap_fsync_state *state = tevent_req_data(
977 req, struct vfswrap_fsync_state);
979 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
983 *vfs_aio_state = state->vfs_aio_state;
987 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
991 START_PROFILE(syscall_lseek);
993 /* Cope with 'stat' file opens. */
994 if (fsp->fh->fd != -1)
995 result = lseek(fsp->fh->fd, offset, whence);
998 * We want to maintain the fiction that we can seek
999 * on a fifo for file system purposes. This allows
1000 * people to set up UNIX fifo's that feed data to Windows
1001 * applications. JRA.
1004 if((result == -1) && (errno == ESPIPE)) {
1009 END_PROFILE(syscall_lseek);
1013 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1014 off_t offset, size_t n)
1018 START_PROFILE_BYTES(syscall_sendfile, n);
1019 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
1020 END_PROFILE_BYTES(syscall_sendfile);
1024 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1026 files_struct *tofsp,
1032 START_PROFILE_BYTES(syscall_recvfile, n);
1033 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
1034 END_PROFILE_BYTES(syscall_recvfile);
1038 static int vfswrap_rename(vfs_handle_struct *handle,
1039 const struct smb_filename *smb_fname_src,
1040 const struct smb_filename *smb_fname_dst)
1044 START_PROFILE(syscall_rename);
1046 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
1051 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
1054 END_PROFILE(syscall_rename);
1058 static int vfswrap_stat(vfs_handle_struct *handle,
1059 struct smb_filename *smb_fname)
1063 START_PROFILE(syscall_stat);
1065 if (smb_fname->stream_name) {
1070 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1071 lp_fake_directory_create_times(SNUM(handle->conn)));
1073 END_PROFILE(syscall_stat);
1077 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1081 START_PROFILE(syscall_fstat);
1082 result = sys_fstat(fsp->fh->fd,
1083 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1084 END_PROFILE(syscall_fstat);
1088 static int vfswrap_lstat(vfs_handle_struct *handle,
1089 struct smb_filename *smb_fname)
1093 START_PROFILE(syscall_lstat);
1095 if (smb_fname->stream_name) {
1100 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1101 lp_fake_directory_create_times(SNUM(handle->conn)));
1103 END_PROFILE(syscall_lstat);
1107 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1109 enum vfs_translate_direction direction,
1110 TALLOC_CTX *mem_ctx,
1113 return NT_STATUS_NONE_MAPPED;
1117 * Implement the default fsctl operation.
1119 static bool vfswrap_logged_ioctl_message = false;
1121 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1122 struct files_struct *fsp,
1125 uint16_t req_flags, /* Needed for UNICODE ... */
1126 const uint8_t *_in_data,
1128 uint8_t **_out_data,
1129 uint32_t max_out_len,
1132 const char *in_data = (const char *)_in_data;
1133 char **out_data = (char **)_out_data;
1137 case FSCTL_SET_SPARSE:
1139 bool set_sparse = true;
1141 if (in_len >= 1 && in_data[0] == 0) {
1145 status = file_set_sparse(handle->conn, fsp, set_sparse);
1147 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1148 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1149 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1150 nt_errstr(status)));
1155 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1157 unsigned char objid[16];
1158 char *return_data = NULL;
1160 /* This should return the object-id on this file.
1161 * I think I'll make this be the inode+dev. JRA.
1164 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1165 fsp_fnum_dbg(fsp)));
1167 *out_len = MIN(max_out_len, 64);
1169 /* Hmmm, will this cause problems if less data asked for? */
1170 return_data = talloc_array(ctx, char, 64);
1171 if (return_data == NULL) {
1172 return NT_STATUS_NO_MEMORY;
1175 /* For backwards compatibility only store the dev/inode. */
1176 push_file_id_16(return_data, &fsp->file_id);
1177 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1178 push_file_id_16(return_data+32, &fsp->file_id);
1179 memset(return_data+48, 0, 16);
1180 *out_data = return_data;
1181 return NT_STATUS_OK;
1184 case FSCTL_GET_REPARSE_POINT:
1186 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1187 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1188 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1189 return NT_STATUS_NOT_A_REPARSE_POINT;
1192 case FSCTL_SET_REPARSE_POINT:
1194 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1195 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1196 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1197 return NT_STATUS_NOT_A_REPARSE_POINT;
1200 case FSCTL_GET_SHADOW_COPY_DATA:
1203 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1204 * and return their volume names. If max_data_count is 16, then it is just
1205 * asking for the number of volumes and length of the combined names.
1207 * pdata is the data allocated by our caller, but that uses
1208 * total_data_count (which is 0 in our case) rather than max_data_count.
1209 * Allocate the correct amount and return the pointer to let
1210 * it be deallocated when we return.
1212 struct shadow_copy_data *shadow_data = NULL;
1213 bool labels = False;
1214 uint32_t labels_data_count = 0;
1216 char *cur_pdata = NULL;
1218 if (max_out_len < 16) {
1219 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1221 return NT_STATUS_INVALID_PARAMETER;
1224 if (max_out_len > 16) {
1228 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1229 if (shadow_data == NULL) {
1230 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1231 return NT_STATUS_NO_MEMORY;
1235 * Call the VFS routine to actually do the work.
1237 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1240 /* broken module didn't set errno on error */
1241 status = NT_STATUS_UNSUCCESSFUL;
1243 status = map_nt_error_from_unix(errno);
1244 if (NT_STATUS_EQUAL(status,
1245 NT_STATUS_NOT_SUPPORTED)) {
1249 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1250 "connectpath %s, failed - %s.\n",
1251 fsp->conn->connectpath,
1252 nt_errstr(status)));
1253 TALLOC_FREE(shadow_data);
1257 labels_data_count = (shadow_data->num_volumes * 2 *
1258 sizeof(SHADOW_COPY_LABEL)) + 2;
1263 *out_len = 12 + labels_data_count;
1266 if (max_out_len < *out_len) {
1267 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1268 max_out_len, *out_len));
1269 TALLOC_FREE(shadow_data);
1270 return NT_STATUS_BUFFER_TOO_SMALL;
1273 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1274 if (cur_pdata == NULL) {
1275 TALLOC_FREE(shadow_data);
1276 return NT_STATUS_NO_MEMORY;
1279 *out_data = cur_pdata;
1281 /* num_volumes 4 bytes */
1282 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1285 /* num_labels 4 bytes */
1286 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1289 /* needed_data_count 4 bytes */
1290 SIVAL(cur_pdata, 8, labels_data_count);
1294 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1295 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1296 if (labels && shadow_data->labels) {
1297 for (i=0; i<shadow_data->num_volumes; i++) {
1299 status = srvstr_push(cur_pdata, req_flags,
1300 cur_pdata, shadow_data->labels[i],
1301 2 * sizeof(SHADOW_COPY_LABEL),
1302 STR_UNICODE|STR_TERMINATE, &len);
1303 if (!NT_STATUS_IS_OK(status)) {
1304 TALLOC_FREE(*out_data);
1305 TALLOC_FREE(shadow_data);
1308 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1309 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1313 TALLOC_FREE(shadow_data);
1315 return NT_STATUS_OK;
1318 case FSCTL_FIND_FILES_BY_SID:
1320 /* pretend this succeeded -
1322 * we have to send back a list with all files owned by this SID
1324 * but I have to check that --metze
1330 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1331 fsp_fnum_dbg(fsp)));
1334 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1335 return NT_STATUS_INVALID_PARAMETER;
1338 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1340 /* unknown 4 bytes: this is not the length of the sid :-( */
1341 /*unknown = IVAL(pdata,0);*/
1343 if (!sid_parse(_in_data + 4, sid_len, &sid)) {
1344 return NT_STATUS_INVALID_PARAMETER;
1346 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1348 if (!sid_to_uid(&sid, &uid)) {
1349 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1350 sid_string_dbg(&sid),
1351 (unsigned long)sid_len));
1355 /* we can take a look at the find source :-)
1357 * find ./ -uid $uid -name '*' is what we need here
1360 * and send 4bytes len and then NULL terminated unicode strings
1363 * but I don't know how to deal with the paged results
1364 * (maybe we can hang the result anywhere in the fsp struct)
1366 * but I don't know how to deal with the paged results
1367 * (maybe we can hang the result anywhere in the fsp struct)
1369 * we don't send all files at once
1370 * and at the next we should *not* start from the beginning,
1371 * so we have to cache the result
1376 /* this works for now... */
1377 return NT_STATUS_OK;
1380 case FSCTL_QUERY_ALLOCATED_RANGES:
1382 /* FIXME: This is just a dummy reply, telling that all of the
1383 * file is allocated. MKS cp needs that.
1384 * Adding the real allocated ranges via FIEMAP on Linux
1385 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1386 * this FSCTL correct for sparse files.
1388 uint64_t offset, length;
1389 char *out_data_tmp = NULL;
1392 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1394 return NT_STATUS_INVALID_PARAMETER;
1397 if (max_out_len < 16) {
1398 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1400 return NT_STATUS_INVALID_PARAMETER;
1403 offset = BVAL(in_data,0);
1404 length = BVAL(in_data,8);
1406 if (offset + length < offset) {
1407 /* No 64-bit integer wrap. */
1408 return NT_STATUS_INVALID_PARAMETER;
1411 /* Shouldn't this be SMB_VFS_STAT ... ? */
1412 status = vfs_stat_fsp(fsp);
1413 if (!NT_STATUS_IS_OK(status)) {
1418 out_data_tmp = talloc_array(ctx, char, *out_len);
1419 if (out_data_tmp == NULL) {
1420 DEBUG(10, ("unable to allocate memory for response\n"));
1421 return NT_STATUS_NO_MEMORY;
1424 if (offset > fsp->fsp_name->st.st_ex_size ||
1425 fsp->fsp_name->st.st_ex_size == 0 ||
1427 memset(out_data_tmp, 0, *out_len);
1429 uint64_t end = offset + length;
1430 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1431 SBVAL(out_data_tmp, 0, 0);
1432 SBVAL(out_data_tmp, 8, end);
1435 *out_data = out_data_tmp;
1437 return NT_STATUS_OK;
1440 case FSCTL_IS_VOLUME_DIRTY:
1442 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1443 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1445 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1446 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1448 return NT_STATUS_INVALID_PARAMETER;
1453 * Only print once ... unfortunately there could be lots of
1454 * different FSCTLs that are called.
1456 if (!vfswrap_logged_ioctl_message) {
1457 vfswrap_logged_ioctl_message = true;
1458 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1459 __func__, function));
1463 return NT_STATUS_NOT_SUPPORTED;
1466 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
1467 const struct smb_filename *fname,
1468 SMB_STRUCT_STAT *sbuf);
1470 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1471 struct smb_filename *smb_fname,
1476 offline = vfswrap_is_offline(handle, smb_fname, &smb_fname->st);
1478 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1481 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1484 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1485 struct files_struct *fsp,
1490 offline = vfswrap_is_offline(handle, fsp->fsp_name, &fsp->fsp_name->st);
1492 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1495 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1498 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1499 const struct smb_filename *smb_fname,
1502 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1505 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1506 struct files_struct *fsp,
1509 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1512 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1514 struct vfswrap_offload_read_state {
1518 static struct tevent_req *vfswrap_offload_read_send(
1519 TALLOC_CTX *mem_ctx,
1520 struct tevent_context *ev,
1521 struct vfs_handle_struct *handle,
1522 struct files_struct *fsp,
1528 struct tevent_req *req = NULL;
1529 struct vfswrap_offload_read_state *state = NULL;
1532 req = tevent_req_create(mem_ctx, &state,
1533 struct vfswrap_offload_read_state);
1538 status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1539 &vfswrap_offload_ctx);
1540 if (tevent_req_nterror(req, status)) {
1541 return tevent_req_post(req, ev);
1544 if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1545 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1546 return tevent_req_post(req, ev);
1549 status = vfs_offload_token_create_blob(state, fsp, fsctl,
1551 if (tevent_req_nterror(req, status)) {
1552 return tevent_req_post(req, ev);
1555 status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1557 if (tevent_req_nterror(req, status)) {
1558 return tevent_req_post(req, ev);
1561 tevent_req_done(req);
1562 return tevent_req_post(req, ev);
1565 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
1566 struct vfs_handle_struct *handle,
1567 TALLOC_CTX *mem_ctx,
1570 struct vfswrap_offload_read_state *state = tevent_req_data(
1571 req, struct vfswrap_offload_read_state);
1574 if (tevent_req_is_nterror(req, &status)) {
1575 tevent_req_received(req);
1579 token->length = state->token.length;
1580 token->data = talloc_move(mem_ctx, &state->token.data);
1582 tevent_req_received(req);
1583 return NT_STATUS_OK;
1586 struct vfswrap_offload_write_state {
1588 bool read_lck_locked;
1589 bool write_lck_locked;
1591 struct tevent_context *src_ev;
1592 struct files_struct *src_fsp;
1594 struct tevent_context *dst_ev;
1595 struct files_struct *dst_fsp;
1599 size_t next_io_size;
1602 static void vfswrap_offload_write_cleanup(struct tevent_req *req,
1603 enum tevent_req_state req_state)
1605 struct vfswrap_offload_write_state *state = tevent_req_data(
1606 req, struct vfswrap_offload_write_state);
1609 if (state->dst_fsp == NULL) {
1613 ok = change_to_user_by_fsp(state->dst_fsp);
1615 state->dst_fsp = NULL;
1618 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
1620 static struct tevent_req *vfswrap_offload_write_send(
1621 struct vfs_handle_struct *handle,
1622 TALLOC_CTX *mem_ctx,
1623 struct tevent_context *ev,
1626 off_t transfer_offset,
1627 struct files_struct *dest_fsp,
1631 struct tevent_req *req;
1632 struct vfswrap_offload_write_state *state = NULL;
1633 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
1634 files_struct *src_fsp = NULL;
1638 req = tevent_req_create(mem_ctx, &state,
1639 struct vfswrap_offload_write_state);
1644 *state = (struct vfswrap_offload_write_state) {
1646 .src_off = transfer_offset,
1648 .dst_fsp = dest_fsp,
1649 .dst_off = dest_off,
1651 .remaining = to_copy,
1654 tevent_req_set_cleanup_fn(req, vfswrap_offload_write_cleanup);
1657 case FSCTL_SRV_COPYCHUNK:
1658 case FSCTL_SRV_COPYCHUNK_WRITE:
1661 case FSCTL_OFFLOAD_WRITE:
1662 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
1663 return tevent_req_post(req, ev);
1665 case FSCTL_DUP_EXTENTS_TO_FILE:
1666 DBG_DEBUG("COW clones not supported by vfs_default\n");
1667 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1668 return tevent_req_post(req, ev);
1671 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1672 return tevent_req_post(req, ev);
1676 * From here on we assume a copy-chunk fsctl
1680 tevent_req_done(req);
1681 return tevent_req_post(req, ev);
1684 status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
1686 if (tevent_req_nterror(req, status)) {
1687 return tevent_req_post(req, ev);
1690 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
1692 status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
1693 if (!NT_STATUS_IS_OK(status)) {
1694 tevent_req_nterror(req, status);
1695 return tevent_req_post(req, ev);
1698 ok = change_to_user_by_fsp(src_fsp);
1700 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1701 return tevent_req_post(req, ev);
1704 state->src_ev = src_fsp->conn->user_ev_ctx;
1705 state->src_fsp = src_fsp;
1707 state->buf = talloc_array(state, uint8_t, num);
1708 if (tevent_req_nomem(state->buf, req)) {
1709 return tevent_req_post(req, ev);
1712 status = vfs_stat_fsp(src_fsp);
1713 if (tevent_req_nterror(req, status)) {
1714 return tevent_req_post(req, ev);
1717 if (src_fsp->fsp_name->st.st_ex_size < state->src_off + num) {
1719 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1720 * If the SourceOffset or SourceOffset + Length extends beyond
1721 * the end of file, the server SHOULD<240> treat this as a
1722 * STATUS_END_OF_FILE error.
1724 * <240> Section 3.3.5.15.6: Windows servers will return
1725 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1727 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1728 return tevent_req_post(req, ev);
1731 status = vfswrap_offload_write_loop(req);
1732 if (!NT_STATUS_IS_OK(status)) {
1733 tevent_req_nterror(req, status);
1734 return tevent_req_post(req, ev);
1740 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
1742 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
1744 struct vfswrap_offload_write_state *state = tevent_req_data(
1745 req, struct vfswrap_offload_write_state);
1746 struct tevent_req *subreq = NULL;
1747 struct lock_struct read_lck;
1751 * This is called under the context of state->src_fsp.
1754 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
1756 init_strict_lock_struct(state->src_fsp,
1757 state->src_fsp->op->global->open_persistent_id,
1759 state->next_io_size,
1763 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
1767 return NT_STATUS_FILE_LOCK_CONFLICT;
1770 subreq = SMB_VFS_PREAD_SEND(state,
1774 state->next_io_size,
1776 if (subreq == NULL) {
1777 return NT_STATUS_NO_MEMORY;
1779 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
1781 return NT_STATUS_OK;
1784 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
1786 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
1788 struct tevent_req *req = tevent_req_callback_data(
1789 subreq, struct tevent_req);
1790 struct vfswrap_offload_write_state *state = tevent_req_data(
1791 req, struct vfswrap_offload_write_state);
1792 struct vfs_aio_state aio_state;
1793 struct lock_struct write_lck;
1797 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
1798 TALLOC_FREE(subreq);
1800 DBG_ERR("read failed: %s\n", strerror(errno));
1801 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1804 if (nread != state->next_io_size) {
1805 DBG_ERR("Short read, only %zd of %zu\n",
1806 nread, state->next_io_size);
1807 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1811 state->src_off += nread;
1813 ok = change_to_user_by_fsp(state->dst_fsp);
1815 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1819 init_strict_lock_struct(state->dst_fsp,
1820 state->dst_fsp->op->global->open_persistent_id,
1822 state->next_io_size,
1826 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
1830 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1834 subreq = SMB_VFS_PWRITE_SEND(state,
1838 state->next_io_size,
1840 if (subreq == NULL) {
1841 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1844 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
1847 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
1849 struct tevent_req *req = tevent_req_callback_data(
1850 subreq, struct tevent_req);
1851 struct vfswrap_offload_write_state *state = tevent_req_data(
1852 req, struct vfswrap_offload_write_state);
1853 struct vfs_aio_state aio_state;
1858 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
1859 TALLOC_FREE(subreq);
1860 if (nwritten == -1) {
1861 DBG_ERR("write failed: %s\n", strerror(errno));
1862 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1865 if (nwritten != state->next_io_size) {
1866 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
1867 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1871 state->dst_off += nwritten;
1873 if (state->remaining < nwritten) {
1874 /* Paranoia check */
1875 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1878 state->remaining -= nwritten;
1879 if (state->remaining == 0) {
1880 tevent_req_done(req);
1884 ok = change_to_user_by_fsp(state->src_fsp);
1886 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1890 status = vfswrap_offload_write_loop(req);
1891 if (!NT_STATUS_IS_OK(status)) {
1892 tevent_req_nterror(req, status);
1899 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
1900 struct tevent_req *req,
1903 struct vfswrap_offload_write_state *state = tevent_req_data(
1904 req, struct vfswrap_offload_write_state);
1907 if (tevent_req_is_nterror(req, &status)) {
1908 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
1910 tevent_req_received(req);
1914 *copied = state->to_copy;
1915 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
1916 tevent_req_received(req);
1918 return NT_STATUS_OK;
1921 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1922 TALLOC_CTX *mem_ctx,
1923 struct files_struct *fsp,
1924 struct smb_filename *smb_fname,
1925 uint16_t *_compression_fmt)
1927 return NT_STATUS_INVALID_DEVICE_REQUEST;
1930 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1931 TALLOC_CTX *mem_ctx,
1932 struct files_struct *fsp,
1933 uint16_t compression_fmt)
1935 return NT_STATUS_INVALID_DEVICE_REQUEST;
1938 /********************************************************************
1939 Given a stat buffer return the allocated size on disk, taking into
1940 account sparse files.
1941 ********************************************************************/
1942 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1943 struct files_struct *fsp,
1944 const SMB_STRUCT_STAT *sbuf)
1948 START_PROFILE(syscall_get_alloc_size);
1950 if(S_ISDIR(sbuf->st_ex_mode)) {
1955 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1956 /* The type of st_blocksize is blkcnt_t which *MUST* be
1957 signed (according to POSIX) and can be less than 64-bits.
1958 Ensure when we're converting to 64 bits wide we don't
1960 #if defined(SIZEOF_BLKCNT_T_8)
1961 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1962 #elif defined(SIZEOF_BLKCNT_T_4)
1964 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1965 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1968 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1972 * Some file systems do not allocate a block for very
1973 * small files. But for non-empty file should report a
1977 uint64_t filesize = get_file_size_stat(sbuf);
1979 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
1983 result = get_file_size_stat(sbuf);
1986 if (fsp && fsp->initial_allocation_size)
1987 result = MAX(result,fsp->initial_allocation_size);
1989 result = smb_roundup(handle->conn, result);
1992 END_PROFILE(syscall_get_alloc_size);
1996 static int vfswrap_unlink(vfs_handle_struct *handle,
1997 const struct smb_filename *smb_fname)
2001 START_PROFILE(syscall_unlink);
2003 if (smb_fname->stream_name) {
2007 result = unlink(smb_fname->base_name);
2010 END_PROFILE(syscall_unlink);
2014 static int vfswrap_chmod(vfs_handle_struct *handle,
2015 const struct smb_filename *smb_fname,
2020 START_PROFILE(syscall_chmod);
2021 result = chmod(smb_fname->base_name, mode);
2022 END_PROFILE(syscall_chmod);
2026 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2030 START_PROFILE(syscall_fchmod);
2031 #if defined(HAVE_FCHMOD)
2032 result = fchmod(fsp->fh->fd, mode);
2038 END_PROFILE(syscall_fchmod);
2042 static int vfswrap_chown(vfs_handle_struct *handle,
2043 const struct smb_filename *smb_fname,
2049 START_PROFILE(syscall_chown);
2050 result = chown(smb_fname->base_name, uid, gid);
2051 END_PROFILE(syscall_chown);
2055 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2060 START_PROFILE(syscall_fchown);
2061 result = fchown(fsp->fh->fd, uid, gid);
2062 END_PROFILE(syscall_fchown);
2070 static int vfswrap_lchown(vfs_handle_struct *handle,
2071 const struct smb_filename *smb_fname,
2077 START_PROFILE(syscall_lchown);
2078 result = lchown(smb_fname->base_name, uid, gid);
2079 END_PROFILE(syscall_lchown);
2083 static int vfswrap_chdir(vfs_handle_struct *handle,
2084 const struct smb_filename *smb_fname)
2088 START_PROFILE(syscall_chdir);
2089 result = chdir(smb_fname->base_name);
2090 END_PROFILE(syscall_chdir);
2094 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2098 struct smb_filename *smb_fname = NULL;
2100 START_PROFILE(syscall_getwd);
2101 result = sys_getwd();
2102 END_PROFILE(syscall_getwd);
2104 if (result == NULL) {
2107 smb_fname = synthetic_smb_fname(ctx,
2113 * sys_getwd() *always* returns malloced memory.
2114 * We must free here to avoid leaks:
2115 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2121 /*********************************************************************
2122 nsec timestamp resolution call. Convert down to whatever the underlying
2123 system will support.
2124 **********************************************************************/
2126 static int vfswrap_ntimes(vfs_handle_struct *handle,
2127 const struct smb_filename *smb_fname,
2128 struct smb_file_time *ft)
2132 START_PROFILE(syscall_ntimes);
2134 if (smb_fname->stream_name) {
2140 if (null_timespec(ft->atime)) {
2141 ft->atime= smb_fname->st.st_ex_atime;
2144 if (null_timespec(ft->mtime)) {
2145 ft->mtime = smb_fname->st.st_ex_mtime;
2148 if (!null_timespec(ft->create_time)) {
2149 set_create_timespec_ea(handle->conn,
2154 if ((timespec_compare(&ft->atime,
2155 &smb_fname->st.st_ex_atime) == 0) &&
2156 (timespec_compare(&ft->mtime,
2157 &smb_fname->st.st_ex_mtime) == 0)) {
2162 #if defined(HAVE_UTIMENSAT)
2164 struct timespec ts[2];
2167 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2169 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2171 if (!((result == -1) && (errno == ENOSYS))) {
2175 #if defined(HAVE_UTIMES)
2177 struct timeval tv[2];
2178 tv[0] = convert_timespec_to_timeval(ft->atime);
2179 tv[1] = convert_timespec_to_timeval(ft->mtime);
2180 result = utimes(smb_fname->base_name, tv);
2182 result = utimes(smb_fname->base_name, NULL);
2184 if (!((result == -1) && (errno == ENOSYS))) {
2188 #if defined(HAVE_UTIME)
2190 struct utimbuf times;
2191 times.actime = convert_timespec_to_time_t(ft->atime);
2192 times.modtime = convert_timespec_to_time_t(ft->mtime);
2193 result = utime(smb_fname->base_name, ×);
2195 result = utime(smb_fname->base_name, NULL);
2197 if (!((result == -1) && (errno == ENOSYS))) {
2205 END_PROFILE(syscall_ntimes);
2209 /*********************************************************************
2210 A version of ftruncate that will write the space on disk if strict
2212 **********************************************************************/
2214 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2216 off_t space_to_write;
2217 uint64_t space_avail;
2218 uint64_t bsize,dfree,dsize;
2221 SMB_STRUCT_STAT *pst;
2223 status = vfs_stat_fsp(fsp);
2224 if (!NT_STATUS_IS_OK(status)) {
2227 pst = &fsp->fsp_name->st;
2230 if (S_ISFIFO(pst->st_ex_mode))
2234 if (pst->st_ex_size == len)
2237 /* Shrink - just ftruncate. */
2238 if (pst->st_ex_size > len)
2239 return ftruncate(fsp->fh->fd, len);
2241 space_to_write = len - pst->st_ex_size;
2243 /* for allocation try fallocate first. This can fail on some
2244 platforms e.g. when the filesystem doesn't support it and no
2245 emulation is being done by the libc (like on AIX with JFS1). In that
2246 case we do our own emulation. fallocate implementations can
2247 return ENOTSUP or EINVAL in cases like that. */
2248 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2249 if (ret == -1 && errno == ENOSPC) {
2255 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2256 "error %d. Falling back to slow manual allocation\n", errno));
2258 /* available disk space is enough or not? */
2260 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2261 /* space_avail is 1k blocks */
2262 if (space_avail == (uint64_t)-1 ||
2263 ((uint64_t)space_to_write/1024 > space_avail) ) {
2268 /* Write out the real space on disk. */
2269 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2277 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2280 SMB_STRUCT_STAT *pst;
2284 START_PROFILE(syscall_ftruncate);
2286 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2287 result = strict_allocate_ftruncate(handle, fsp, len);
2288 END_PROFILE(syscall_ftruncate);
2292 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2293 ftruncate if the system supports it. Then I discovered that
2294 you can have some filesystems that support ftruncate
2295 expansion and some that don't! On Linux fat can't do
2296 ftruncate extend but ext2 can. */
2298 result = ftruncate(fsp->fh->fd, len);
2300 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2301 extend a file with ftruncate. Provide alternate implementation
2304 /* Do an fstat to see if the file is longer than the requested
2305 size in which case the ftruncate above should have
2306 succeeded or shorter, in which case seek to len - 1 and
2307 write 1 byte of zero */
2308 status = vfs_stat_fsp(fsp);
2309 if (!NT_STATUS_IS_OK(status)) {
2313 /* We need to update the files_struct after successful ftruncate */
2318 pst = &fsp->fsp_name->st;
2321 if (S_ISFIFO(pst->st_ex_mode)) {
2327 if (pst->st_ex_size == len) {
2332 if (pst->st_ex_size > len) {
2333 /* the ftruncate should have worked */
2337 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2345 END_PROFILE(syscall_ftruncate);
2349 static int vfswrap_fallocate(vfs_handle_struct *handle,
2357 START_PROFILE(syscall_fallocate);
2359 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2361 * posix_fallocate returns 0 on success, errno on error
2362 * and doesn't set errno. Make it behave like fallocate()
2363 * which returns -1, and sets errno on failure.
2370 /* sys_fallocate handles filtering of unsupported mode flags */
2371 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2373 END_PROFILE(syscall_fallocate);
2377 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2381 START_PROFILE(syscall_fcntl_lock);
2383 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2385 "force process locks",
2387 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2390 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2391 END_PROFILE(syscall_fcntl_lock);
2395 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2396 uint32_t share_mode, uint32_t access_mask)
2398 START_PROFILE(syscall_kernel_flock);
2399 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2400 END_PROFILE(syscall_kernel_flock);
2404 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2409 START_PROFILE(syscall_fcntl_getlock);
2411 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2413 "force process locks",
2415 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2418 result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2419 END_PROFILE(syscall_fcntl_getlock);
2423 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2428 START_PROFILE(syscall_linux_setlease);
2430 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2431 result = linux_setlease(fsp->fh->fd, leasetype);
2435 END_PROFILE(syscall_linux_setlease);
2439 static int vfswrap_symlink(vfs_handle_struct *handle,
2440 const char *link_target,
2441 const struct smb_filename *new_smb_fname)
2445 START_PROFILE(syscall_symlink);
2446 result = symlink(link_target, new_smb_fname->base_name);
2447 END_PROFILE(syscall_symlink);
2451 static int vfswrap_readlink(vfs_handle_struct *handle,
2452 const struct smb_filename *smb_fname,
2458 START_PROFILE(syscall_readlink);
2459 result = readlink(smb_fname->base_name, buf, bufsiz);
2460 END_PROFILE(syscall_readlink);
2464 static int vfswrap_link(vfs_handle_struct *handle,
2465 const struct smb_filename *old_smb_fname,
2466 const struct smb_filename *new_smb_fname)
2470 START_PROFILE(syscall_link);
2471 result = link(old_smb_fname->base_name, new_smb_fname->base_name);
2472 END_PROFILE(syscall_link);
2476 static int vfswrap_mknod(vfs_handle_struct *handle,
2477 const struct smb_filename *smb_fname,
2483 START_PROFILE(syscall_mknod);
2484 result = sys_mknod(smb_fname->base_name, mode, dev);
2485 END_PROFILE(syscall_mknod);
2489 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2491 const struct smb_filename *smb_fname)
2494 struct smb_filename *result_fname = NULL;
2496 START_PROFILE(syscall_realpath);
2497 result = sys_realpath(smb_fname->base_name);
2498 END_PROFILE(syscall_realpath);
2500 result_fname = synthetic_smb_fname(ctx, result, NULL, NULL, 0);
2503 return result_fname;
2506 static int vfswrap_chflags(vfs_handle_struct *handle,
2507 const struct smb_filename *smb_fname,
2511 return chflags(smb_fname->base_name, flags);
2518 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2519 const SMB_STRUCT_STAT *sbuf)
2523 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2527 key.devid = sbuf->st_ex_dev;
2528 key.inode = sbuf->st_ex_ino;
2529 /* key.extid is unused by default. */
2534 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2535 struct files_struct *fsp,
2536 const struct smb_filename *smb_fname,
2537 TALLOC_CTX *mem_ctx,
2538 unsigned int *pnum_streams,
2539 struct stream_struct **pstreams)
2541 SMB_STRUCT_STAT sbuf;
2542 struct stream_struct *tmp_streams = NULL;
2545 if ((fsp != NULL) && (fsp->is_directory)) {
2547 * No default streams on directories
2552 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2553 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2556 struct smb_filename smb_fname_cp;
2558 ZERO_STRUCT(smb_fname_cp);
2559 smb_fname_cp.base_name = discard_const_p(char,
2560 smb_fname->base_name);
2561 smb_fname_cp.flags = smb_fname->flags;
2563 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
2564 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2566 ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2568 sbuf = smb_fname_cp.st;
2572 return map_nt_error_from_unix(errno);
2575 if (S_ISDIR(sbuf.st_ex_mode)) {
2579 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2580 (*pnum_streams) + 1);
2581 if (tmp_streams == NULL) {
2582 return NT_STATUS_NO_MEMORY;
2584 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2585 if (tmp_streams[*pnum_streams].name == NULL) {
2586 return NT_STATUS_NO_MEMORY;
2588 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2589 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2592 *pstreams = tmp_streams;
2594 return NT_STATUS_OK;
2597 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2600 TALLOC_CTX *mem_ctx,
2604 * Don't fall back to get_real_filename so callers can differentiate
2605 * between a full directory scan and an actual case-insensitive stat.
2611 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2612 const struct smb_filename *smb_fname)
2614 return handle->conn->connectpath;
2617 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2618 struct byte_range_lock *br_lck,
2619 struct lock_struct *plock,
2622 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2624 /* Note: blr is not used in the default implementation. */
2625 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2628 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2629 struct messaging_context *msg_ctx,
2630 struct byte_range_lock *br_lck,
2631 const struct lock_struct *plock)
2633 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2635 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2638 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2639 struct byte_range_lock *br_lck,
2640 struct lock_struct *plock)
2642 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2644 /* Note: blr is not used in the default implementation. */
2645 return brl_lock_cancel_default(br_lck, plock);
2648 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
2650 struct lock_struct *plock)
2652 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2653 plock->lock_type == WRITE_LOCK);
2655 return strict_lock_check_default(fsp, plock);
2658 /* NT ACL operations. */
2660 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2662 uint32_t security_info,
2663 TALLOC_CTX *mem_ctx,
2664 struct security_descriptor **ppdesc)
2668 START_PROFILE(fget_nt_acl);
2669 result = posix_fget_nt_acl(fsp, security_info,
2671 END_PROFILE(fget_nt_acl);
2675 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2676 const struct smb_filename *smb_fname,
2677 uint32_t security_info,
2678 TALLOC_CTX *mem_ctx,
2679 struct security_descriptor **ppdesc)
2683 START_PROFILE(get_nt_acl);
2684 result = posix_get_nt_acl(handle->conn,
2689 END_PROFILE(get_nt_acl);
2693 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2697 START_PROFILE(fset_nt_acl);
2698 result = set_nt_acl(fsp, security_info_sent, psd);
2699 END_PROFILE(fset_nt_acl);
2703 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2704 struct smb_filename *file,
2705 struct security_acl *sacl,
2706 uint32_t access_requested,
2707 uint32_t access_denied)
2709 return NT_STATUS_OK; /* Nothing to do here ... */
2712 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2713 const struct smb_filename *smb_fname,
2714 SMB_ACL_TYPE_T type,
2715 TALLOC_CTX *mem_ctx)
2717 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
2720 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2722 TALLOC_CTX *mem_ctx)
2724 return sys_acl_get_fd(handle, fsp, mem_ctx);
2727 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
2728 const struct smb_filename *smb_fname,
2729 SMB_ACL_TYPE_T acltype,
2732 return sys_acl_set_file(handle, smb_fname, acltype, theacl);
2735 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2737 return sys_acl_set_fd(handle, fsp, theacl);
2740 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
2741 const struct smb_filename *smb_fname)
2743 return sys_acl_delete_def_file(handle, smb_fname);
2746 /****************************************************************
2747 Extended attribute operations.
2748 *****************************************************************/
2750 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
2751 const struct smb_filename *smb_fname,
2756 return getxattr(smb_fname->base_name, name, value, size);
2759 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2761 return fgetxattr(fsp->fh->fd, name, value, size);
2764 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
2765 const struct smb_filename *smb_fname,
2769 return listxattr(smb_fname->base_name, list, size);
2772 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2774 return flistxattr(fsp->fh->fd, list, size);
2777 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
2778 const struct smb_filename *smb_fname,
2781 return removexattr(smb_fname->base_name, name);
2784 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2786 return fremovexattr(fsp->fh->fd, name);
2789 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
2790 const struct smb_filename *smb_fname,
2796 return setxattr(smb_fname->base_name, name, value, size, flags);
2799 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2801 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2804 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2809 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2810 const struct smb_filename *fname,
2811 SMB_STRUCT_STAT *sbuf)
2815 bool offline = false;
2817 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2821 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2822 #if defined(ENOTSUP)
2828 status = get_full_smb_filename(talloc_tos(), fname, &path);
2829 if (!NT_STATUS_IS_OK(status)) {
2830 errno = map_errno_from_nt_status(status);
2834 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2841 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2842 struct files_struct *fsp,
2843 TALLOC_CTX *mem_ctx,
2846 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2849 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2850 struct files_struct *fsp,
2851 const DATA_BLOB old_cookie,
2852 TALLOC_CTX *mem_ctx,
2853 DATA_BLOB *new_cookie)
2855 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2859 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2860 struct smb_request *smb1req,
2861 struct smbXsrv_open *op,
2862 const DATA_BLOB old_cookie,
2863 TALLOC_CTX *mem_ctx,
2864 struct files_struct **fsp,
2865 DATA_BLOB *new_cookie)
2867 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2868 old_cookie, mem_ctx,
2872 static struct vfs_fn_pointers vfs_default_fns = {
2873 /* Disk operations */
2875 .connect_fn = vfswrap_connect,
2876 .disconnect_fn = vfswrap_disconnect,
2877 .disk_free_fn = vfswrap_disk_free,
2878 .get_quota_fn = vfswrap_get_quota,
2879 .set_quota_fn = vfswrap_set_quota,
2880 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2881 .statvfs_fn = vfswrap_statvfs,
2882 .fs_capabilities_fn = vfswrap_fs_capabilities,
2883 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2884 .snap_check_path_fn = vfswrap_snap_check_path,
2885 .snap_create_fn = vfswrap_snap_create,
2886 .snap_delete_fn = vfswrap_snap_delete,
2888 /* Directory operations */
2890 .opendir_fn = vfswrap_opendir,
2891 .fdopendir_fn = vfswrap_fdopendir,
2892 .readdir_fn = vfswrap_readdir,
2893 .readdir_attr_fn = vfswrap_readdir_attr,
2894 .seekdir_fn = vfswrap_seekdir,
2895 .telldir_fn = vfswrap_telldir,
2896 .rewind_dir_fn = vfswrap_rewinddir,
2897 .mkdir_fn = vfswrap_mkdir,
2898 .rmdir_fn = vfswrap_rmdir,
2899 .closedir_fn = vfswrap_closedir,
2901 /* File operations */
2903 .open_fn = vfswrap_open,
2904 .create_file_fn = vfswrap_create_file,
2905 .close_fn = vfswrap_close,
2906 .pread_fn = vfswrap_pread,
2907 .pread_send_fn = vfswrap_pread_send,
2908 .pread_recv_fn = vfswrap_pread_recv,
2909 .pwrite_fn = vfswrap_pwrite,
2910 .pwrite_send_fn = vfswrap_pwrite_send,
2911 .pwrite_recv_fn = vfswrap_pwrite_recv,
2912 .lseek_fn = vfswrap_lseek,
2913 .sendfile_fn = vfswrap_sendfile,
2914 .recvfile_fn = vfswrap_recvfile,
2915 .rename_fn = vfswrap_rename,
2916 .fsync_send_fn = vfswrap_fsync_send,
2917 .fsync_recv_fn = vfswrap_fsync_recv,
2918 .stat_fn = vfswrap_stat,
2919 .fstat_fn = vfswrap_fstat,
2920 .lstat_fn = vfswrap_lstat,
2921 .get_alloc_size_fn = vfswrap_get_alloc_size,
2922 .unlink_fn = vfswrap_unlink,
2923 .chmod_fn = vfswrap_chmod,
2924 .fchmod_fn = vfswrap_fchmod,
2925 .chown_fn = vfswrap_chown,
2926 .fchown_fn = vfswrap_fchown,
2927 .lchown_fn = vfswrap_lchown,
2928 .chdir_fn = vfswrap_chdir,
2929 .getwd_fn = vfswrap_getwd,
2930 .ntimes_fn = vfswrap_ntimes,
2931 .ftruncate_fn = vfswrap_ftruncate,
2932 .fallocate_fn = vfswrap_fallocate,
2933 .lock_fn = vfswrap_lock,
2934 .kernel_flock_fn = vfswrap_kernel_flock,
2935 .linux_setlease_fn = vfswrap_linux_setlease,
2936 .getlock_fn = vfswrap_getlock,
2937 .symlink_fn = vfswrap_symlink,
2938 .readlink_fn = vfswrap_readlink,
2939 .link_fn = vfswrap_link,
2940 .mknod_fn = vfswrap_mknod,
2941 .realpath_fn = vfswrap_realpath,
2942 .chflags_fn = vfswrap_chflags,
2943 .file_id_create_fn = vfswrap_file_id_create,
2944 .streaminfo_fn = vfswrap_streaminfo,
2945 .get_real_filename_fn = vfswrap_get_real_filename,
2946 .connectpath_fn = vfswrap_connectpath,
2947 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2948 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2949 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2950 .strict_lock_check_fn = vfswrap_strict_lock_check,
2951 .translate_name_fn = vfswrap_translate_name,
2952 .fsctl_fn = vfswrap_fsctl,
2953 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
2954 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
2955 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
2956 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
2957 .offload_read_send_fn = vfswrap_offload_read_send,
2958 .offload_read_recv_fn = vfswrap_offload_read_recv,
2959 .offload_write_send_fn = vfswrap_offload_write_send,
2960 .offload_write_recv_fn = vfswrap_offload_write_recv,
2961 .get_compression_fn = vfswrap_get_compression,
2962 .set_compression_fn = vfswrap_set_compression,
2964 /* NT ACL operations. */
2966 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2967 .get_nt_acl_fn = vfswrap_get_nt_acl,
2968 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2969 .audit_file_fn = vfswrap_audit_file,
2971 /* POSIX ACL operations. */
2973 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2974 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2975 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2976 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2977 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2978 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2979 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2981 /* EA operations. */
2982 .getxattr_fn = vfswrap_getxattr,
2983 .fgetxattr_fn = vfswrap_fgetxattr,
2984 .listxattr_fn = vfswrap_listxattr,
2985 .flistxattr_fn = vfswrap_flistxattr,
2986 .removexattr_fn = vfswrap_removexattr,
2987 .fremovexattr_fn = vfswrap_fremovexattr,
2988 .setxattr_fn = vfswrap_setxattr,
2989 .fsetxattr_fn = vfswrap_fsetxattr,
2991 /* aio operations */
2992 .aio_force_fn = vfswrap_aio_force,
2994 /* durable handle operations */
2995 .durable_cookie_fn = vfswrap_durable_cookie,
2996 .durable_disconnect_fn = vfswrap_durable_disconnect,
2997 .durable_reconnect_fn = vfswrap_durable_reconnect,
3001 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3004 * Here we need to implement every call!
3006 * As this is the end of the vfs module chain.
3008 smb_vfs_assert_all_fns(&vfs_default_fns, DEFAULT_VFS_MODULE_NAME);
3009 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3010 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);