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"
39 #define DBGC_CLASS DBGC_VFS
41 /* Check for NULL pointer parameters in vfswrap_* functions */
43 /* We don't want to have NULL function pointers lying around. Someone
44 is sure to try and execute them. These stubs are used to prevent
47 static int vfswrap_connect(vfs_handle_struct *handle, const char *service, const char *user)
49 return 0; /* Return >= 0 for success */
52 static void vfswrap_disconnect(vfs_handle_struct *handle)
58 static uint64_t vfswrap_disk_free(vfs_handle_struct *handle, const char *path,
59 uint64_t *bsize, uint64_t *dfree,
62 if (sys_fsusage(path, dfree, dsize) != 0) {
70 static int vfswrap_get_quota(struct vfs_handle_struct *handle, const char *path,
71 enum SMB_QUOTA_TYPE qtype, unid_t id,
74 #ifdef HAVE_SYS_QUOTAS
77 START_PROFILE(syscall_get_quota);
78 result = sys_get_quota(path, qtype, id, qt);
79 END_PROFILE(syscall_get_quota);
87 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
89 #ifdef HAVE_SYS_QUOTAS
92 START_PROFILE(syscall_set_quota);
93 result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
94 END_PROFILE(syscall_set_quota);
102 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
103 struct files_struct *fsp,
104 struct shadow_copy_data *shadow_copy_data,
108 return -1; /* Not implemented. */
111 static int vfswrap_statvfs(struct vfs_handle_struct *handle, const char *path, vfs_statvfs_struct *statbuf)
113 return sys_statvfs(path, statbuf);
116 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
117 enum timestamp_set_resolution *p_ts_res)
119 connection_struct *conn = handle->conn;
120 uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
121 struct smb_filename *smb_fname_cpath = NULL;
122 struct vfs_statvfs_struct statbuf;
125 ZERO_STRUCT(statbuf);
126 ret = sys_statvfs(conn->connectpath, &statbuf);
128 caps = statbuf.FsCapabilities;
131 *p_ts_res = TIMESTAMP_SET_SECONDS;
133 /* Work out what timestamp resolution we can
134 * use when setting a timestamp. */
136 smb_fname_cpath = synthetic_smb_fname(talloc_tos(), conn->connectpath,
138 if (smb_fname_cpath == NULL) {
142 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
144 TALLOC_FREE(smb_fname_cpath);
148 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
149 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
150 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
151 /* If any of the normal UNIX directory timestamps
152 * have a non-zero tv_nsec component assume
153 * we might be able to set sub-second timestamps.
154 * See what filetime set primitives we have.
156 #if defined(HAVE_UTIMENSAT)
157 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
158 #elif defined(HAVE_UTIMES)
159 /* utimes allows msec timestamps to be set. */
160 *p_ts_res = TIMESTAMP_SET_MSEC;
161 #elif defined(HAVE_UTIME)
162 /* utime only allows sec timestamps to be set. */
163 *p_ts_res = TIMESTAMP_SET_SECONDS;
166 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
168 "available on share %s, directory %s\n",
169 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
170 lp_servicename(talloc_tos(), conn->params->service),
171 conn->connectpath ));
173 TALLOC_FREE(smb_fname_cpath);
177 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
178 struct dfs_GetDFSReferral *r)
180 struct junction_map *junction = NULL;
182 bool self_referral = false;
183 char *pathnamep = NULL;
184 char *local_dfs_path = NULL;
187 uint16_t max_referral_level = r->in.req.max_referral_level;
190 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
193 /* get the junction entry */
194 if (r->in.req.servername == NULL) {
195 return NT_STATUS_NOT_FOUND;
199 * Trim pathname sent by client so it begins with only one backslash.
200 * Two backslashes confuse some dfs clients
203 local_dfs_path = talloc_strdup(r, r->in.req.servername);
204 if (local_dfs_path == NULL) {
205 return NT_STATUS_NO_MEMORY;
207 pathnamep = local_dfs_path;
208 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
209 IS_DIRECTORY_SEP(pathnamep[1])) {
213 junction = talloc_zero(r, struct junction_map);
214 if (junction == NULL) {
215 return NT_STATUS_NO_MEMORY;
218 /* The following call can change cwd. */
219 status = get_referred_path(r, pathnamep,
220 !handle->conn->sconn->using_smb2,
221 junction, &consumedcnt, &self_referral);
222 if (!NT_STATUS_IS_OK(status)) {
223 vfs_ChDir(handle->conn, handle->conn->connectpath);
226 vfs_ChDir(handle->conn, handle->conn->connectpath);
228 if (!self_referral) {
229 pathnamep[consumedcnt] = '\0';
232 dbgtext("Path %s to alternate path(s):",
234 for (i=0; i < junction->referral_count; i++) {
236 junction->referral_list[i].alternate_path);
242 if (r->in.req.max_referral_level <= 2) {
243 max_referral_level = 2;
245 if (r->in.req.max_referral_level >= 3) {
246 max_referral_level = 3;
249 r->out.resp = talloc_zero(r, struct dfs_referral_resp);
250 if (r->out.resp == NULL) {
251 return NT_STATUS_NO_MEMORY;
254 r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
255 r->out.resp->nb_referrals = junction->referral_count;
257 r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
259 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
262 r->out.resp->referral_entries = talloc_zero_array(r,
263 struct dfs_referral_type,
264 r->out.resp->nb_referrals);
265 if (r->out.resp->referral_entries == NULL) {
266 return NT_STATUS_NO_MEMORY;
269 switch (max_referral_level) {
271 for(i=0; i < junction->referral_count; i++) {
272 struct referral *ref = &junction->referral_list[i];
273 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
274 struct dfs_referral_type *t =
275 &r->out.resp->referral_entries[i];
276 struct dfs_referral_v2 *v2 = &t->referral.v2;
279 v2->size = VERSION2_REFERRAL_SIZE;
281 v2->server_type = DFS_SERVER_ROOT;
283 v2->server_type = DFS_SERVER_NON_ROOT;
286 v2->proximity = ref->proximity;
288 v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
289 if (v2->DFS_path == NULL) {
290 return NT_STATUS_NO_MEMORY;
292 v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
293 if (v2->DFS_alt_path == NULL) {
294 return NT_STATUS_NO_MEMORY;
296 v2->netw_address = talloc_strdup(mem_ctx,
297 ref->alternate_path);
298 if (v2->netw_address == NULL) {
299 return NT_STATUS_NO_MEMORY;
305 for(i=0; i < junction->referral_count; i++) {
306 struct referral *ref = &junction->referral_list[i];
307 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
308 struct dfs_referral_type *t =
309 &r->out.resp->referral_entries[i];
310 struct dfs_referral_v3 *v3 = &t->referral.v3;
311 struct dfs_normal_referral *r1 = &v3->referrals.r1;
314 v3->size = VERSION3_REFERRAL_SIZE;
316 v3->server_type = DFS_SERVER_ROOT;
318 v3->server_type = DFS_SERVER_NON_ROOT;
322 r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
323 if (r1->DFS_path == NULL) {
324 return NT_STATUS_NO_MEMORY;
326 r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
327 if (r1->DFS_alt_path == NULL) {
328 return NT_STATUS_NO_MEMORY;
330 r1->netw_address = talloc_strdup(mem_ctx,
331 ref->alternate_path);
332 if (r1->netw_address == NULL) {
333 return NT_STATUS_NO_MEMORY;
338 DEBUG(0,("Invalid dfs referral version: %d\n",
339 max_referral_level));
340 return NT_STATUS_INVALID_LEVEL;
344 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
350 static NTSTATUS vfswrap_snap_check_path(struct vfs_handle_struct *handle,
352 const char *service_path,
355 return NT_STATUS_NOT_SUPPORTED;
358 static NTSTATUS vfswrap_snap_create(struct vfs_handle_struct *handle,
360 const char *base_volume,
366 return NT_STATUS_NOT_SUPPORTED;
369 static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle,
374 return NT_STATUS_NOT_SUPPORTED;
377 /* Directory operations */
379 static DIR *vfswrap_opendir(vfs_handle_struct *handle,
380 const struct smb_filename *smb_fname,
386 START_PROFILE(syscall_opendir);
387 result = opendir(smb_fname->base_name);
388 END_PROFILE(syscall_opendir);
392 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
399 START_PROFILE(syscall_fdopendir);
400 result = sys_fdopendir(fsp->fh->fd);
401 END_PROFILE(syscall_fdopendir);
406 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
408 SMB_STRUCT_STAT *sbuf)
410 struct dirent *result;
412 START_PROFILE(syscall_readdir);
413 result = readdir(dirp);
414 END_PROFILE(syscall_readdir);
416 /* Default Posix readdir() does not give us stat info.
417 * Set to invalid to indicate we didn't return this info. */
418 SET_STAT_INVALID(*sbuf);
419 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
420 if (result != NULL) {
421 /* See if we can efficiently return this. */
423 int flags = AT_SYMLINK_NOFOLLOW;
424 int ret = fstatat(dirfd(dirp),
429 * As this is an optimization,
430 * ignore it if we stat'ed a
431 * symlink. Make the caller
432 * do it again as we don't
433 * know if they wanted the link
434 * info, or its target info.
436 if ((ret == 0) && (!S_ISLNK(st.st_mode))) {
437 init_stat_ex_from_stat(sbuf,
439 lp_fake_directory_create_times(
440 SNUM(handle->conn)));
448 static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
449 const struct smb_filename *fname,
451 struct readdir_attr_data **attr_data)
453 return NT_STATUS_NOT_SUPPORTED;
456 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
458 START_PROFILE(syscall_seekdir);
459 seekdir(dirp, offset);
460 END_PROFILE(syscall_seekdir);
463 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
466 START_PROFILE(syscall_telldir);
467 result = telldir(dirp);
468 END_PROFILE(syscall_telldir);
472 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
474 START_PROFILE(syscall_rewinddir);
476 END_PROFILE(syscall_rewinddir);
479 static int vfswrap_mkdir(vfs_handle_struct *handle,
480 const struct smb_filename *smb_fname,
484 bool has_dacl = False;
485 const char *path = smb_fname->base_name;
488 START_PROFILE(syscall_mkdir);
490 if (lp_inherit_acls(SNUM(handle->conn))
491 && parent_dirname(talloc_tos(), path, &parent, NULL)
492 && (has_dacl = directory_has_default_acl(handle->conn, parent))) {
493 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
498 result = mkdir(path, mode);
500 if (result == 0 && !has_dacl) {
502 * We need to do this as the default behavior of POSIX ACLs
503 * is to set the mask to be the requested group permission
504 * bits, not the group permission bits to be the requested
505 * group permission bits. This is not what we want, as it will
506 * mess up any inherited ACL bits that were set. JRA.
508 int saved_errno = errno; /* We may get ENOSYS */
509 if ((SMB_VFS_CHMOD_ACL(handle->conn, smb_fname, mode) == -1) &&
515 END_PROFILE(syscall_mkdir);
519 static int vfswrap_rmdir(vfs_handle_struct *handle,
520 const struct smb_filename *smb_fname)
524 START_PROFILE(syscall_rmdir);
525 result = rmdir(smb_fname->base_name);
526 END_PROFILE(syscall_rmdir);
530 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
534 START_PROFILE(syscall_closedir);
535 result = closedir(dirp);
536 END_PROFILE(syscall_closedir);
540 static void vfswrap_init_search_op(vfs_handle_struct *handle,
543 /* Default behavior is a NOOP */
546 /* File operations */
548 static int vfswrap_open(vfs_handle_struct *handle,
549 struct smb_filename *smb_fname,
550 files_struct *fsp, int flags, mode_t mode)
554 START_PROFILE(syscall_open);
556 if (smb_fname->stream_name) {
561 result = open(smb_fname->base_name, flags, mode);
563 END_PROFILE(syscall_open);
567 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
568 struct smb_request *req,
569 uint16_t root_dir_fid,
570 struct smb_filename *smb_fname,
571 uint32_t access_mask,
572 uint32_t share_access,
573 uint32_t create_disposition,
574 uint32_t create_options,
575 uint32_t file_attributes,
576 uint32_t oplock_request,
577 struct smb2_lease *lease,
578 uint64_t allocation_size,
579 uint32_t private_flags,
580 struct security_descriptor *sd,
581 struct ea_list *ea_list,
582 files_struct **result,
584 const struct smb2_create_blobs *in_context_blobs,
585 struct smb2_create_blobs *out_context_blobs)
587 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
588 access_mask, share_access,
589 create_disposition, create_options,
590 file_attributes, oplock_request, lease,
591 allocation_size, private_flags,
593 pinfo, in_context_blobs, out_context_blobs);
596 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
600 START_PROFILE(syscall_close);
601 result = fd_close_posix(fsp);
602 END_PROFILE(syscall_close);
606 static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
610 START_PROFILE_BYTES(syscall_read, n);
611 result = sys_read(fsp->fh->fd, data, n);
612 END_PROFILE_BYTES(syscall_read);
616 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
617 size_t n, off_t offset)
621 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
622 START_PROFILE_BYTES(syscall_pread, n);
623 result = sys_pread(fsp->fh->fd, data, n, offset);
624 END_PROFILE_BYTES(syscall_pread);
626 if (result == -1 && errno == ESPIPE) {
627 /* Maintain the fiction that pipes can be seeked (sought?) on. */
628 result = SMB_VFS_READ(fsp, data, n);
632 #else /* HAVE_PREAD */
636 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
637 if (curr == -1 && errno == ESPIPE) {
638 /* Maintain the fiction that pipes can be seeked (sought?) on. */
639 result = SMB_VFS_READ(fsp, data, n);
644 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
649 result = SMB_VFS_READ(fsp, data, n);
652 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
655 #endif /* HAVE_PREAD */
660 static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
664 START_PROFILE_BYTES(syscall_write, n);
665 result = sys_write(fsp->fh->fd, data, n);
666 END_PROFILE_BYTES(syscall_write);
670 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
671 size_t n, off_t offset)
675 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
676 START_PROFILE_BYTES(syscall_pwrite, n);
677 result = sys_pwrite(fsp->fh->fd, data, n, offset);
678 END_PROFILE_BYTES(syscall_pwrite);
680 if (result == -1 && errno == ESPIPE) {
681 /* Maintain the fiction that pipes can be sought on. */
682 result = SMB_VFS_WRITE(fsp, data, n);
685 #else /* HAVE_PWRITE */
689 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
694 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
698 result = SMB_VFS_WRITE(fsp, data, n);
701 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
704 #endif /* HAVE_PWRITE */
709 static int vfswrap_init_pool(struct smbd_server_connection *conn)
713 if (conn->pool != NULL) {
717 ret = pthreadpool_tevent_init(conn, lp_aio_max_threads(),
722 struct vfswrap_pread_state {
730 struct vfs_aio_state vfs_aio_state;
731 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
734 static void vfs_pread_do(void *private_data);
735 static void vfs_pread_done(struct tevent_req *subreq);
737 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
739 struct tevent_context *ev,
740 struct files_struct *fsp,
742 size_t n, off_t offset)
744 struct tevent_req *req, *subreq;
745 struct vfswrap_pread_state *state;
748 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
753 ret = vfswrap_init_pool(handle->conn->sconn);
754 if (tevent_req_error(req, ret)) {
755 return tevent_req_post(req, ev);
759 state->fd = fsp->fh->fd;
762 state->offset = offset;
764 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
765 state->profile_bytes, n);
766 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
768 subreq = pthreadpool_tevent_job_send(
769 state, ev, handle->conn->sconn->pool,
770 vfs_pread_do, state);
771 if (tevent_req_nomem(subreq, req)) {
772 return tevent_req_post(req, ev);
774 tevent_req_set_callback(subreq, vfs_pread_done, req);
779 static void vfs_pread_do(void *private_data)
781 struct vfswrap_pread_state *state = talloc_get_type_abort(
782 private_data, struct vfswrap_pread_state);
783 struct timespec start_time;
784 struct timespec end_time;
786 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
788 PROFILE_TIMESTAMP(&start_time);
791 state->ret = pread(state->fd, state->buf, state->count,
793 } while ((state->ret == -1) && (errno == EINTR));
797 PROFILE_TIMESTAMP(&end_time);
799 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
801 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
804 static void vfs_pread_done(struct tevent_req *subreq)
806 struct tevent_req *req = tevent_req_callback_data(
807 subreq, struct tevent_req);
809 struct vfswrap_pread_state *state = tevent_req_data(
810 req, struct vfswrap_pread_state);
814 ret = pthreadpool_tevent_job_recv(subreq);
816 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
817 if (tevent_req_error(req, ret)) {
821 tevent_req_done(req);
824 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
825 struct vfs_aio_state *vfs_aio_state)
827 struct vfswrap_pread_state *state = tevent_req_data(
828 req, struct vfswrap_pread_state);
830 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
834 *vfs_aio_state = state->vfs_aio_state;
838 struct vfswrap_pwrite_state {
846 struct vfs_aio_state vfs_aio_state;
847 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
850 static void vfs_pwrite_do(void *private_data);
851 static void vfs_pwrite_done(struct tevent_req *subreq);
853 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
855 struct tevent_context *ev,
856 struct files_struct *fsp,
858 size_t n, off_t offset)
860 struct tevent_req *req, *subreq;
861 struct vfswrap_pwrite_state *state;
864 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
869 ret = vfswrap_init_pool(handle->conn->sconn);
870 if (tevent_req_error(req, ret)) {
871 return tevent_req_post(req, ev);
875 state->fd = fsp->fh->fd;
878 state->offset = offset;
880 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
881 state->profile_bytes, n);
882 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
884 subreq = pthreadpool_tevent_job_send(
885 state, ev, handle->conn->sconn->pool,
886 vfs_pwrite_do, state);
887 if (tevent_req_nomem(subreq, req)) {
888 return tevent_req_post(req, ev);
890 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
895 static void vfs_pwrite_do(void *private_data)
897 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
898 private_data, struct vfswrap_pwrite_state);
899 struct timespec start_time;
900 struct timespec end_time;
902 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
904 PROFILE_TIMESTAMP(&start_time);
907 state->ret = pwrite(state->fd, state->buf, state->count,
909 } while ((state->ret == -1) && (errno == EINTR));
913 PROFILE_TIMESTAMP(&end_time);
915 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
917 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
920 static void vfs_pwrite_done(struct tevent_req *subreq)
922 struct tevent_req *req = tevent_req_callback_data(
923 subreq, struct tevent_req);
925 struct vfswrap_pwrite_state *state = tevent_req_data(
926 req, struct vfswrap_pwrite_state);
930 ret = pthreadpool_tevent_job_recv(subreq);
932 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
933 if (tevent_req_error(req, ret)) {
937 tevent_req_done(req);
940 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
941 struct vfs_aio_state *vfs_aio_state)
943 struct vfswrap_pwrite_state *state = tevent_req_data(
944 req, struct vfswrap_pwrite_state);
946 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
950 *vfs_aio_state = state->vfs_aio_state;
954 struct vfswrap_fsync_state {
959 struct vfs_aio_state vfs_aio_state;
960 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
963 static void vfs_fsync_do(void *private_data);
964 static void vfs_fsync_done(struct tevent_req *subreq);
966 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
968 struct tevent_context *ev,
969 struct files_struct *fsp)
971 struct tevent_req *req, *subreq;
972 struct vfswrap_fsync_state *state;
975 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
980 ret = vfswrap_init_pool(handle->conn->sconn);
981 if (tevent_req_error(req, ret)) {
982 return tevent_req_post(req, ev);
986 state->fd = fsp->fh->fd;
988 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
989 state->profile_basic);
991 subreq = pthreadpool_tevent_job_send(
992 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
993 if (tevent_req_nomem(subreq, req)) {
994 return tevent_req_post(req, ev);
996 tevent_req_set_callback(subreq, vfs_fsync_done, req);
1001 static void vfs_fsync_do(void *private_data)
1003 struct vfswrap_fsync_state *state = talloc_get_type_abort(
1004 private_data, struct vfswrap_fsync_state);
1005 struct timespec start_time;
1006 struct timespec end_time;
1008 PROFILE_TIMESTAMP(&start_time);
1011 state->ret = fsync(state->fd);
1012 } while ((state->ret == -1) && (errno == EINTR));
1016 PROFILE_TIMESTAMP(&end_time);
1018 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1021 static void vfs_fsync_done(struct tevent_req *subreq)
1023 struct tevent_req *req = tevent_req_callback_data(
1024 subreq, struct tevent_req);
1026 struct vfswrap_fsync_state *state = tevent_req_data(
1027 req, struct vfswrap_fsync_state);
1031 ret = pthreadpool_tevent_job_recv(subreq);
1032 TALLOC_FREE(subreq);
1033 SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
1034 if (tevent_req_error(req, ret)) {
1038 tevent_req_done(req);
1041 static int vfswrap_fsync_recv(struct tevent_req *req,
1042 struct vfs_aio_state *vfs_aio_state)
1044 struct vfswrap_fsync_state *state = tevent_req_data(
1045 req, struct vfswrap_fsync_state);
1047 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1051 *vfs_aio_state = state->vfs_aio_state;
1055 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1059 START_PROFILE(syscall_lseek);
1061 /* Cope with 'stat' file opens. */
1062 if (fsp->fh->fd != -1)
1063 result = lseek(fsp->fh->fd, offset, whence);
1066 * We want to maintain the fiction that we can seek
1067 * on a fifo for file system purposes. This allows
1068 * people to set up UNIX fifo's that feed data to Windows
1069 * applications. JRA.
1072 if((result == -1) && (errno == ESPIPE)) {
1077 END_PROFILE(syscall_lseek);
1081 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1082 off_t offset, size_t n)
1086 START_PROFILE_BYTES(syscall_sendfile, n);
1087 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
1088 END_PROFILE_BYTES(syscall_sendfile);
1092 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1094 files_struct *tofsp,
1100 START_PROFILE_BYTES(syscall_recvfile, n);
1101 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
1102 END_PROFILE_BYTES(syscall_recvfile);
1106 static int vfswrap_rename(vfs_handle_struct *handle,
1107 const struct smb_filename *smb_fname_src,
1108 const struct smb_filename *smb_fname_dst)
1112 START_PROFILE(syscall_rename);
1114 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
1119 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
1122 END_PROFILE(syscall_rename);
1126 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
1131 START_PROFILE(syscall_fsync);
1132 result = fsync(fsp->fh->fd);
1133 END_PROFILE(syscall_fsync);
1140 static int vfswrap_stat(vfs_handle_struct *handle,
1141 struct smb_filename *smb_fname)
1145 START_PROFILE(syscall_stat);
1147 if (smb_fname->stream_name) {
1152 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1153 lp_fake_directory_create_times(SNUM(handle->conn)));
1155 END_PROFILE(syscall_stat);
1159 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1163 START_PROFILE(syscall_fstat);
1164 result = sys_fstat(fsp->fh->fd,
1165 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1166 END_PROFILE(syscall_fstat);
1170 static int vfswrap_lstat(vfs_handle_struct *handle,
1171 struct smb_filename *smb_fname)
1175 START_PROFILE(syscall_lstat);
1177 if (smb_fname->stream_name) {
1182 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1183 lp_fake_directory_create_times(SNUM(handle->conn)));
1185 END_PROFILE(syscall_lstat);
1189 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1191 enum vfs_translate_direction direction,
1192 TALLOC_CTX *mem_ctx,
1195 return NT_STATUS_NONE_MAPPED;
1199 * Implement the default fsctl operation.
1201 static bool vfswrap_logged_ioctl_message = false;
1203 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1204 struct files_struct *fsp,
1207 uint16_t req_flags, /* Needed for UNICODE ... */
1208 const uint8_t *_in_data,
1210 uint8_t **_out_data,
1211 uint32_t max_out_len,
1214 const char *in_data = (const char *)_in_data;
1215 char **out_data = (char **)_out_data;
1219 case FSCTL_SET_SPARSE:
1221 bool set_sparse = true;
1223 if (in_len >= 1 && in_data[0] == 0) {
1227 status = file_set_sparse(handle->conn, fsp, set_sparse);
1229 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1230 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1231 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1232 nt_errstr(status)));
1237 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1239 unsigned char objid[16];
1240 char *return_data = NULL;
1242 /* This should return the object-id on this file.
1243 * I think I'll make this be the inode+dev. JRA.
1246 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1247 fsp_fnum_dbg(fsp)));
1249 *out_len = MIN(max_out_len, 64);
1251 /* Hmmm, will this cause problems if less data asked for? */
1252 return_data = talloc_array(ctx, char, 64);
1253 if (return_data == NULL) {
1254 return NT_STATUS_NO_MEMORY;
1257 /* For backwards compatibility only store the dev/inode. */
1258 push_file_id_16(return_data, &fsp->file_id);
1259 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1260 push_file_id_16(return_data+32, &fsp->file_id);
1261 memset(return_data+48, 0, 16);
1262 *out_data = return_data;
1263 return NT_STATUS_OK;
1266 case FSCTL_GET_REPARSE_POINT:
1268 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1269 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1270 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1271 return NT_STATUS_NOT_A_REPARSE_POINT;
1274 case FSCTL_SET_REPARSE_POINT:
1276 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1277 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1278 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1279 return NT_STATUS_NOT_A_REPARSE_POINT;
1282 case FSCTL_GET_SHADOW_COPY_DATA:
1285 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1286 * and return their volume names. If max_data_count is 16, then it is just
1287 * asking for the number of volumes and length of the combined names.
1289 * pdata is the data allocated by our caller, but that uses
1290 * total_data_count (which is 0 in our case) rather than max_data_count.
1291 * Allocate the correct amount and return the pointer to let
1292 * it be deallocated when we return.
1294 struct shadow_copy_data *shadow_data = NULL;
1295 bool labels = False;
1296 uint32_t labels_data_count = 0;
1298 char *cur_pdata = NULL;
1300 if (max_out_len < 16) {
1301 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1303 return NT_STATUS_INVALID_PARAMETER;
1306 if (max_out_len > 16) {
1310 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1311 if (shadow_data == NULL) {
1312 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1313 return NT_STATUS_NO_MEMORY;
1317 * Call the VFS routine to actually do the work.
1319 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1322 /* broken module didn't set errno on error */
1323 status = NT_STATUS_UNSUCCESSFUL;
1325 status = map_nt_error_from_unix(errno);
1326 if (NT_STATUS_EQUAL(status,
1327 NT_STATUS_NOT_SUPPORTED)) {
1331 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1332 "connectpath %s, failed - %s.\n",
1333 fsp->conn->connectpath,
1334 nt_errstr(status)));
1335 TALLOC_FREE(shadow_data);
1339 labels_data_count = (shadow_data->num_volumes * 2 *
1340 sizeof(SHADOW_COPY_LABEL)) + 2;
1345 *out_len = 12 + labels_data_count;
1348 if (max_out_len < *out_len) {
1349 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1350 max_out_len, *out_len));
1351 TALLOC_FREE(shadow_data);
1352 return NT_STATUS_BUFFER_TOO_SMALL;
1355 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1356 if (cur_pdata == NULL) {
1357 TALLOC_FREE(shadow_data);
1358 return NT_STATUS_NO_MEMORY;
1361 *out_data = cur_pdata;
1363 /* num_volumes 4 bytes */
1364 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1367 /* num_labels 4 bytes */
1368 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1371 /* needed_data_count 4 bytes */
1372 SIVAL(cur_pdata, 8, labels_data_count);
1376 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1377 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1378 if (labels && shadow_data->labels) {
1379 for (i=0; i<shadow_data->num_volumes; i++) {
1381 status = srvstr_push(cur_pdata, req_flags,
1382 cur_pdata, shadow_data->labels[i],
1383 2 * sizeof(SHADOW_COPY_LABEL),
1384 STR_UNICODE|STR_TERMINATE, &len);
1385 if (!NT_STATUS_IS_OK(status)) {
1386 TALLOC_FREE(*out_data);
1387 TALLOC_FREE(shadow_data);
1390 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1391 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1395 TALLOC_FREE(shadow_data);
1397 return NT_STATUS_OK;
1400 case FSCTL_FIND_FILES_BY_SID:
1402 /* pretend this succeeded -
1404 * we have to send back a list with all files owned by this SID
1406 * but I have to check that --metze
1412 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1413 fsp_fnum_dbg(fsp)));
1416 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1417 return NT_STATUS_INVALID_PARAMETER;
1420 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1422 /* unknown 4 bytes: this is not the length of the sid :-( */
1423 /*unknown = IVAL(pdata,0);*/
1425 if (!sid_parse(_in_data + 4, sid_len, &sid)) {
1426 return NT_STATUS_INVALID_PARAMETER;
1428 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1430 if (!sid_to_uid(&sid, &uid)) {
1431 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1432 sid_string_dbg(&sid),
1433 (unsigned long)sid_len));
1437 /* we can take a look at the find source :-)
1439 * find ./ -uid $uid -name '*' is what we need here
1442 * and send 4bytes len and then NULL terminated unicode strings
1445 * but I don't know how to deal with the paged results
1446 * (maybe we can hang the result anywhere in the fsp struct)
1448 * but I don't know how to deal with the paged results
1449 * (maybe we can hang the result anywhere in the fsp struct)
1451 * we don't send all files at once
1452 * and at the next we should *not* start from the beginning,
1453 * so we have to cache the result
1458 /* this works for now... */
1459 return NT_STATUS_OK;
1462 case FSCTL_QUERY_ALLOCATED_RANGES:
1464 /* FIXME: This is just a dummy reply, telling that all of the
1465 * file is allocated. MKS cp needs that.
1466 * Adding the real allocated ranges via FIEMAP on Linux
1467 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1468 * this FSCTL correct for sparse files.
1470 uint64_t offset, length;
1471 char *out_data_tmp = NULL;
1474 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1476 return NT_STATUS_INVALID_PARAMETER;
1479 if (max_out_len < 16) {
1480 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1482 return NT_STATUS_INVALID_PARAMETER;
1485 offset = BVAL(in_data,0);
1486 length = BVAL(in_data,8);
1488 if (offset + length < offset) {
1489 /* No 64-bit integer wrap. */
1490 return NT_STATUS_INVALID_PARAMETER;
1493 /* Shouldn't this be SMB_VFS_STAT ... ? */
1494 status = vfs_stat_fsp(fsp);
1495 if (!NT_STATUS_IS_OK(status)) {
1500 out_data_tmp = talloc_array(ctx, char, *out_len);
1501 if (out_data_tmp == NULL) {
1502 DEBUG(10, ("unable to allocate memory for response\n"));
1503 return NT_STATUS_NO_MEMORY;
1506 if (offset > fsp->fsp_name->st.st_ex_size ||
1507 fsp->fsp_name->st.st_ex_size == 0 ||
1509 memset(out_data_tmp, 0, *out_len);
1511 uint64_t end = offset + length;
1512 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1513 SBVAL(out_data_tmp, 0, 0);
1514 SBVAL(out_data_tmp, 8, end);
1517 *out_data = out_data_tmp;
1519 return NT_STATUS_OK;
1522 case FSCTL_IS_VOLUME_DIRTY:
1524 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1525 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1527 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1528 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1530 return NT_STATUS_INVALID_PARAMETER;
1535 * Only print once ... unfortunately there could be lots of
1536 * different FSCTLs that are called.
1538 if (!vfswrap_logged_ioctl_message) {
1539 vfswrap_logged_ioctl_message = true;
1540 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1541 __func__, function));
1545 return NT_STATUS_NOT_SUPPORTED;
1548 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
1549 const struct smb_filename *fname,
1550 SMB_STRUCT_STAT *sbuf);
1552 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1553 struct smb_filename *smb_fname,
1558 offline = vfswrap_is_offline(handle, smb_fname, &smb_fname->st);
1560 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1563 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1566 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1567 struct files_struct *fsp,
1572 offline = vfswrap_is_offline(handle, fsp->fsp_name, &fsp->fsp_name->st);
1574 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1577 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1580 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1581 const struct smb_filename *smb_fname,
1584 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1587 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1588 struct files_struct *fsp,
1591 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1594 struct vfs_cc_state {
1595 struct tevent_context *ev;
1597 bool read_lck_locked;
1598 struct lock_struct read_lck;
1599 bool write_lck_locked;
1600 struct lock_struct write_lck;
1601 struct files_struct *src_fsp;
1603 struct files_struct *dst_fsp;
1607 size_t next_io_size;
1610 static NTSTATUS copy_chunk_loop(struct tevent_req *req);
1612 static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *handle,
1613 TALLOC_CTX *mem_ctx,
1614 struct tevent_context *ev,
1615 struct files_struct *src_fsp,
1617 struct files_struct *dest_fsp,
1621 struct tevent_req *req;
1622 struct vfs_cc_state *state = NULL;
1623 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
1626 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
1628 req = tevent_req_create(mem_ctx, &state, struct vfs_cc_state);
1633 *state = (struct vfs_cc_state) {
1637 .dst_fsp = dest_fsp,
1638 .dst_off = dest_off,
1640 .remaining = to_copy,
1642 state->buf = talloc_array(state, uint8_t, num);
1643 if (tevent_req_nomem(state->buf, req)) {
1644 return tevent_req_post(req, ev);
1647 status = vfs_stat_fsp(src_fsp);
1648 if (tevent_req_nterror(req, status)) {
1649 return tevent_req_post(req, ev);
1652 if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
1654 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1655 * If the SourceOffset or SourceOffset + Length extends beyond
1656 * the end of file, the server SHOULD<240> treat this as a
1657 * STATUS_END_OF_FILE error.
1659 * <240> Section 3.3.5.15.6: Windows servers will return
1660 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1662 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1663 return tevent_req_post(req, ev);
1666 if (src_fsp->op == NULL) {
1667 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1668 return tevent_req_post(req, ev);
1671 if (dest_fsp->op == NULL) {
1672 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1673 return tevent_req_post(req, ev);
1676 status = copy_chunk_loop(req);
1677 if (!NT_STATUS_IS_OK(status)) {
1678 tevent_req_nterror(req, status);
1679 return tevent_req_post(req, ev);
1685 static void vfswrap_copy_chunk_read_done(struct tevent_req *subreq);
1687 static NTSTATUS copy_chunk_loop(struct tevent_req *req)
1689 struct vfs_cc_state *state = tevent_req_data(req, struct vfs_cc_state);
1690 struct tevent_req *subreq = NULL;
1693 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
1695 init_strict_lock_struct(state->src_fsp,
1696 state->src_fsp->op->global->open_persistent_id,
1698 state->next_io_size,
1702 ok = SMB_VFS_STRICT_LOCK(state->src_fsp->conn,
1706 return NT_STATUS_FILE_LOCK_CONFLICT;
1709 subreq = SMB_VFS_PREAD_SEND(state,
1710 state->src_fsp->conn->sconn->ev_ctx,
1713 state->next_io_size,
1715 if (subreq == NULL) {
1716 return NT_STATUS_NO_MEMORY;
1718 tevent_req_set_callback(subreq, vfswrap_copy_chunk_read_done, req);
1720 return NT_STATUS_OK;
1723 static void vfswrap_copy_chunk_write_done(struct tevent_req *subreq);
1725 static void vfswrap_copy_chunk_read_done(struct tevent_req *subreq)
1727 struct tevent_req *req = tevent_req_callback_data(
1728 subreq, struct tevent_req);
1729 struct vfs_cc_state *state = tevent_req_data(req, struct vfs_cc_state);
1730 struct vfs_aio_state aio_state;
1734 SMB_VFS_STRICT_UNLOCK(state->src_fsp->conn,
1737 ZERO_STRUCT(state->read_lck);
1739 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
1740 TALLOC_FREE(subreq);
1742 DBG_ERR("read failed: %s\n", strerror(errno));
1743 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1746 if (nread != state->next_io_size) {
1747 DBG_ERR("Short read, only %zd of %zu\n",
1748 nread, state->next_io_size);
1749 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1753 state->src_off += nread;
1755 init_strict_lock_struct(state->dst_fsp,
1756 state->dst_fsp->op->global->open_persistent_id,
1758 state->next_io_size,
1762 ok = SMB_VFS_STRICT_LOCK(state->dst_fsp->conn,
1766 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1770 subreq = SMB_VFS_PWRITE_SEND(state,
1774 state->next_io_size,
1776 if (subreq == NULL) {
1777 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1780 tevent_req_set_callback(subreq, vfswrap_copy_chunk_write_done, req);
1783 static void vfswrap_copy_chunk_write_done(struct tevent_req *subreq)
1785 struct tevent_req *req = tevent_req_callback_data(
1786 subreq, struct tevent_req);
1787 struct vfs_cc_state *state = tevent_req_data(req, struct vfs_cc_state);
1788 struct vfs_aio_state aio_state;
1792 SMB_VFS_STRICT_UNLOCK(state->dst_fsp->conn,
1795 ZERO_STRUCT(state->write_lck);
1797 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
1798 TALLOC_FREE(subreq);
1799 if (nwritten == -1) {
1800 DBG_ERR("write failed: %s\n", strerror(errno));
1801 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1804 if (nwritten != state->next_io_size) {
1805 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
1806 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1810 state->dst_off += nwritten;
1812 if (state->remaining < nwritten) {
1813 /* Paranoia check */
1814 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1817 state->remaining -= nwritten;
1818 if (state->remaining == 0) {
1819 tevent_req_done(req);
1823 status = copy_chunk_loop(req);
1824 if (!NT_STATUS_IS_OK(status)) {
1825 tevent_req_nterror(req, status);
1832 static NTSTATUS vfswrap_copy_chunk_recv(struct vfs_handle_struct *handle,
1833 struct tevent_req *req,
1836 struct vfs_cc_state *state = tevent_req_data(req, struct vfs_cc_state);
1839 if (tevent_req_is_nterror(req, &status)) {
1840 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
1842 tevent_req_received(req);
1846 *copied = state->to_copy;
1847 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
1848 tevent_req_received(req);
1850 return NT_STATUS_OK;
1853 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1854 TALLOC_CTX *mem_ctx,
1855 struct files_struct *fsp,
1856 struct smb_filename *smb_fname,
1857 uint16_t *_compression_fmt)
1859 return NT_STATUS_INVALID_DEVICE_REQUEST;
1862 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1863 TALLOC_CTX *mem_ctx,
1864 struct files_struct *fsp,
1865 uint16_t compression_fmt)
1867 return NT_STATUS_INVALID_DEVICE_REQUEST;
1870 /********************************************************************
1871 Given a stat buffer return the allocated size on disk, taking into
1872 account sparse files.
1873 ********************************************************************/
1874 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1875 struct files_struct *fsp,
1876 const SMB_STRUCT_STAT *sbuf)
1880 START_PROFILE(syscall_get_alloc_size);
1882 if(S_ISDIR(sbuf->st_ex_mode)) {
1887 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1888 /* The type of st_blocksize is blkcnt_t which *MUST* be
1889 signed (according to POSIX) and can be less than 64-bits.
1890 Ensure when we're converting to 64 bits wide we don't
1892 #if defined(SIZEOF_BLKCNT_T_8)
1893 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1894 #elif defined(SIZEOF_BLKCNT_T_4)
1896 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1897 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1900 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1904 * Some file systems do not allocate a block for very
1905 * small files. But for non-empty file should report a
1909 uint64_t filesize = get_file_size_stat(sbuf);
1911 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
1915 result = get_file_size_stat(sbuf);
1918 if (fsp && fsp->initial_allocation_size)
1919 result = MAX(result,fsp->initial_allocation_size);
1921 result = smb_roundup(handle->conn, result);
1924 END_PROFILE(syscall_get_alloc_size);
1928 static int vfswrap_unlink(vfs_handle_struct *handle,
1929 const struct smb_filename *smb_fname)
1933 START_PROFILE(syscall_unlink);
1935 if (smb_fname->stream_name) {
1939 result = unlink(smb_fname->base_name);
1942 END_PROFILE(syscall_unlink);
1946 static int vfswrap_chmod(vfs_handle_struct *handle,
1947 const struct smb_filename *smb_fname,
1952 START_PROFILE(syscall_chmod);
1955 * We need to do this due to the fact that the default POSIX ACL
1956 * chmod modifies the ACL *mask* for the group owner, not the
1957 * group owner bits directly. JRA.
1962 int saved_errno = errno; /* We might get ENOSYS */
1963 result = SMB_VFS_CHMOD_ACL(handle->conn,
1967 END_PROFILE(syscall_chmod);
1970 /* Error - return the old errno. */
1971 errno = saved_errno;
1974 result = chmod(smb_fname->base_name, mode);
1975 END_PROFILE(syscall_chmod);
1979 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
1983 START_PROFILE(syscall_fchmod);
1986 * We need to do this due to the fact that the default POSIX ACL
1987 * chmod modifies the ACL *mask* for the group owner, not the
1988 * group owner bits directly. JRA.
1992 int saved_errno = errno; /* We might get ENOSYS */
1993 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
1994 END_PROFILE(syscall_fchmod);
1997 /* Error - return the old errno. */
1998 errno = saved_errno;
2001 #if defined(HAVE_FCHMOD)
2002 result = fchmod(fsp->fh->fd, mode);
2008 END_PROFILE(syscall_fchmod);
2012 static int vfswrap_chown(vfs_handle_struct *handle,
2013 const struct smb_filename *smb_fname,
2019 START_PROFILE(syscall_chown);
2020 result = chown(smb_fname->base_name, uid, gid);
2021 END_PROFILE(syscall_chown);
2025 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2030 START_PROFILE(syscall_fchown);
2031 result = fchown(fsp->fh->fd, uid, gid);
2032 END_PROFILE(syscall_fchown);
2040 static int vfswrap_lchown(vfs_handle_struct *handle,
2041 const struct smb_filename *smb_fname,
2047 START_PROFILE(syscall_lchown);
2048 result = lchown(smb_fname->base_name, uid, gid);
2049 END_PROFILE(syscall_lchown);
2053 static int vfswrap_chdir(vfs_handle_struct *handle, const char *path)
2057 START_PROFILE(syscall_chdir);
2058 result = chdir(path);
2059 END_PROFILE(syscall_chdir);
2063 static char *vfswrap_getwd(vfs_handle_struct *handle)
2067 START_PROFILE(syscall_getwd);
2068 result = sys_getwd();
2069 END_PROFILE(syscall_getwd);
2073 /*********************************************************************
2074 nsec timestamp resolution call. Convert down to whatever the underlying
2075 system will support.
2076 **********************************************************************/
2078 static int vfswrap_ntimes(vfs_handle_struct *handle,
2079 const struct smb_filename *smb_fname,
2080 struct smb_file_time *ft)
2084 START_PROFILE(syscall_ntimes);
2086 if (smb_fname->stream_name) {
2092 if (null_timespec(ft->atime)) {
2093 ft->atime= smb_fname->st.st_ex_atime;
2096 if (null_timespec(ft->mtime)) {
2097 ft->mtime = smb_fname->st.st_ex_mtime;
2100 if (!null_timespec(ft->create_time)) {
2101 set_create_timespec_ea(handle->conn,
2106 if ((timespec_compare(&ft->atime,
2107 &smb_fname->st.st_ex_atime) == 0) &&
2108 (timespec_compare(&ft->mtime,
2109 &smb_fname->st.st_ex_mtime) == 0)) {
2114 #if defined(HAVE_UTIMENSAT)
2116 struct timespec ts[2];
2119 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2121 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2123 if (!((result == -1) && (errno == ENOSYS))) {
2127 #if defined(HAVE_UTIMES)
2129 struct timeval tv[2];
2130 tv[0] = convert_timespec_to_timeval(ft->atime);
2131 tv[1] = convert_timespec_to_timeval(ft->mtime);
2132 result = utimes(smb_fname->base_name, tv);
2134 result = utimes(smb_fname->base_name, NULL);
2136 if (!((result == -1) && (errno == ENOSYS))) {
2140 #if defined(HAVE_UTIME)
2142 struct utimbuf times;
2143 times.actime = convert_timespec_to_time_t(ft->atime);
2144 times.modtime = convert_timespec_to_time_t(ft->mtime);
2145 result = utime(smb_fname->base_name, ×);
2147 result = utime(smb_fname->base_name, NULL);
2149 if (!((result == -1) && (errno == ENOSYS))) {
2157 END_PROFILE(syscall_ntimes);
2161 /*********************************************************************
2162 A version of ftruncate that will write the space on disk if strict
2164 **********************************************************************/
2166 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2168 off_t space_to_write;
2169 uint64_t space_avail;
2170 uint64_t bsize,dfree,dsize;
2173 SMB_STRUCT_STAT *pst;
2175 status = vfs_stat_fsp(fsp);
2176 if (!NT_STATUS_IS_OK(status)) {
2179 pst = &fsp->fsp_name->st;
2182 if (S_ISFIFO(pst->st_ex_mode))
2186 if (pst->st_ex_size == len)
2189 /* Shrink - just ftruncate. */
2190 if (pst->st_ex_size > len)
2191 return ftruncate(fsp->fh->fd, len);
2193 space_to_write = len - pst->st_ex_size;
2195 /* for allocation try fallocate first. This can fail on some
2196 platforms e.g. when the filesystem doesn't support it and no
2197 emulation is being done by the libc (like on AIX with JFS1). In that
2198 case we do our own emulation. fallocate implementations can
2199 return ENOTSUP or EINVAL in cases like that. */
2200 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2201 if (ret == -1 && errno == ENOSPC) {
2207 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2208 "error %d. Falling back to slow manual allocation\n", errno));
2210 /* available disk space is enough or not? */
2212 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2213 /* space_avail is 1k blocks */
2214 if (space_avail == (uint64_t)-1 ||
2215 ((uint64_t)space_to_write/1024 > space_avail) ) {
2220 /* Write out the real space on disk. */
2221 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2229 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2232 SMB_STRUCT_STAT *pst;
2236 START_PROFILE(syscall_ftruncate);
2238 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2239 result = strict_allocate_ftruncate(handle, fsp, len);
2240 END_PROFILE(syscall_ftruncate);
2244 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2245 ftruncate if the system supports it. Then I discovered that
2246 you can have some filesystems that support ftruncate
2247 expansion and some that don't! On Linux fat can't do
2248 ftruncate extend but ext2 can. */
2250 result = ftruncate(fsp->fh->fd, len);
2252 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2253 extend a file with ftruncate. Provide alternate implementation
2256 /* Do an fstat to see if the file is longer than the requested
2257 size in which case the ftruncate above should have
2258 succeeded or shorter, in which case seek to len - 1 and
2259 write 1 byte of zero */
2260 status = vfs_stat_fsp(fsp);
2261 if (!NT_STATUS_IS_OK(status)) {
2265 /* We need to update the files_struct after successful ftruncate */
2270 pst = &fsp->fsp_name->st;
2273 if (S_ISFIFO(pst->st_ex_mode)) {
2279 if (pst->st_ex_size == len) {
2284 if (pst->st_ex_size > len) {
2285 /* the ftruncate should have worked */
2289 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2297 END_PROFILE(syscall_ftruncate);
2301 static int vfswrap_fallocate(vfs_handle_struct *handle,
2309 START_PROFILE(syscall_fallocate);
2311 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2313 * posix_fallocate returns 0 on success, errno on error
2314 * and doesn't set errno. Make it behave like fallocate()
2315 * which returns -1, and sets errno on failure.
2322 /* sys_fallocate handles filtering of unsupported mode flags */
2323 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2325 END_PROFILE(syscall_fallocate);
2329 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2333 START_PROFILE(syscall_fcntl_lock);
2335 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2337 "force process locks",
2339 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2342 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2343 END_PROFILE(syscall_fcntl_lock);
2347 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2348 uint32_t share_mode, uint32_t access_mask)
2350 START_PROFILE(syscall_kernel_flock);
2351 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2352 END_PROFILE(syscall_kernel_flock);
2356 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2361 START_PROFILE(syscall_fcntl_getlock);
2363 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2365 "force process locks",
2367 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2370 result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2371 END_PROFILE(syscall_fcntl_getlock);
2375 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2380 START_PROFILE(syscall_linux_setlease);
2382 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2383 result = linux_setlease(fsp->fh->fd, leasetype);
2387 END_PROFILE(syscall_linux_setlease);
2391 static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2395 START_PROFILE(syscall_symlink);
2396 result = symlink(oldpath, newpath);
2397 END_PROFILE(syscall_symlink);
2401 static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
2405 START_PROFILE(syscall_readlink);
2406 result = readlink(path, buf, bufsiz);
2407 END_PROFILE(syscall_readlink);
2411 static int vfswrap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2415 START_PROFILE(syscall_link);
2416 result = link(oldpath, newpath);
2417 END_PROFILE(syscall_link);
2421 static int vfswrap_mknod(vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev)
2425 START_PROFILE(syscall_mknod);
2426 result = sys_mknod(pathname, mode, dev);
2427 END_PROFILE(syscall_mknod);
2431 static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
2435 START_PROFILE(syscall_realpath);
2436 result = sys_realpath(path);
2437 END_PROFILE(syscall_realpath);
2441 static int vfswrap_chflags(vfs_handle_struct *handle, const char *path,
2445 return chflags(path, flags);
2452 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2453 const SMB_STRUCT_STAT *sbuf)
2457 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2461 key.devid = sbuf->st_ex_dev;
2462 key.inode = sbuf->st_ex_ino;
2463 /* key.extid is unused by default. */
2468 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2469 struct files_struct *fsp,
2470 const struct smb_filename *smb_fname,
2471 TALLOC_CTX *mem_ctx,
2472 unsigned int *pnum_streams,
2473 struct stream_struct **pstreams)
2475 SMB_STRUCT_STAT sbuf;
2476 struct stream_struct *tmp_streams = NULL;
2479 if ((fsp != NULL) && (fsp->is_directory)) {
2481 * No default streams on directories
2486 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2487 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2490 struct smb_filename smb_fname_cp;
2492 ZERO_STRUCT(smb_fname_cp);
2493 smb_fname_cp.base_name = discard_const_p(char,
2494 smb_fname->base_name);
2495 smb_fname_cp.flags = smb_fname->flags;
2497 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
2498 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2500 ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2502 sbuf = smb_fname_cp.st;
2506 return map_nt_error_from_unix(errno);
2509 if (S_ISDIR(sbuf.st_ex_mode)) {
2513 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2514 (*pnum_streams) + 1);
2515 if (tmp_streams == NULL) {
2516 return NT_STATUS_NO_MEMORY;
2518 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2519 if (tmp_streams[*pnum_streams].name == NULL) {
2520 return NT_STATUS_NO_MEMORY;
2522 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2523 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2526 *pstreams = tmp_streams;
2528 return NT_STATUS_OK;
2531 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2534 TALLOC_CTX *mem_ctx,
2538 * Don't fall back to get_real_filename so callers can differentiate
2539 * between a full directory scan and an actual case-insensitive stat.
2545 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2548 return handle->conn->connectpath;
2551 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2552 struct byte_range_lock *br_lck,
2553 struct lock_struct *plock,
2556 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2558 /* Note: blr is not used in the default implementation. */
2559 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2562 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2563 struct messaging_context *msg_ctx,
2564 struct byte_range_lock *br_lck,
2565 const struct lock_struct *plock)
2567 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2569 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2572 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2573 struct byte_range_lock *br_lck,
2574 struct lock_struct *plock)
2576 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2578 /* Note: blr is not used in the default implementation. */
2579 return brl_lock_cancel_default(br_lck, plock);
2582 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2584 struct lock_struct *plock)
2586 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2587 plock->lock_type == WRITE_LOCK);
2589 return strict_lock_default(fsp, plock);
2592 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2594 struct lock_struct *plock)
2596 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2597 plock->lock_type == WRITE_LOCK);
2599 strict_unlock_default(fsp, plock);
2602 /* NT ACL operations. */
2604 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2606 uint32_t security_info,
2607 TALLOC_CTX *mem_ctx,
2608 struct security_descriptor **ppdesc)
2612 START_PROFILE(fget_nt_acl);
2613 result = posix_fget_nt_acl(fsp, security_info,
2615 END_PROFILE(fget_nt_acl);
2619 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2620 const struct smb_filename *smb_fname,
2621 uint32_t security_info,
2622 TALLOC_CTX *mem_ctx,
2623 struct security_descriptor **ppdesc)
2627 START_PROFILE(get_nt_acl);
2628 result = posix_get_nt_acl(handle->conn,
2633 END_PROFILE(get_nt_acl);
2637 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2641 START_PROFILE(fset_nt_acl);
2642 result = set_nt_acl(fsp, security_info_sent, psd);
2643 END_PROFILE(fset_nt_acl);
2647 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2648 struct smb_filename *file,
2649 struct security_acl *sacl,
2650 uint32_t access_requested,
2651 uint32_t access_denied)
2653 return NT_STATUS_OK; /* Nothing to do here ... */
2656 static int vfswrap_chmod_acl(vfs_handle_struct *handle,
2657 const struct smb_filename *smb_fname,
2666 START_PROFILE(chmod_acl);
2667 result = chmod_acl(handle->conn, smb_fname->base_name, mode);
2668 END_PROFILE(chmod_acl);
2673 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2681 START_PROFILE(fchmod_acl);
2682 result = fchmod_acl(fsp, mode);
2683 END_PROFILE(fchmod_acl);
2688 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2690 SMB_ACL_TYPE_T type,
2691 TALLOC_CTX *mem_ctx)
2693 return sys_acl_get_file(handle, path_p, type, mem_ctx);
2696 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2698 TALLOC_CTX *mem_ctx)
2700 return sys_acl_get_fd(handle, fsp, mem_ctx);
2703 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2705 return sys_acl_set_file(handle, name, acltype, theacl);
2708 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2710 return sys_acl_set_fd(handle, fsp, theacl);
2713 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
2715 return sys_acl_delete_def_file(handle, path);
2718 /****************************************************************
2719 Extended attribute operations.
2720 *****************************************************************/
2722 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
2724 return getxattr(path, name, value, size);
2727 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2729 return fgetxattr(fsp->fh->fd, name, value, size);
2732 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
2734 return listxattr(path, list, size);
2737 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2739 return flistxattr(fsp->fh->fd, list, size);
2742 static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
2744 return removexattr(path, name);
2747 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2749 return fremovexattr(fsp->fh->fd, name);
2752 static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
2754 return setxattr(path, name, value, size, flags);
2757 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2759 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2762 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2767 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2768 const struct smb_filename *fname,
2769 SMB_STRUCT_STAT *sbuf)
2773 bool offline = false;
2775 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2779 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2780 #if defined(ENOTSUP)
2786 status = get_full_smb_filename(talloc_tos(), fname, &path);
2787 if (!NT_STATUS_IS_OK(status)) {
2788 errno = map_errno_from_nt_status(status);
2792 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2799 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2800 struct files_struct *fsp,
2801 TALLOC_CTX *mem_ctx,
2804 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2807 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2808 struct files_struct *fsp,
2809 const DATA_BLOB old_cookie,
2810 TALLOC_CTX *mem_ctx,
2811 DATA_BLOB *new_cookie)
2813 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2817 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2818 struct smb_request *smb1req,
2819 struct smbXsrv_open *op,
2820 const DATA_BLOB old_cookie,
2821 TALLOC_CTX *mem_ctx,
2822 struct files_struct **fsp,
2823 DATA_BLOB *new_cookie)
2825 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2826 old_cookie, mem_ctx,
2830 static struct vfs_fn_pointers vfs_default_fns = {
2831 /* Disk operations */
2833 .connect_fn = vfswrap_connect,
2834 .disconnect_fn = vfswrap_disconnect,
2835 .disk_free_fn = vfswrap_disk_free,
2836 .get_quota_fn = vfswrap_get_quota,
2837 .set_quota_fn = vfswrap_set_quota,
2838 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2839 .statvfs_fn = vfswrap_statvfs,
2840 .fs_capabilities_fn = vfswrap_fs_capabilities,
2841 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2842 .snap_check_path_fn = vfswrap_snap_check_path,
2843 .snap_create_fn = vfswrap_snap_create,
2844 .snap_delete_fn = vfswrap_snap_delete,
2846 /* Directory operations */
2848 .opendir_fn = vfswrap_opendir,
2849 .fdopendir_fn = vfswrap_fdopendir,
2850 .readdir_fn = vfswrap_readdir,
2851 .readdir_attr_fn = vfswrap_readdir_attr,
2852 .seekdir_fn = vfswrap_seekdir,
2853 .telldir_fn = vfswrap_telldir,
2854 .rewind_dir_fn = vfswrap_rewinddir,
2855 .mkdir_fn = vfswrap_mkdir,
2856 .rmdir_fn = vfswrap_rmdir,
2857 .closedir_fn = vfswrap_closedir,
2858 .init_search_op_fn = vfswrap_init_search_op,
2860 /* File operations */
2862 .open_fn = vfswrap_open,
2863 .create_file_fn = vfswrap_create_file,
2864 .close_fn = vfswrap_close,
2865 .read_fn = vfswrap_read,
2866 .pread_fn = vfswrap_pread,
2867 .pread_send_fn = vfswrap_pread_send,
2868 .pread_recv_fn = vfswrap_pread_recv,
2869 .write_fn = vfswrap_write,
2870 .pwrite_fn = vfswrap_pwrite,
2871 .pwrite_send_fn = vfswrap_pwrite_send,
2872 .pwrite_recv_fn = vfswrap_pwrite_recv,
2873 .lseek_fn = vfswrap_lseek,
2874 .sendfile_fn = vfswrap_sendfile,
2875 .recvfile_fn = vfswrap_recvfile,
2876 .rename_fn = vfswrap_rename,
2877 .fsync_fn = vfswrap_fsync,
2878 .fsync_send_fn = vfswrap_fsync_send,
2879 .fsync_recv_fn = vfswrap_fsync_recv,
2880 .stat_fn = vfswrap_stat,
2881 .fstat_fn = vfswrap_fstat,
2882 .lstat_fn = vfswrap_lstat,
2883 .get_alloc_size_fn = vfswrap_get_alloc_size,
2884 .unlink_fn = vfswrap_unlink,
2885 .chmod_fn = vfswrap_chmod,
2886 .fchmod_fn = vfswrap_fchmod,
2887 .chown_fn = vfswrap_chown,
2888 .fchown_fn = vfswrap_fchown,
2889 .lchown_fn = vfswrap_lchown,
2890 .chdir_fn = vfswrap_chdir,
2891 .getwd_fn = vfswrap_getwd,
2892 .ntimes_fn = vfswrap_ntimes,
2893 .ftruncate_fn = vfswrap_ftruncate,
2894 .fallocate_fn = vfswrap_fallocate,
2895 .lock_fn = vfswrap_lock,
2896 .kernel_flock_fn = vfswrap_kernel_flock,
2897 .linux_setlease_fn = vfswrap_linux_setlease,
2898 .getlock_fn = vfswrap_getlock,
2899 .symlink_fn = vfswrap_symlink,
2900 .readlink_fn = vfswrap_readlink,
2901 .link_fn = vfswrap_link,
2902 .mknod_fn = vfswrap_mknod,
2903 .realpath_fn = vfswrap_realpath,
2904 .chflags_fn = vfswrap_chflags,
2905 .file_id_create_fn = vfswrap_file_id_create,
2906 .streaminfo_fn = vfswrap_streaminfo,
2907 .get_real_filename_fn = vfswrap_get_real_filename,
2908 .connectpath_fn = vfswrap_connectpath,
2909 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2910 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2911 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2912 .strict_lock_fn = vfswrap_strict_lock,
2913 .strict_unlock_fn = vfswrap_strict_unlock,
2914 .translate_name_fn = vfswrap_translate_name,
2915 .fsctl_fn = vfswrap_fsctl,
2916 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
2917 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
2918 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
2919 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
2920 .copy_chunk_send_fn = vfswrap_copy_chunk_send,
2921 .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
2922 .get_compression_fn = vfswrap_get_compression,
2923 .set_compression_fn = vfswrap_set_compression,
2925 /* NT ACL operations. */
2927 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2928 .get_nt_acl_fn = vfswrap_get_nt_acl,
2929 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2930 .audit_file_fn = vfswrap_audit_file,
2932 /* POSIX ACL operations. */
2934 .chmod_acl_fn = vfswrap_chmod_acl,
2935 .fchmod_acl_fn = vfswrap_fchmod_acl,
2937 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2938 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2939 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2940 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2941 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2942 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2943 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2945 /* EA operations. */
2946 .getxattr_fn = vfswrap_getxattr,
2947 .fgetxattr_fn = vfswrap_fgetxattr,
2948 .listxattr_fn = vfswrap_listxattr,
2949 .flistxattr_fn = vfswrap_flistxattr,
2950 .removexattr_fn = vfswrap_removexattr,
2951 .fremovexattr_fn = vfswrap_fremovexattr,
2952 .setxattr_fn = vfswrap_setxattr,
2953 .fsetxattr_fn = vfswrap_fsetxattr,
2955 /* aio operations */
2956 .aio_force_fn = vfswrap_aio_force,
2958 /* durable handle operations */
2959 .durable_cookie_fn = vfswrap_durable_cookie,
2960 .durable_disconnect_fn = vfswrap_durable_disconnect,
2961 .durable_reconnect_fn = vfswrap_durable_reconnect,
2964 NTSTATUS vfs_default_init(void);
2965 NTSTATUS vfs_default_init(void)
2967 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
2968 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);