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,
59 const struct smb_filename *smb_fname,
64 if (sys_fsusage(smb_fname->base_name, dfree, dsize) != 0) {
72 static int vfswrap_get_quota(struct vfs_handle_struct *handle, const char *path,
73 enum SMB_QUOTA_TYPE qtype, unid_t id,
76 #ifdef HAVE_SYS_QUOTAS
79 START_PROFILE(syscall_get_quota);
80 result = sys_get_quota(path, qtype, id, qt);
81 END_PROFILE(syscall_get_quota);
89 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
91 #ifdef HAVE_SYS_QUOTAS
94 START_PROFILE(syscall_set_quota);
95 result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
96 END_PROFILE(syscall_set_quota);
104 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
105 struct files_struct *fsp,
106 struct shadow_copy_data *shadow_copy_data,
110 return -1; /* Not implemented. */
113 static int vfswrap_statvfs(struct vfs_handle_struct *handle, const char *path, vfs_statvfs_struct *statbuf)
115 return sys_statvfs(path, statbuf);
118 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
119 enum timestamp_set_resolution *p_ts_res)
121 connection_struct *conn = handle->conn;
122 uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
123 struct smb_filename *smb_fname_cpath = NULL;
124 struct vfs_statvfs_struct statbuf;
127 ZERO_STRUCT(statbuf);
128 ret = sys_statvfs(conn->connectpath, &statbuf);
130 caps = statbuf.FsCapabilities;
133 *p_ts_res = TIMESTAMP_SET_SECONDS;
135 /* Work out what timestamp resolution we can
136 * use when setting a timestamp. */
138 smb_fname_cpath = synthetic_smb_fname(talloc_tos(), conn->connectpath,
140 if (smb_fname_cpath == NULL) {
144 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
146 TALLOC_FREE(smb_fname_cpath);
150 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
151 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
152 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
153 /* If any of the normal UNIX directory timestamps
154 * have a non-zero tv_nsec component assume
155 * we might be able to set sub-second timestamps.
156 * See what filetime set primitives we have.
158 #if defined(HAVE_UTIMENSAT)
159 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
160 #elif defined(HAVE_UTIMES)
161 /* utimes allows msec timestamps to be set. */
162 *p_ts_res = TIMESTAMP_SET_MSEC;
163 #elif defined(HAVE_UTIME)
164 /* utime only allows sec timestamps to be set. */
165 *p_ts_res = TIMESTAMP_SET_SECONDS;
168 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
170 "available on share %s, directory %s\n",
171 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
172 lp_servicename(talloc_tos(), conn->params->service),
173 conn->connectpath ));
175 TALLOC_FREE(smb_fname_cpath);
179 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
180 struct dfs_GetDFSReferral *r)
182 struct junction_map *junction = NULL;
184 bool self_referral = false;
185 char *pathnamep = NULL;
186 char *local_dfs_path = NULL;
189 uint16_t max_referral_level = r->in.req.max_referral_level;
192 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
195 /* get the junction entry */
196 if (r->in.req.servername == NULL) {
197 return NT_STATUS_NOT_FOUND;
201 * Trim pathname sent by client so it begins with only one backslash.
202 * Two backslashes confuse some dfs clients
205 local_dfs_path = talloc_strdup(r, r->in.req.servername);
206 if (local_dfs_path == NULL) {
207 return NT_STATUS_NO_MEMORY;
209 pathnamep = local_dfs_path;
210 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
211 IS_DIRECTORY_SEP(pathnamep[1])) {
215 junction = talloc_zero(r, struct junction_map);
216 if (junction == NULL) {
217 return NT_STATUS_NO_MEMORY;
220 /* The following call can change cwd. */
221 status = get_referred_path(r, pathnamep,
222 handle->conn->sconn->remote_address,
223 handle->conn->sconn->local_address,
224 !handle->conn->sconn->using_smb2,
225 junction, &consumedcnt, &self_referral);
226 if (!NT_STATUS_IS_OK(status)) {
227 vfs_ChDir(handle->conn, handle->conn->connectpath);
230 vfs_ChDir(handle->conn, handle->conn->connectpath);
232 if (!self_referral) {
233 pathnamep[consumedcnt] = '\0';
236 dbgtext("Path %s to alternate path(s):",
238 for (i=0; i < junction->referral_count; i++) {
240 junction->referral_list[i].alternate_path);
246 if (r->in.req.max_referral_level <= 2) {
247 max_referral_level = 2;
249 if (r->in.req.max_referral_level >= 3) {
250 max_referral_level = 3;
253 r->out.resp = talloc_zero(r, struct dfs_referral_resp);
254 if (r->out.resp == NULL) {
255 return NT_STATUS_NO_MEMORY;
258 r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
259 r->out.resp->nb_referrals = junction->referral_count;
261 r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
263 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
266 r->out.resp->referral_entries = talloc_zero_array(r,
267 struct dfs_referral_type,
268 r->out.resp->nb_referrals);
269 if (r->out.resp->referral_entries == NULL) {
270 return NT_STATUS_NO_MEMORY;
273 switch (max_referral_level) {
275 for(i=0; i < junction->referral_count; i++) {
276 struct referral *ref = &junction->referral_list[i];
277 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
278 struct dfs_referral_type *t =
279 &r->out.resp->referral_entries[i];
280 struct dfs_referral_v2 *v2 = &t->referral.v2;
283 v2->size = VERSION2_REFERRAL_SIZE;
285 v2->server_type = DFS_SERVER_ROOT;
287 v2->server_type = DFS_SERVER_NON_ROOT;
290 v2->proximity = ref->proximity;
292 v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
293 if (v2->DFS_path == NULL) {
294 return NT_STATUS_NO_MEMORY;
296 v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
297 if (v2->DFS_alt_path == NULL) {
298 return NT_STATUS_NO_MEMORY;
300 v2->netw_address = talloc_strdup(mem_ctx,
301 ref->alternate_path);
302 if (v2->netw_address == NULL) {
303 return NT_STATUS_NO_MEMORY;
309 for(i=0; i < junction->referral_count; i++) {
310 struct referral *ref = &junction->referral_list[i];
311 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
312 struct dfs_referral_type *t =
313 &r->out.resp->referral_entries[i];
314 struct dfs_referral_v3 *v3 = &t->referral.v3;
315 struct dfs_normal_referral *r1 = &v3->referrals.r1;
318 v3->size = VERSION3_REFERRAL_SIZE;
320 v3->server_type = DFS_SERVER_ROOT;
322 v3->server_type = DFS_SERVER_NON_ROOT;
326 r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
327 if (r1->DFS_path == NULL) {
328 return NT_STATUS_NO_MEMORY;
330 r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
331 if (r1->DFS_alt_path == NULL) {
332 return NT_STATUS_NO_MEMORY;
334 r1->netw_address = talloc_strdup(mem_ctx,
335 ref->alternate_path);
336 if (r1->netw_address == NULL) {
337 return NT_STATUS_NO_MEMORY;
342 DEBUG(0,("Invalid dfs referral version: %d\n",
343 max_referral_level));
344 return NT_STATUS_INVALID_LEVEL;
348 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
354 static NTSTATUS vfswrap_snap_check_path(struct vfs_handle_struct *handle,
356 const char *service_path,
359 return NT_STATUS_NOT_SUPPORTED;
362 static NTSTATUS vfswrap_snap_create(struct vfs_handle_struct *handle,
364 const char *base_volume,
370 return NT_STATUS_NOT_SUPPORTED;
373 static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle,
378 return NT_STATUS_NOT_SUPPORTED;
381 /* Directory operations */
383 static DIR *vfswrap_opendir(vfs_handle_struct *handle,
384 const struct smb_filename *smb_fname,
390 START_PROFILE(syscall_opendir);
391 result = opendir(smb_fname->base_name);
392 END_PROFILE(syscall_opendir);
396 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
403 START_PROFILE(syscall_fdopendir);
404 result = sys_fdopendir(fsp->fh->fd);
405 END_PROFILE(syscall_fdopendir);
410 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
412 SMB_STRUCT_STAT *sbuf)
414 struct dirent *result;
416 START_PROFILE(syscall_readdir);
417 result = readdir(dirp);
418 END_PROFILE(syscall_readdir);
420 /* Default Posix readdir() does not give us stat info.
421 * Set to invalid to indicate we didn't return this info. */
422 SET_STAT_INVALID(*sbuf);
423 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
424 if (result != NULL) {
425 /* See if we can efficiently return this. */
427 int flags = AT_SYMLINK_NOFOLLOW;
428 int ret = fstatat(dirfd(dirp),
433 * As this is an optimization,
434 * ignore it if we stat'ed a
435 * symlink. Make the caller
436 * do it again as we don't
437 * know if they wanted the link
438 * info, or its target info.
440 if ((ret == 0) && (!S_ISLNK(st.st_mode))) {
441 init_stat_ex_from_stat(sbuf,
443 lp_fake_directory_create_times(
444 SNUM(handle->conn)));
452 static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
453 const struct smb_filename *fname,
455 struct readdir_attr_data **attr_data)
457 return NT_STATUS_NOT_SUPPORTED;
460 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
462 START_PROFILE(syscall_seekdir);
463 seekdir(dirp, offset);
464 END_PROFILE(syscall_seekdir);
467 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
470 START_PROFILE(syscall_telldir);
471 result = telldir(dirp);
472 END_PROFILE(syscall_telldir);
476 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
478 START_PROFILE(syscall_rewinddir);
480 END_PROFILE(syscall_rewinddir);
483 static int vfswrap_mkdir(vfs_handle_struct *handle,
484 const struct smb_filename *smb_fname,
488 bool has_dacl = False;
489 const char *path = smb_fname->base_name;
492 START_PROFILE(syscall_mkdir);
494 if (lp_inherit_acls(SNUM(handle->conn))
495 && parent_dirname(talloc_tos(), path, &parent, NULL)
496 && (has_dacl = directory_has_default_acl(handle->conn, parent))) {
497 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
502 result = mkdir(path, mode);
504 if (result == 0 && !has_dacl) {
506 * We need to do this as the default behavior of POSIX ACLs
507 * is to set the mask to be the requested group permission
508 * bits, not the group permission bits to be the requested
509 * group permission bits. This is not what we want, as it will
510 * mess up any inherited ACL bits that were set. JRA.
512 int saved_errno = errno; /* We may get ENOSYS */
513 if ((SMB_VFS_CHMOD_ACL(handle->conn, smb_fname, mode) == -1) &&
519 END_PROFILE(syscall_mkdir);
523 static int vfswrap_rmdir(vfs_handle_struct *handle,
524 const struct smb_filename *smb_fname)
528 START_PROFILE(syscall_rmdir);
529 result = rmdir(smb_fname->base_name);
530 END_PROFILE(syscall_rmdir);
534 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
538 START_PROFILE(syscall_closedir);
539 result = closedir(dirp);
540 END_PROFILE(syscall_closedir);
544 static void vfswrap_init_search_op(vfs_handle_struct *handle,
547 /* Default behavior is a NOOP */
550 /* File operations */
552 static int vfswrap_open(vfs_handle_struct *handle,
553 struct smb_filename *smb_fname,
554 files_struct *fsp, int flags, mode_t mode)
558 START_PROFILE(syscall_open);
560 if (smb_fname->stream_name) {
565 result = open(smb_fname->base_name, flags, mode);
567 END_PROFILE(syscall_open);
571 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
572 struct smb_request *req,
573 uint16_t root_dir_fid,
574 struct smb_filename *smb_fname,
575 uint32_t access_mask,
576 uint32_t share_access,
577 uint32_t create_disposition,
578 uint32_t create_options,
579 uint32_t file_attributes,
580 uint32_t oplock_request,
581 struct smb2_lease *lease,
582 uint64_t allocation_size,
583 uint32_t private_flags,
584 struct security_descriptor *sd,
585 struct ea_list *ea_list,
586 files_struct **result,
588 const struct smb2_create_blobs *in_context_blobs,
589 struct smb2_create_blobs *out_context_blobs)
591 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
592 access_mask, share_access,
593 create_disposition, create_options,
594 file_attributes, oplock_request, lease,
595 allocation_size, private_flags,
597 pinfo, in_context_blobs, out_context_blobs);
600 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
604 START_PROFILE(syscall_close);
605 result = fd_close_posix(fsp);
606 END_PROFILE(syscall_close);
610 static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
614 START_PROFILE_BYTES(syscall_read, n);
615 result = sys_read(fsp->fh->fd, data, n);
616 END_PROFILE_BYTES(syscall_read);
620 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
621 size_t n, off_t offset)
625 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
626 START_PROFILE_BYTES(syscall_pread, n);
627 result = sys_pread(fsp->fh->fd, data, n, offset);
628 END_PROFILE_BYTES(syscall_pread);
630 if (result == -1 && errno == ESPIPE) {
631 /* Maintain the fiction that pipes can be seeked (sought?) on. */
632 result = SMB_VFS_READ(fsp, data, n);
636 #else /* HAVE_PREAD */
640 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
641 if (curr == -1 && errno == ESPIPE) {
642 /* Maintain the fiction that pipes can be seeked (sought?) on. */
643 result = SMB_VFS_READ(fsp, data, n);
648 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
653 result = SMB_VFS_READ(fsp, data, n);
656 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
659 #endif /* HAVE_PREAD */
664 static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
668 START_PROFILE_BYTES(syscall_write, n);
669 result = sys_write(fsp->fh->fd, data, n);
670 END_PROFILE_BYTES(syscall_write);
674 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
675 size_t n, off_t offset)
679 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
680 START_PROFILE_BYTES(syscall_pwrite, n);
681 result = sys_pwrite(fsp->fh->fd, data, n, offset);
682 END_PROFILE_BYTES(syscall_pwrite);
684 if (result == -1 && errno == ESPIPE) {
685 /* Maintain the fiction that pipes can be sought on. */
686 result = SMB_VFS_WRITE(fsp, data, n);
689 #else /* HAVE_PWRITE */
693 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
698 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
702 result = SMB_VFS_WRITE(fsp, data, n);
705 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
708 #endif /* HAVE_PWRITE */
713 static int vfswrap_init_pool(struct smbd_server_connection *conn)
717 if (conn->pool != NULL) {
721 ret = pthreadpool_tevent_init(conn, lp_aio_max_threads(),
726 struct vfswrap_pread_state {
734 struct vfs_aio_state vfs_aio_state;
735 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
738 static void vfs_pread_do(void *private_data);
739 static void vfs_pread_done(struct tevent_req *subreq);
741 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
743 struct tevent_context *ev,
744 struct files_struct *fsp,
746 size_t n, off_t offset)
748 struct tevent_req *req, *subreq;
749 struct vfswrap_pread_state *state;
752 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
757 ret = vfswrap_init_pool(handle->conn->sconn);
758 if (tevent_req_error(req, ret)) {
759 return tevent_req_post(req, ev);
763 state->fd = fsp->fh->fd;
766 state->offset = offset;
768 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
769 state->profile_bytes, n);
770 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
772 subreq = pthreadpool_tevent_job_send(
773 state, ev, handle->conn->sconn->pool,
774 vfs_pread_do, state);
775 if (tevent_req_nomem(subreq, req)) {
776 return tevent_req_post(req, ev);
778 tevent_req_set_callback(subreq, vfs_pread_done, req);
783 static void vfs_pread_do(void *private_data)
785 struct vfswrap_pread_state *state = talloc_get_type_abort(
786 private_data, struct vfswrap_pread_state);
787 struct timespec start_time;
788 struct timespec end_time;
790 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
792 PROFILE_TIMESTAMP(&start_time);
795 state->ret = pread(state->fd, state->buf, state->count,
797 } while ((state->ret == -1) && (errno == EINTR));
801 PROFILE_TIMESTAMP(&end_time);
803 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
805 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
808 static void vfs_pread_done(struct tevent_req *subreq)
810 struct tevent_req *req = tevent_req_callback_data(
811 subreq, struct tevent_req);
813 struct vfswrap_pread_state *state = tevent_req_data(
814 req, struct vfswrap_pread_state);
818 ret = pthreadpool_tevent_job_recv(subreq);
820 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
821 if (tevent_req_error(req, ret)) {
825 tevent_req_done(req);
828 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
829 struct vfs_aio_state *vfs_aio_state)
831 struct vfswrap_pread_state *state = tevent_req_data(
832 req, struct vfswrap_pread_state);
834 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
838 *vfs_aio_state = state->vfs_aio_state;
842 struct vfswrap_pwrite_state {
850 struct vfs_aio_state vfs_aio_state;
851 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
854 static void vfs_pwrite_do(void *private_data);
855 static void vfs_pwrite_done(struct tevent_req *subreq);
857 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
859 struct tevent_context *ev,
860 struct files_struct *fsp,
862 size_t n, off_t offset)
864 struct tevent_req *req, *subreq;
865 struct vfswrap_pwrite_state *state;
868 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
873 ret = vfswrap_init_pool(handle->conn->sconn);
874 if (tevent_req_error(req, ret)) {
875 return tevent_req_post(req, ev);
879 state->fd = fsp->fh->fd;
882 state->offset = offset;
884 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
885 state->profile_bytes, n);
886 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
888 subreq = pthreadpool_tevent_job_send(
889 state, ev, handle->conn->sconn->pool,
890 vfs_pwrite_do, state);
891 if (tevent_req_nomem(subreq, req)) {
892 return tevent_req_post(req, ev);
894 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
899 static void vfs_pwrite_do(void *private_data)
901 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
902 private_data, struct vfswrap_pwrite_state);
903 struct timespec start_time;
904 struct timespec end_time;
906 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
908 PROFILE_TIMESTAMP(&start_time);
911 state->ret = pwrite(state->fd, state->buf, state->count,
913 } while ((state->ret == -1) && (errno == EINTR));
917 PROFILE_TIMESTAMP(&end_time);
919 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
921 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
924 static void vfs_pwrite_done(struct tevent_req *subreq)
926 struct tevent_req *req = tevent_req_callback_data(
927 subreq, struct tevent_req);
929 struct vfswrap_pwrite_state *state = tevent_req_data(
930 req, struct vfswrap_pwrite_state);
934 ret = pthreadpool_tevent_job_recv(subreq);
936 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
937 if (tevent_req_error(req, ret)) {
941 tevent_req_done(req);
944 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
945 struct vfs_aio_state *vfs_aio_state)
947 struct vfswrap_pwrite_state *state = tevent_req_data(
948 req, struct vfswrap_pwrite_state);
950 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
954 *vfs_aio_state = state->vfs_aio_state;
958 struct vfswrap_fsync_state {
963 struct vfs_aio_state vfs_aio_state;
964 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
967 static void vfs_fsync_do(void *private_data);
968 static void vfs_fsync_done(struct tevent_req *subreq);
970 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
972 struct tevent_context *ev,
973 struct files_struct *fsp)
975 struct tevent_req *req, *subreq;
976 struct vfswrap_fsync_state *state;
979 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
984 ret = vfswrap_init_pool(handle->conn->sconn);
985 if (tevent_req_error(req, ret)) {
986 return tevent_req_post(req, ev);
990 state->fd = fsp->fh->fd;
992 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
993 state->profile_basic);
995 subreq = pthreadpool_tevent_job_send(
996 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
997 if (tevent_req_nomem(subreq, req)) {
998 return tevent_req_post(req, ev);
1000 tevent_req_set_callback(subreq, vfs_fsync_done, req);
1005 static void vfs_fsync_do(void *private_data)
1007 struct vfswrap_fsync_state *state = talloc_get_type_abort(
1008 private_data, struct vfswrap_fsync_state);
1009 struct timespec start_time;
1010 struct timespec end_time;
1012 PROFILE_TIMESTAMP(&start_time);
1015 state->ret = fsync(state->fd);
1016 } while ((state->ret == -1) && (errno == EINTR));
1020 PROFILE_TIMESTAMP(&end_time);
1022 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1025 static void vfs_fsync_done(struct tevent_req *subreq)
1027 struct tevent_req *req = tevent_req_callback_data(
1028 subreq, struct tevent_req);
1030 struct vfswrap_fsync_state *state = tevent_req_data(
1031 req, struct vfswrap_fsync_state);
1035 ret = pthreadpool_tevent_job_recv(subreq);
1036 TALLOC_FREE(subreq);
1037 SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
1038 if (tevent_req_error(req, ret)) {
1042 tevent_req_done(req);
1045 static int vfswrap_fsync_recv(struct tevent_req *req,
1046 struct vfs_aio_state *vfs_aio_state)
1048 struct vfswrap_fsync_state *state = tevent_req_data(
1049 req, struct vfswrap_fsync_state);
1051 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1055 *vfs_aio_state = state->vfs_aio_state;
1059 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1063 START_PROFILE(syscall_lseek);
1065 /* Cope with 'stat' file opens. */
1066 if (fsp->fh->fd != -1)
1067 result = lseek(fsp->fh->fd, offset, whence);
1070 * We want to maintain the fiction that we can seek
1071 * on a fifo for file system purposes. This allows
1072 * people to set up UNIX fifo's that feed data to Windows
1073 * applications. JRA.
1076 if((result == -1) && (errno == ESPIPE)) {
1081 END_PROFILE(syscall_lseek);
1085 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1086 off_t offset, size_t n)
1090 START_PROFILE_BYTES(syscall_sendfile, n);
1091 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
1092 END_PROFILE_BYTES(syscall_sendfile);
1096 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1098 files_struct *tofsp,
1104 START_PROFILE_BYTES(syscall_recvfile, n);
1105 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
1106 END_PROFILE_BYTES(syscall_recvfile);
1110 static int vfswrap_rename(vfs_handle_struct *handle,
1111 const struct smb_filename *smb_fname_src,
1112 const struct smb_filename *smb_fname_dst)
1116 START_PROFILE(syscall_rename);
1118 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
1123 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
1126 END_PROFILE(syscall_rename);
1130 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
1135 START_PROFILE(syscall_fsync);
1136 result = fsync(fsp->fh->fd);
1137 END_PROFILE(syscall_fsync);
1144 static int vfswrap_stat(vfs_handle_struct *handle,
1145 struct smb_filename *smb_fname)
1149 START_PROFILE(syscall_stat);
1151 if (smb_fname->stream_name) {
1156 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1157 lp_fake_directory_create_times(SNUM(handle->conn)));
1159 END_PROFILE(syscall_stat);
1163 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1167 START_PROFILE(syscall_fstat);
1168 result = sys_fstat(fsp->fh->fd,
1169 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1170 END_PROFILE(syscall_fstat);
1174 static int vfswrap_lstat(vfs_handle_struct *handle,
1175 struct smb_filename *smb_fname)
1179 START_PROFILE(syscall_lstat);
1181 if (smb_fname->stream_name) {
1186 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1187 lp_fake_directory_create_times(SNUM(handle->conn)));
1189 END_PROFILE(syscall_lstat);
1193 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1195 enum vfs_translate_direction direction,
1196 TALLOC_CTX *mem_ctx,
1199 return NT_STATUS_NONE_MAPPED;
1203 * Implement the default fsctl operation.
1205 static bool vfswrap_logged_ioctl_message = false;
1207 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1208 struct files_struct *fsp,
1211 uint16_t req_flags, /* Needed for UNICODE ... */
1212 const uint8_t *_in_data,
1214 uint8_t **_out_data,
1215 uint32_t max_out_len,
1218 const char *in_data = (const char *)_in_data;
1219 char **out_data = (char **)_out_data;
1223 case FSCTL_SET_SPARSE:
1225 bool set_sparse = true;
1227 if (in_len >= 1 && in_data[0] == 0) {
1231 status = file_set_sparse(handle->conn, fsp, set_sparse);
1233 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1234 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1235 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1236 nt_errstr(status)));
1241 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1243 unsigned char objid[16];
1244 char *return_data = NULL;
1246 /* This should return the object-id on this file.
1247 * I think I'll make this be the inode+dev. JRA.
1250 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1251 fsp_fnum_dbg(fsp)));
1253 *out_len = MIN(max_out_len, 64);
1255 /* Hmmm, will this cause problems if less data asked for? */
1256 return_data = talloc_array(ctx, char, 64);
1257 if (return_data == NULL) {
1258 return NT_STATUS_NO_MEMORY;
1261 /* For backwards compatibility only store the dev/inode. */
1262 push_file_id_16(return_data, &fsp->file_id);
1263 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1264 push_file_id_16(return_data+32, &fsp->file_id);
1265 memset(return_data+48, 0, 16);
1266 *out_data = return_data;
1267 return NT_STATUS_OK;
1270 case FSCTL_GET_REPARSE_POINT:
1272 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1273 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1274 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1275 return NT_STATUS_NOT_A_REPARSE_POINT;
1278 case FSCTL_SET_REPARSE_POINT:
1280 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1281 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1282 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1283 return NT_STATUS_NOT_A_REPARSE_POINT;
1286 case FSCTL_GET_SHADOW_COPY_DATA:
1289 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1290 * and return their volume names. If max_data_count is 16, then it is just
1291 * asking for the number of volumes and length of the combined names.
1293 * pdata is the data allocated by our caller, but that uses
1294 * total_data_count (which is 0 in our case) rather than max_data_count.
1295 * Allocate the correct amount and return the pointer to let
1296 * it be deallocated when we return.
1298 struct shadow_copy_data *shadow_data = NULL;
1299 bool labels = False;
1300 uint32_t labels_data_count = 0;
1302 char *cur_pdata = NULL;
1304 if (max_out_len < 16) {
1305 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1307 return NT_STATUS_INVALID_PARAMETER;
1310 if (max_out_len > 16) {
1314 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1315 if (shadow_data == NULL) {
1316 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1317 return NT_STATUS_NO_MEMORY;
1321 * Call the VFS routine to actually do the work.
1323 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1326 /* broken module didn't set errno on error */
1327 status = NT_STATUS_UNSUCCESSFUL;
1329 status = map_nt_error_from_unix(errno);
1330 if (NT_STATUS_EQUAL(status,
1331 NT_STATUS_NOT_SUPPORTED)) {
1335 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1336 "connectpath %s, failed - %s.\n",
1337 fsp->conn->connectpath,
1338 nt_errstr(status)));
1339 TALLOC_FREE(shadow_data);
1343 labels_data_count = (shadow_data->num_volumes * 2 *
1344 sizeof(SHADOW_COPY_LABEL)) + 2;
1349 *out_len = 12 + labels_data_count;
1352 if (max_out_len < *out_len) {
1353 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1354 max_out_len, *out_len));
1355 TALLOC_FREE(shadow_data);
1356 return NT_STATUS_BUFFER_TOO_SMALL;
1359 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1360 if (cur_pdata == NULL) {
1361 TALLOC_FREE(shadow_data);
1362 return NT_STATUS_NO_MEMORY;
1365 *out_data = cur_pdata;
1367 /* num_volumes 4 bytes */
1368 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1371 /* num_labels 4 bytes */
1372 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1375 /* needed_data_count 4 bytes */
1376 SIVAL(cur_pdata, 8, labels_data_count);
1380 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1381 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1382 if (labels && shadow_data->labels) {
1383 for (i=0; i<shadow_data->num_volumes; i++) {
1385 status = srvstr_push(cur_pdata, req_flags,
1386 cur_pdata, shadow_data->labels[i],
1387 2 * sizeof(SHADOW_COPY_LABEL),
1388 STR_UNICODE|STR_TERMINATE, &len);
1389 if (!NT_STATUS_IS_OK(status)) {
1390 TALLOC_FREE(*out_data);
1391 TALLOC_FREE(shadow_data);
1394 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1395 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1399 TALLOC_FREE(shadow_data);
1401 return NT_STATUS_OK;
1404 case FSCTL_FIND_FILES_BY_SID:
1406 /* pretend this succeeded -
1408 * we have to send back a list with all files owned by this SID
1410 * but I have to check that --metze
1416 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1417 fsp_fnum_dbg(fsp)));
1420 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1421 return NT_STATUS_INVALID_PARAMETER;
1424 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1426 /* unknown 4 bytes: this is not the length of the sid :-( */
1427 /*unknown = IVAL(pdata,0);*/
1429 if (!sid_parse(_in_data + 4, sid_len, &sid)) {
1430 return NT_STATUS_INVALID_PARAMETER;
1432 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1434 if (!sid_to_uid(&sid, &uid)) {
1435 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1436 sid_string_dbg(&sid),
1437 (unsigned long)sid_len));
1441 /* we can take a look at the find source :-)
1443 * find ./ -uid $uid -name '*' is what we need here
1446 * and send 4bytes len and then NULL terminated unicode strings
1449 * but I don't know how to deal with the paged results
1450 * (maybe we can hang the result anywhere in the fsp struct)
1452 * but I don't know how to deal with the paged results
1453 * (maybe we can hang the result anywhere in the fsp struct)
1455 * we don't send all files at once
1456 * and at the next we should *not* start from the beginning,
1457 * so we have to cache the result
1462 /* this works for now... */
1463 return NT_STATUS_OK;
1466 case FSCTL_QUERY_ALLOCATED_RANGES:
1468 /* FIXME: This is just a dummy reply, telling that all of the
1469 * file is allocated. MKS cp needs that.
1470 * Adding the real allocated ranges via FIEMAP on Linux
1471 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1472 * this FSCTL correct for sparse files.
1474 uint64_t offset, length;
1475 char *out_data_tmp = NULL;
1478 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1480 return NT_STATUS_INVALID_PARAMETER;
1483 if (max_out_len < 16) {
1484 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1486 return NT_STATUS_INVALID_PARAMETER;
1489 offset = BVAL(in_data,0);
1490 length = BVAL(in_data,8);
1492 if (offset + length < offset) {
1493 /* No 64-bit integer wrap. */
1494 return NT_STATUS_INVALID_PARAMETER;
1497 /* Shouldn't this be SMB_VFS_STAT ... ? */
1498 status = vfs_stat_fsp(fsp);
1499 if (!NT_STATUS_IS_OK(status)) {
1504 out_data_tmp = talloc_array(ctx, char, *out_len);
1505 if (out_data_tmp == NULL) {
1506 DEBUG(10, ("unable to allocate memory for response\n"));
1507 return NT_STATUS_NO_MEMORY;
1510 if (offset > fsp->fsp_name->st.st_ex_size ||
1511 fsp->fsp_name->st.st_ex_size == 0 ||
1513 memset(out_data_tmp, 0, *out_len);
1515 uint64_t end = offset + length;
1516 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1517 SBVAL(out_data_tmp, 0, 0);
1518 SBVAL(out_data_tmp, 8, end);
1521 *out_data = out_data_tmp;
1523 return NT_STATUS_OK;
1526 case FSCTL_IS_VOLUME_DIRTY:
1528 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1529 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1531 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1532 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1534 return NT_STATUS_INVALID_PARAMETER;
1539 * Only print once ... unfortunately there could be lots of
1540 * different FSCTLs that are called.
1542 if (!vfswrap_logged_ioctl_message) {
1543 vfswrap_logged_ioctl_message = true;
1544 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1545 __func__, function));
1549 return NT_STATUS_NOT_SUPPORTED;
1552 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
1553 const struct smb_filename *fname,
1554 SMB_STRUCT_STAT *sbuf);
1556 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1557 struct smb_filename *smb_fname,
1562 offline = vfswrap_is_offline(handle, smb_fname, &smb_fname->st);
1564 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1567 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1570 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1571 struct files_struct *fsp,
1576 offline = vfswrap_is_offline(handle, fsp->fsp_name, &fsp->fsp_name->st);
1578 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1581 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1584 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1585 const struct smb_filename *smb_fname,
1588 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1591 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1592 struct files_struct *fsp,
1595 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1598 struct vfs_cc_state {
1599 struct tevent_context *ev;
1601 bool read_lck_locked;
1602 struct lock_struct read_lck;
1603 bool write_lck_locked;
1604 struct lock_struct write_lck;
1605 struct files_struct *src_fsp;
1607 struct files_struct *dst_fsp;
1611 size_t next_io_size;
1615 static NTSTATUS copy_chunk_loop(struct tevent_req *req);
1617 static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *handle,
1618 TALLOC_CTX *mem_ctx,
1619 struct tevent_context *ev,
1620 struct files_struct *src_fsp,
1622 struct files_struct *dest_fsp,
1627 struct tevent_req *req;
1628 struct vfs_cc_state *state = NULL;
1629 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
1632 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
1634 req = tevent_req_create(mem_ctx, &state, struct vfs_cc_state);
1639 if (flags & ~VFS_COPY_CHUNK_FL_MASK_ALL) {
1640 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1641 return tevent_req_post(req, ev);
1644 if (flags & VFS_COPY_CHUNK_FL_MUST_CLONE) {
1645 DEBUG(10, ("COW clones not supported by vfs_default\n"));
1646 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1647 return tevent_req_post(req, ev);
1650 *state = (struct vfs_cc_state) {
1654 .dst_fsp = dest_fsp,
1655 .dst_off = dest_off,
1657 .remaining = to_copy,
1660 state->buf = talloc_array(state, uint8_t, num);
1661 if (tevent_req_nomem(state->buf, req)) {
1662 return tevent_req_post(req, ev);
1665 status = vfs_stat_fsp(src_fsp);
1666 if (tevent_req_nterror(req, status)) {
1667 return tevent_req_post(req, ev);
1670 if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
1672 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1673 * If the SourceOffset or SourceOffset + Length extends beyond
1674 * the end of file, the server SHOULD<240> treat this as a
1675 * STATUS_END_OF_FILE error.
1677 * <240> Section 3.3.5.15.6: Windows servers will return
1678 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1680 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1681 return tevent_req_post(req, ev);
1684 if (src_fsp->op == NULL) {
1685 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1686 return tevent_req_post(req, ev);
1689 if (dest_fsp->op == NULL) {
1690 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1691 return tevent_req_post(req, ev);
1694 status = copy_chunk_loop(req);
1695 if (!NT_STATUS_IS_OK(status)) {
1696 tevent_req_nterror(req, status);
1697 return tevent_req_post(req, ev);
1703 static void vfswrap_copy_chunk_read_done(struct tevent_req *subreq);
1705 static NTSTATUS copy_chunk_loop(struct tevent_req *req)
1707 struct vfs_cc_state *state = tevent_req_data(req, struct vfs_cc_state);
1708 struct tevent_req *subreq = NULL;
1711 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
1713 if (!(state->flags & VFS_COPY_CHUNK_FL_IGNORE_LOCKS)) {
1714 init_strict_lock_struct(state->src_fsp,
1715 state->src_fsp->op->global->open_persistent_id,
1717 state->next_io_size,
1721 ok = SMB_VFS_STRICT_LOCK(state->src_fsp->conn,
1725 return NT_STATUS_FILE_LOCK_CONFLICT;
1729 subreq = SMB_VFS_PREAD_SEND(state,
1730 state->src_fsp->conn->sconn->ev_ctx,
1733 state->next_io_size,
1735 if (subreq == NULL) {
1736 return NT_STATUS_NO_MEMORY;
1738 tevent_req_set_callback(subreq, vfswrap_copy_chunk_read_done, req);
1740 return NT_STATUS_OK;
1743 static void vfswrap_copy_chunk_write_done(struct tevent_req *subreq);
1745 static void vfswrap_copy_chunk_read_done(struct tevent_req *subreq)
1747 struct tevent_req *req = tevent_req_callback_data(
1748 subreq, struct tevent_req);
1749 struct vfs_cc_state *state = tevent_req_data(req, struct vfs_cc_state);
1750 struct vfs_aio_state aio_state;
1754 if (!(state->flags & VFS_COPY_CHUNK_FL_IGNORE_LOCKS)) {
1755 SMB_VFS_STRICT_UNLOCK(state->src_fsp->conn,
1758 ZERO_STRUCT(state->read_lck);
1761 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
1762 TALLOC_FREE(subreq);
1764 DBG_ERR("read failed: %s\n", strerror(errno));
1765 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1768 if (nread != state->next_io_size) {
1769 DBG_ERR("Short read, only %zd of %zu\n",
1770 nread, state->next_io_size);
1771 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1775 state->src_off += nread;
1777 if (!(state->flags & VFS_COPY_CHUNK_FL_IGNORE_LOCKS)) {
1778 init_strict_lock_struct(state->dst_fsp,
1779 state->dst_fsp->op->global->open_persistent_id,
1781 state->next_io_size,
1785 ok = SMB_VFS_STRICT_LOCK(state->dst_fsp->conn,
1789 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1794 subreq = SMB_VFS_PWRITE_SEND(state,
1798 state->next_io_size,
1800 if (subreq == NULL) {
1801 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1804 tevent_req_set_callback(subreq, vfswrap_copy_chunk_write_done, req);
1807 static void vfswrap_copy_chunk_write_done(struct tevent_req *subreq)
1809 struct tevent_req *req = tevent_req_callback_data(
1810 subreq, struct tevent_req);
1811 struct vfs_cc_state *state = tevent_req_data(req, struct vfs_cc_state);
1812 struct vfs_aio_state aio_state;
1816 if (!(state->flags & VFS_COPY_CHUNK_FL_IGNORE_LOCKS)) {
1817 SMB_VFS_STRICT_UNLOCK(state->dst_fsp->conn,
1820 ZERO_STRUCT(state->write_lck);
1823 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
1824 TALLOC_FREE(subreq);
1825 if (nwritten == -1) {
1826 DBG_ERR("write failed: %s\n", strerror(errno));
1827 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1830 if (nwritten != state->next_io_size) {
1831 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
1832 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1836 state->dst_off += nwritten;
1838 if (state->remaining < nwritten) {
1839 /* Paranoia check */
1840 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1843 state->remaining -= nwritten;
1844 if (state->remaining == 0) {
1845 tevent_req_done(req);
1849 status = copy_chunk_loop(req);
1850 if (!NT_STATUS_IS_OK(status)) {
1851 tevent_req_nterror(req, status);
1858 static NTSTATUS vfswrap_copy_chunk_recv(struct vfs_handle_struct *handle,
1859 struct tevent_req *req,
1862 struct vfs_cc_state *state = tevent_req_data(req, struct vfs_cc_state);
1865 if (tevent_req_is_nterror(req, &status)) {
1866 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
1868 tevent_req_received(req);
1872 *copied = state->to_copy;
1873 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
1874 tevent_req_received(req);
1876 return NT_STATUS_OK;
1879 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1880 TALLOC_CTX *mem_ctx,
1881 struct files_struct *fsp,
1882 struct smb_filename *smb_fname,
1883 uint16_t *_compression_fmt)
1885 return NT_STATUS_INVALID_DEVICE_REQUEST;
1888 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1889 TALLOC_CTX *mem_ctx,
1890 struct files_struct *fsp,
1891 uint16_t compression_fmt)
1893 return NT_STATUS_INVALID_DEVICE_REQUEST;
1896 /********************************************************************
1897 Given a stat buffer return the allocated size on disk, taking into
1898 account sparse files.
1899 ********************************************************************/
1900 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1901 struct files_struct *fsp,
1902 const SMB_STRUCT_STAT *sbuf)
1906 START_PROFILE(syscall_get_alloc_size);
1908 if(S_ISDIR(sbuf->st_ex_mode)) {
1913 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1914 /* The type of st_blocksize is blkcnt_t which *MUST* be
1915 signed (according to POSIX) and can be less than 64-bits.
1916 Ensure when we're converting to 64 bits wide we don't
1918 #if defined(SIZEOF_BLKCNT_T_8)
1919 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1920 #elif defined(SIZEOF_BLKCNT_T_4)
1922 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1923 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1926 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1930 * Some file systems do not allocate a block for very
1931 * small files. But for non-empty file should report a
1935 uint64_t filesize = get_file_size_stat(sbuf);
1937 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
1941 result = get_file_size_stat(sbuf);
1944 if (fsp && fsp->initial_allocation_size)
1945 result = MAX(result,fsp->initial_allocation_size);
1947 result = smb_roundup(handle->conn, result);
1950 END_PROFILE(syscall_get_alloc_size);
1954 static int vfswrap_unlink(vfs_handle_struct *handle,
1955 const struct smb_filename *smb_fname)
1959 START_PROFILE(syscall_unlink);
1961 if (smb_fname->stream_name) {
1965 result = unlink(smb_fname->base_name);
1968 END_PROFILE(syscall_unlink);
1972 static int vfswrap_chmod(vfs_handle_struct *handle,
1973 const struct smb_filename *smb_fname,
1978 START_PROFILE(syscall_chmod);
1981 * We need to do this due to the fact that the default POSIX ACL
1982 * chmod modifies the ACL *mask* for the group owner, not the
1983 * group owner bits directly. JRA.
1988 int saved_errno = errno; /* We might get ENOSYS */
1989 result = SMB_VFS_CHMOD_ACL(handle->conn,
1993 END_PROFILE(syscall_chmod);
1996 /* Error - return the old errno. */
1997 errno = saved_errno;
2000 result = chmod(smb_fname->base_name, mode);
2001 END_PROFILE(syscall_chmod);
2005 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2009 START_PROFILE(syscall_fchmod);
2012 * We need to do this due to the fact that the default POSIX ACL
2013 * chmod modifies the ACL *mask* for the group owner, not the
2014 * group owner bits directly. JRA.
2018 int saved_errno = errno; /* We might get ENOSYS */
2019 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
2020 END_PROFILE(syscall_fchmod);
2023 /* Error - return the old errno. */
2024 errno = saved_errno;
2027 #if defined(HAVE_FCHMOD)
2028 result = fchmod(fsp->fh->fd, mode);
2034 END_PROFILE(syscall_fchmod);
2038 static int vfswrap_chown(vfs_handle_struct *handle,
2039 const struct smb_filename *smb_fname,
2045 START_PROFILE(syscall_chown);
2046 result = chown(smb_fname->base_name, uid, gid);
2047 END_PROFILE(syscall_chown);
2051 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2056 START_PROFILE(syscall_fchown);
2057 result = fchown(fsp->fh->fd, uid, gid);
2058 END_PROFILE(syscall_fchown);
2066 static int vfswrap_lchown(vfs_handle_struct *handle,
2067 const struct smb_filename *smb_fname,
2073 START_PROFILE(syscall_lchown);
2074 result = lchown(smb_fname->base_name, uid, gid);
2075 END_PROFILE(syscall_lchown);
2079 static int vfswrap_chdir(vfs_handle_struct *handle, const char *path)
2083 START_PROFILE(syscall_chdir);
2084 result = chdir(path);
2085 END_PROFILE(syscall_chdir);
2089 static char *vfswrap_getwd(vfs_handle_struct *handle)
2093 START_PROFILE(syscall_getwd);
2094 result = sys_getwd();
2095 END_PROFILE(syscall_getwd);
2099 /*********************************************************************
2100 nsec timestamp resolution call. Convert down to whatever the underlying
2101 system will support.
2102 **********************************************************************/
2104 static int vfswrap_ntimes(vfs_handle_struct *handle,
2105 const struct smb_filename *smb_fname,
2106 struct smb_file_time *ft)
2110 START_PROFILE(syscall_ntimes);
2112 if (smb_fname->stream_name) {
2118 if (null_timespec(ft->atime)) {
2119 ft->atime= smb_fname->st.st_ex_atime;
2122 if (null_timespec(ft->mtime)) {
2123 ft->mtime = smb_fname->st.st_ex_mtime;
2126 if (!null_timespec(ft->create_time)) {
2127 set_create_timespec_ea(handle->conn,
2132 if ((timespec_compare(&ft->atime,
2133 &smb_fname->st.st_ex_atime) == 0) &&
2134 (timespec_compare(&ft->mtime,
2135 &smb_fname->st.st_ex_mtime) == 0)) {
2140 #if defined(HAVE_UTIMENSAT)
2142 struct timespec ts[2];
2145 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2147 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2149 if (!((result == -1) && (errno == ENOSYS))) {
2153 #if defined(HAVE_UTIMES)
2155 struct timeval tv[2];
2156 tv[0] = convert_timespec_to_timeval(ft->atime);
2157 tv[1] = convert_timespec_to_timeval(ft->mtime);
2158 result = utimes(smb_fname->base_name, tv);
2160 result = utimes(smb_fname->base_name, NULL);
2162 if (!((result == -1) && (errno == ENOSYS))) {
2166 #if defined(HAVE_UTIME)
2168 struct utimbuf times;
2169 times.actime = convert_timespec_to_time_t(ft->atime);
2170 times.modtime = convert_timespec_to_time_t(ft->mtime);
2171 result = utime(smb_fname->base_name, ×);
2173 result = utime(smb_fname->base_name, NULL);
2175 if (!((result == -1) && (errno == ENOSYS))) {
2183 END_PROFILE(syscall_ntimes);
2187 /*********************************************************************
2188 A version of ftruncate that will write the space on disk if strict
2190 **********************************************************************/
2192 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2194 off_t space_to_write;
2195 uint64_t space_avail;
2196 uint64_t bsize,dfree,dsize;
2199 SMB_STRUCT_STAT *pst;
2201 status = vfs_stat_fsp(fsp);
2202 if (!NT_STATUS_IS_OK(status)) {
2205 pst = &fsp->fsp_name->st;
2208 if (S_ISFIFO(pst->st_ex_mode))
2212 if (pst->st_ex_size == len)
2215 /* Shrink - just ftruncate. */
2216 if (pst->st_ex_size > len)
2217 return ftruncate(fsp->fh->fd, len);
2219 space_to_write = len - pst->st_ex_size;
2221 /* for allocation try fallocate first. This can fail on some
2222 platforms e.g. when the filesystem doesn't support it and no
2223 emulation is being done by the libc (like on AIX with JFS1). In that
2224 case we do our own emulation. fallocate implementations can
2225 return ENOTSUP or EINVAL in cases like that. */
2226 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2227 if (ret == -1 && errno == ENOSPC) {
2233 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2234 "error %d. Falling back to slow manual allocation\n", errno));
2236 /* available disk space is enough or not? */
2238 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2239 /* space_avail is 1k blocks */
2240 if (space_avail == (uint64_t)-1 ||
2241 ((uint64_t)space_to_write/1024 > space_avail) ) {
2246 /* Write out the real space on disk. */
2247 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2255 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2258 SMB_STRUCT_STAT *pst;
2262 START_PROFILE(syscall_ftruncate);
2264 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2265 result = strict_allocate_ftruncate(handle, fsp, len);
2266 END_PROFILE(syscall_ftruncate);
2270 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2271 ftruncate if the system supports it. Then I discovered that
2272 you can have some filesystems that support ftruncate
2273 expansion and some that don't! On Linux fat can't do
2274 ftruncate extend but ext2 can. */
2276 result = ftruncate(fsp->fh->fd, len);
2278 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2279 extend a file with ftruncate. Provide alternate implementation
2282 /* Do an fstat to see if the file is longer than the requested
2283 size in which case the ftruncate above should have
2284 succeeded or shorter, in which case seek to len - 1 and
2285 write 1 byte of zero */
2286 status = vfs_stat_fsp(fsp);
2287 if (!NT_STATUS_IS_OK(status)) {
2291 /* We need to update the files_struct after successful ftruncate */
2296 pst = &fsp->fsp_name->st;
2299 if (S_ISFIFO(pst->st_ex_mode)) {
2305 if (pst->st_ex_size == len) {
2310 if (pst->st_ex_size > len) {
2311 /* the ftruncate should have worked */
2315 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2323 END_PROFILE(syscall_ftruncate);
2327 static int vfswrap_fallocate(vfs_handle_struct *handle,
2335 START_PROFILE(syscall_fallocate);
2337 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2339 * posix_fallocate returns 0 on success, errno on error
2340 * and doesn't set errno. Make it behave like fallocate()
2341 * which returns -1, and sets errno on failure.
2348 /* sys_fallocate handles filtering of unsupported mode flags */
2349 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2351 END_PROFILE(syscall_fallocate);
2355 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2359 START_PROFILE(syscall_fcntl_lock);
2361 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2363 "force process locks",
2365 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2368 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2369 END_PROFILE(syscall_fcntl_lock);
2373 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2374 uint32_t share_mode, uint32_t access_mask)
2376 START_PROFILE(syscall_kernel_flock);
2377 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2378 END_PROFILE(syscall_kernel_flock);
2382 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2387 START_PROFILE(syscall_fcntl_getlock);
2389 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2391 "force process locks",
2393 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2396 result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2397 END_PROFILE(syscall_fcntl_getlock);
2401 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2406 START_PROFILE(syscall_linux_setlease);
2408 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2409 result = linux_setlease(fsp->fh->fd, leasetype);
2413 END_PROFILE(syscall_linux_setlease);
2417 static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2421 START_PROFILE(syscall_symlink);
2422 result = symlink(oldpath, newpath);
2423 END_PROFILE(syscall_symlink);
2427 static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
2431 START_PROFILE(syscall_readlink);
2432 result = readlink(path, buf, bufsiz);
2433 END_PROFILE(syscall_readlink);
2437 static int vfswrap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2441 START_PROFILE(syscall_link);
2442 result = link(oldpath, newpath);
2443 END_PROFILE(syscall_link);
2447 static int vfswrap_mknod(vfs_handle_struct *handle,
2448 const struct smb_filename *smb_fname,
2454 START_PROFILE(syscall_mknod);
2455 result = sys_mknod(smb_fname->base_name, mode, dev);
2456 END_PROFILE(syscall_mknod);
2460 static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
2464 START_PROFILE(syscall_realpath);
2465 result = sys_realpath(path);
2466 END_PROFILE(syscall_realpath);
2470 static int vfswrap_chflags(vfs_handle_struct *handle,
2471 const struct smb_filename *smb_fname,
2475 return chflags(smb_fname->base_name, flags);
2482 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2483 const SMB_STRUCT_STAT *sbuf)
2487 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2491 key.devid = sbuf->st_ex_dev;
2492 key.inode = sbuf->st_ex_ino;
2493 /* key.extid is unused by default. */
2498 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2499 struct files_struct *fsp,
2500 const struct smb_filename *smb_fname,
2501 TALLOC_CTX *mem_ctx,
2502 unsigned int *pnum_streams,
2503 struct stream_struct **pstreams)
2505 SMB_STRUCT_STAT sbuf;
2506 struct stream_struct *tmp_streams = NULL;
2509 if ((fsp != NULL) && (fsp->is_directory)) {
2511 * No default streams on directories
2516 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2517 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2520 struct smb_filename smb_fname_cp;
2522 ZERO_STRUCT(smb_fname_cp);
2523 smb_fname_cp.base_name = discard_const_p(char,
2524 smb_fname->base_name);
2525 smb_fname_cp.flags = smb_fname->flags;
2527 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
2528 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2530 ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2532 sbuf = smb_fname_cp.st;
2536 return map_nt_error_from_unix(errno);
2539 if (S_ISDIR(sbuf.st_ex_mode)) {
2543 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2544 (*pnum_streams) + 1);
2545 if (tmp_streams == NULL) {
2546 return NT_STATUS_NO_MEMORY;
2548 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2549 if (tmp_streams[*pnum_streams].name == NULL) {
2550 return NT_STATUS_NO_MEMORY;
2552 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2553 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2556 *pstreams = tmp_streams;
2558 return NT_STATUS_OK;
2561 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2564 TALLOC_CTX *mem_ctx,
2568 * Don't fall back to get_real_filename so callers can differentiate
2569 * between a full directory scan and an actual case-insensitive stat.
2575 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2578 return handle->conn->connectpath;
2581 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2582 struct byte_range_lock *br_lck,
2583 struct lock_struct *plock,
2586 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2588 /* Note: blr is not used in the default implementation. */
2589 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2592 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2593 struct messaging_context *msg_ctx,
2594 struct byte_range_lock *br_lck,
2595 const struct lock_struct *plock)
2597 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2599 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2602 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2603 struct byte_range_lock *br_lck,
2604 struct lock_struct *plock)
2606 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2608 /* Note: blr is not used in the default implementation. */
2609 return brl_lock_cancel_default(br_lck, plock);
2612 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2614 struct lock_struct *plock)
2616 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2617 plock->lock_type == WRITE_LOCK);
2619 return strict_lock_default(fsp, plock);
2622 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2624 struct lock_struct *plock)
2626 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2627 plock->lock_type == WRITE_LOCK);
2629 strict_unlock_default(fsp, plock);
2632 /* NT ACL operations. */
2634 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2636 uint32_t security_info,
2637 TALLOC_CTX *mem_ctx,
2638 struct security_descriptor **ppdesc)
2642 START_PROFILE(fget_nt_acl);
2643 result = posix_fget_nt_acl(fsp, security_info,
2645 END_PROFILE(fget_nt_acl);
2649 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2650 const struct smb_filename *smb_fname,
2651 uint32_t security_info,
2652 TALLOC_CTX *mem_ctx,
2653 struct security_descriptor **ppdesc)
2657 START_PROFILE(get_nt_acl);
2658 result = posix_get_nt_acl(handle->conn,
2663 END_PROFILE(get_nt_acl);
2667 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2671 START_PROFILE(fset_nt_acl);
2672 result = set_nt_acl(fsp, security_info_sent, psd);
2673 END_PROFILE(fset_nt_acl);
2677 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2678 struct smb_filename *file,
2679 struct security_acl *sacl,
2680 uint32_t access_requested,
2681 uint32_t access_denied)
2683 return NT_STATUS_OK; /* Nothing to do here ... */
2686 static int vfswrap_chmod_acl(vfs_handle_struct *handle,
2687 const struct smb_filename *smb_fname,
2696 START_PROFILE(chmod_acl);
2697 result = chmod_acl(handle->conn, smb_fname, mode);
2698 END_PROFILE(chmod_acl);
2703 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2711 START_PROFILE(fchmod_acl);
2712 result = fchmod_acl(fsp, mode);
2713 END_PROFILE(fchmod_acl);
2718 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2719 const struct smb_filename *smb_fname,
2720 SMB_ACL_TYPE_T type,
2721 TALLOC_CTX *mem_ctx)
2723 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
2726 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2728 TALLOC_CTX *mem_ctx)
2730 return sys_acl_get_fd(handle, fsp, mem_ctx);
2733 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
2734 const struct smb_filename *smb_fname,
2735 SMB_ACL_TYPE_T acltype,
2738 return sys_acl_set_file(handle, smb_fname, acltype, theacl);
2741 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2743 return sys_acl_set_fd(handle, fsp, theacl);
2746 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
2747 const struct smb_filename *smb_fname)
2749 return sys_acl_delete_def_file(handle, smb_fname);
2752 /****************************************************************
2753 Extended attribute operations.
2754 *****************************************************************/
2756 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
2757 const struct smb_filename *smb_fname,
2762 return getxattr(smb_fname->base_name, name, value, size);
2765 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2767 return fgetxattr(fsp->fh->fd, name, value, size);
2770 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
2771 const struct smb_filename *smb_fname,
2775 return listxattr(smb_fname->base_name, list, size);
2778 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2780 return flistxattr(fsp->fh->fd, list, size);
2783 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
2784 const struct smb_filename *smb_fname,
2787 return removexattr(smb_fname->base_name, name);
2790 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2792 return fremovexattr(fsp->fh->fd, name);
2795 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
2796 const struct smb_filename *smb_fname,
2802 return setxattr(smb_fname->base_name, name, value, size, flags);
2805 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2807 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2810 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2815 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2816 const struct smb_filename *fname,
2817 SMB_STRUCT_STAT *sbuf)
2821 bool offline = false;
2823 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2827 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2828 #if defined(ENOTSUP)
2834 status = get_full_smb_filename(talloc_tos(), fname, &path);
2835 if (!NT_STATUS_IS_OK(status)) {
2836 errno = map_errno_from_nt_status(status);
2840 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2847 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2848 struct files_struct *fsp,
2849 TALLOC_CTX *mem_ctx,
2852 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2855 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2856 struct files_struct *fsp,
2857 const DATA_BLOB old_cookie,
2858 TALLOC_CTX *mem_ctx,
2859 DATA_BLOB *new_cookie)
2861 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2865 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2866 struct smb_request *smb1req,
2867 struct smbXsrv_open *op,
2868 const DATA_BLOB old_cookie,
2869 TALLOC_CTX *mem_ctx,
2870 struct files_struct **fsp,
2871 DATA_BLOB *new_cookie)
2873 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2874 old_cookie, mem_ctx,
2878 static struct vfs_fn_pointers vfs_default_fns = {
2879 /* Disk operations */
2881 .connect_fn = vfswrap_connect,
2882 .disconnect_fn = vfswrap_disconnect,
2883 .disk_free_fn = vfswrap_disk_free,
2884 .get_quota_fn = vfswrap_get_quota,
2885 .set_quota_fn = vfswrap_set_quota,
2886 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2887 .statvfs_fn = vfswrap_statvfs,
2888 .fs_capabilities_fn = vfswrap_fs_capabilities,
2889 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2890 .snap_check_path_fn = vfswrap_snap_check_path,
2891 .snap_create_fn = vfswrap_snap_create,
2892 .snap_delete_fn = vfswrap_snap_delete,
2894 /* Directory operations */
2896 .opendir_fn = vfswrap_opendir,
2897 .fdopendir_fn = vfswrap_fdopendir,
2898 .readdir_fn = vfswrap_readdir,
2899 .readdir_attr_fn = vfswrap_readdir_attr,
2900 .seekdir_fn = vfswrap_seekdir,
2901 .telldir_fn = vfswrap_telldir,
2902 .rewind_dir_fn = vfswrap_rewinddir,
2903 .mkdir_fn = vfswrap_mkdir,
2904 .rmdir_fn = vfswrap_rmdir,
2905 .closedir_fn = vfswrap_closedir,
2906 .init_search_op_fn = vfswrap_init_search_op,
2908 /* File operations */
2910 .open_fn = vfswrap_open,
2911 .create_file_fn = vfswrap_create_file,
2912 .close_fn = vfswrap_close,
2913 .read_fn = vfswrap_read,
2914 .pread_fn = vfswrap_pread,
2915 .pread_send_fn = vfswrap_pread_send,
2916 .pread_recv_fn = vfswrap_pread_recv,
2917 .write_fn = vfswrap_write,
2918 .pwrite_fn = vfswrap_pwrite,
2919 .pwrite_send_fn = vfswrap_pwrite_send,
2920 .pwrite_recv_fn = vfswrap_pwrite_recv,
2921 .lseek_fn = vfswrap_lseek,
2922 .sendfile_fn = vfswrap_sendfile,
2923 .recvfile_fn = vfswrap_recvfile,
2924 .rename_fn = vfswrap_rename,
2925 .fsync_fn = vfswrap_fsync,
2926 .fsync_send_fn = vfswrap_fsync_send,
2927 .fsync_recv_fn = vfswrap_fsync_recv,
2928 .stat_fn = vfswrap_stat,
2929 .fstat_fn = vfswrap_fstat,
2930 .lstat_fn = vfswrap_lstat,
2931 .get_alloc_size_fn = vfswrap_get_alloc_size,
2932 .unlink_fn = vfswrap_unlink,
2933 .chmod_fn = vfswrap_chmod,
2934 .fchmod_fn = vfswrap_fchmod,
2935 .chown_fn = vfswrap_chown,
2936 .fchown_fn = vfswrap_fchown,
2937 .lchown_fn = vfswrap_lchown,
2938 .chdir_fn = vfswrap_chdir,
2939 .getwd_fn = vfswrap_getwd,
2940 .ntimes_fn = vfswrap_ntimes,
2941 .ftruncate_fn = vfswrap_ftruncate,
2942 .fallocate_fn = vfswrap_fallocate,
2943 .lock_fn = vfswrap_lock,
2944 .kernel_flock_fn = vfswrap_kernel_flock,
2945 .linux_setlease_fn = vfswrap_linux_setlease,
2946 .getlock_fn = vfswrap_getlock,
2947 .symlink_fn = vfswrap_symlink,
2948 .readlink_fn = vfswrap_readlink,
2949 .link_fn = vfswrap_link,
2950 .mknod_fn = vfswrap_mknod,
2951 .realpath_fn = vfswrap_realpath,
2952 .chflags_fn = vfswrap_chflags,
2953 .file_id_create_fn = vfswrap_file_id_create,
2954 .streaminfo_fn = vfswrap_streaminfo,
2955 .get_real_filename_fn = vfswrap_get_real_filename,
2956 .connectpath_fn = vfswrap_connectpath,
2957 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2958 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2959 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2960 .strict_lock_fn = vfswrap_strict_lock,
2961 .strict_unlock_fn = vfswrap_strict_unlock,
2962 .translate_name_fn = vfswrap_translate_name,
2963 .fsctl_fn = vfswrap_fsctl,
2964 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
2965 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
2966 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
2967 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
2968 .copy_chunk_send_fn = vfswrap_copy_chunk_send,
2969 .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
2970 .get_compression_fn = vfswrap_get_compression,
2971 .set_compression_fn = vfswrap_set_compression,
2973 /* NT ACL operations. */
2975 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2976 .get_nt_acl_fn = vfswrap_get_nt_acl,
2977 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2978 .audit_file_fn = vfswrap_audit_file,
2980 /* POSIX ACL operations. */
2982 .chmod_acl_fn = vfswrap_chmod_acl,
2983 .fchmod_acl_fn = vfswrap_fchmod_acl,
2985 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2986 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2987 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2988 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2989 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2990 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2991 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2993 /* EA operations. */
2994 .getxattr_fn = vfswrap_getxattr,
2995 .fgetxattr_fn = vfswrap_fgetxattr,
2996 .listxattr_fn = vfswrap_listxattr,
2997 .flistxattr_fn = vfswrap_flistxattr,
2998 .removexattr_fn = vfswrap_removexattr,
2999 .fremovexattr_fn = vfswrap_fremovexattr,
3000 .setxattr_fn = vfswrap_setxattr,
3001 .fsetxattr_fn = vfswrap_fsetxattr,
3003 /* aio operations */
3004 .aio_force_fn = vfswrap_aio_force,
3006 /* durable handle operations */
3007 .durable_cookie_fn = vfswrap_durable_cookie,
3008 .durable_disconnect_fn = vfswrap_durable_disconnect,
3009 .durable_reconnect_fn = vfswrap_durable_reconnect,
3012 NTSTATUS vfs_default_init(TALLOC_CTX *);
3013 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3015 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3016 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);