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"
38 #define DBGC_CLASS DBGC_VFS
40 /* Check for NULL pointer parameters in vfswrap_* functions */
42 /* We don't want to have NULL function pointers lying around. Someone
43 is sure to try and execute them. These stubs are used to prevent
46 static int vfswrap_connect(vfs_handle_struct *handle, const char *service, const char *user)
48 return 0; /* Return >= 0 for success */
51 static void vfswrap_disconnect(vfs_handle_struct *handle)
57 static uint64_t vfswrap_disk_free(vfs_handle_struct *handle, const char *path,
58 uint64_t *bsize, uint64_t *dfree,
61 if (sys_fsusage(path, dfree, dsize) != 0) {
69 static int vfswrap_get_quota(struct vfs_handle_struct *handle, const char *path,
70 enum SMB_QUOTA_TYPE qtype, unid_t id,
73 #ifdef HAVE_SYS_QUOTAS
76 START_PROFILE(syscall_get_quota);
77 result = sys_get_quota(path, qtype, id, qt);
78 END_PROFILE(syscall_get_quota);
86 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
88 #ifdef HAVE_SYS_QUOTAS
91 START_PROFILE(syscall_set_quota);
92 result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
93 END_PROFILE(syscall_set_quota);
101 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
102 struct files_struct *fsp,
103 struct shadow_copy_data *shadow_copy_data,
107 return -1; /* Not implemented. */
110 static int vfswrap_statvfs(struct vfs_handle_struct *handle, const char *path, vfs_statvfs_struct *statbuf)
112 return sys_statvfs(path, statbuf);
115 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
116 enum timestamp_set_resolution *p_ts_res)
118 connection_struct *conn = handle->conn;
119 uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
120 struct smb_filename *smb_fname_cpath = NULL;
121 struct vfs_statvfs_struct statbuf;
124 ZERO_STRUCT(statbuf);
125 ret = sys_statvfs(conn->connectpath, &statbuf);
127 caps = statbuf.FsCapabilities;
130 *p_ts_res = TIMESTAMP_SET_SECONDS;
132 /* Work out what timestamp resolution we can
133 * use when setting a timestamp. */
135 smb_fname_cpath = synthetic_smb_fname(talloc_tos(), conn->connectpath,
137 if (smb_fname_cpath == NULL) {
141 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
143 TALLOC_FREE(smb_fname_cpath);
147 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
148 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
149 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
150 /* If any of the normal UNIX directory timestamps
151 * have a non-zero tv_nsec component assume
152 * we might be able to set sub-second timestamps.
153 * See what filetime set primitives we have.
155 #if defined(HAVE_UTIMENSAT)
156 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
157 #elif defined(HAVE_UTIMES)
158 /* utimes allows msec timestamps to be set. */
159 *p_ts_res = TIMESTAMP_SET_MSEC;
160 #elif defined(HAVE_UTIME)
161 /* utime only allows sec timestamps to be set. */
162 *p_ts_res = TIMESTAMP_SET_SECONDS;
165 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
167 "available on share %s, directory %s\n",
168 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
169 lp_servicename(talloc_tos(), conn->params->service),
170 conn->connectpath ));
172 TALLOC_FREE(smb_fname_cpath);
176 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
177 struct dfs_GetDFSReferral *r)
179 struct junction_map *junction = NULL;
181 bool self_referral = false;
182 char *pathnamep = NULL;
183 char *local_dfs_path = NULL;
186 uint16_t max_referral_level = r->in.req.max_referral_level;
189 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
192 /* get the junction entry */
193 if (r->in.req.servername == NULL) {
194 return NT_STATUS_NOT_FOUND;
198 * Trim pathname sent by client so it begins with only one backslash.
199 * Two backslashes confuse some dfs clients
202 local_dfs_path = talloc_strdup(r, r->in.req.servername);
203 if (local_dfs_path == NULL) {
204 return NT_STATUS_NO_MEMORY;
206 pathnamep = local_dfs_path;
207 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
208 IS_DIRECTORY_SEP(pathnamep[1])) {
212 junction = talloc_zero(r, struct junction_map);
213 if (junction == NULL) {
214 return NT_STATUS_NO_MEMORY;
217 /* The following call can change cwd. */
218 status = get_referred_path(r, pathnamep,
219 !handle->conn->sconn->using_smb2,
220 junction, &consumedcnt, &self_referral);
221 if (!NT_STATUS_IS_OK(status)) {
222 vfs_ChDir(handle->conn, handle->conn->connectpath);
225 vfs_ChDir(handle->conn, handle->conn->connectpath);
227 if (!self_referral) {
228 pathnamep[consumedcnt] = '\0';
231 dbgtext("Path %s to alternate path(s):",
233 for (i=0; i < junction->referral_count; i++) {
235 junction->referral_list[i].alternate_path);
241 if (r->in.req.max_referral_level <= 2) {
242 max_referral_level = 2;
244 if (r->in.req.max_referral_level >= 3) {
245 max_referral_level = 3;
248 r->out.resp = talloc_zero(r, struct dfs_referral_resp);
249 if (r->out.resp == NULL) {
250 return NT_STATUS_NO_MEMORY;
253 r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
254 r->out.resp->nb_referrals = junction->referral_count;
256 r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
258 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
261 r->out.resp->referral_entries = talloc_zero_array(r,
262 struct dfs_referral_type,
263 r->out.resp->nb_referrals);
264 if (r->out.resp->referral_entries == NULL) {
265 return NT_STATUS_NO_MEMORY;
268 switch (max_referral_level) {
270 for(i=0; i < junction->referral_count; i++) {
271 struct referral *ref = &junction->referral_list[i];
272 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
273 struct dfs_referral_type *t =
274 &r->out.resp->referral_entries[i];
275 struct dfs_referral_v2 *v2 = &t->referral.v2;
278 v2->size = VERSION2_REFERRAL_SIZE;
280 v2->server_type = DFS_SERVER_ROOT;
282 v2->server_type = DFS_SERVER_NON_ROOT;
285 v2->proximity = ref->proximity;
287 v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
288 if (v2->DFS_path == NULL) {
289 return NT_STATUS_NO_MEMORY;
291 v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
292 if (v2->DFS_alt_path == NULL) {
293 return NT_STATUS_NO_MEMORY;
295 v2->netw_address = talloc_strdup(mem_ctx,
296 ref->alternate_path);
297 if (v2->netw_address == NULL) {
298 return NT_STATUS_NO_MEMORY;
304 for(i=0; i < junction->referral_count; i++) {
305 struct referral *ref = &junction->referral_list[i];
306 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
307 struct dfs_referral_type *t =
308 &r->out.resp->referral_entries[i];
309 struct dfs_referral_v3 *v3 = &t->referral.v3;
310 struct dfs_normal_referral *r1 = &v3->referrals.r1;
313 v3->size = VERSION3_REFERRAL_SIZE;
315 v3->server_type = DFS_SERVER_ROOT;
317 v3->server_type = DFS_SERVER_NON_ROOT;
321 r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
322 if (r1->DFS_path == NULL) {
323 return NT_STATUS_NO_MEMORY;
325 r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
326 if (r1->DFS_alt_path == NULL) {
327 return NT_STATUS_NO_MEMORY;
329 r1->netw_address = talloc_strdup(mem_ctx,
330 ref->alternate_path);
331 if (r1->netw_address == NULL) {
332 return NT_STATUS_NO_MEMORY;
337 DEBUG(0,("Invalid dfs referral version: %d\n",
338 max_referral_level));
339 return NT_STATUS_INVALID_LEVEL;
343 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
349 static NTSTATUS vfswrap_snap_check_path(struct vfs_handle_struct *handle,
351 const char *service_path,
354 return NT_STATUS_NOT_SUPPORTED;
357 static NTSTATUS vfswrap_snap_create(struct vfs_handle_struct *handle,
359 const char *base_volume,
365 return NT_STATUS_NOT_SUPPORTED;
368 static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle,
373 return NT_STATUS_NOT_SUPPORTED;
376 /* Directory operations */
378 static DIR *vfswrap_opendir(vfs_handle_struct *handle,
379 const struct smb_filename *smb_fname,
385 START_PROFILE(syscall_opendir);
386 result = opendir(smb_fname->base_name);
387 END_PROFILE(syscall_opendir);
391 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
398 START_PROFILE(syscall_fdopendir);
399 result = sys_fdopendir(fsp->fh->fd);
400 END_PROFILE(syscall_fdopendir);
405 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
407 SMB_STRUCT_STAT *sbuf)
409 struct dirent *result;
411 START_PROFILE(syscall_readdir);
412 result = readdir(dirp);
413 END_PROFILE(syscall_readdir);
415 /* Default Posix readdir() does not give us stat info.
416 * Set to invalid to indicate we didn't return this info. */
417 SET_STAT_INVALID(*sbuf);
418 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
419 if (result != NULL) {
420 /* See if we can efficiently return this. */
422 int flags = AT_SYMLINK_NOFOLLOW;
423 int ret = fstatat(dirfd(dirp),
428 * As this is an optimization,
429 * ignore it if we stat'ed a
430 * symlink. Make the caller
431 * do it again as we don't
432 * know if they wanted the link
433 * info, or its target info.
435 if ((ret == 0) && (!S_ISLNK(st.st_mode))) {
436 init_stat_ex_from_stat(sbuf,
438 lp_fake_directory_create_times(
439 SNUM(handle->conn)));
447 static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
448 const struct smb_filename *fname,
450 struct readdir_attr_data **attr_data)
452 return NT_STATUS_NOT_SUPPORTED;
455 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
457 START_PROFILE(syscall_seekdir);
458 seekdir(dirp, offset);
459 END_PROFILE(syscall_seekdir);
462 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
465 START_PROFILE(syscall_telldir);
466 result = telldir(dirp);
467 END_PROFILE(syscall_telldir);
471 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
473 START_PROFILE(syscall_rewinddir);
475 END_PROFILE(syscall_rewinddir);
478 static int vfswrap_mkdir(vfs_handle_struct *handle,
479 const struct smb_filename *smb_fname,
483 bool has_dacl = False;
484 const char *path = smb_fname->base_name;
487 START_PROFILE(syscall_mkdir);
489 if (lp_inherit_acls(SNUM(handle->conn))
490 && parent_dirname(talloc_tos(), path, &parent, NULL)
491 && (has_dacl = directory_has_default_acl(handle->conn, parent))) {
492 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
497 result = mkdir(path, mode);
499 if (result == 0 && !has_dacl) {
501 * We need to do this as the default behavior of POSIX ACLs
502 * is to set the mask to be the requested group permission
503 * bits, not the group permission bits to be the requested
504 * group permission bits. This is not what we want, as it will
505 * mess up any inherited ACL bits that were set. JRA.
507 int saved_errno = errno; /* We may get ENOSYS */
508 if ((SMB_VFS_CHMOD_ACL(handle->conn, smb_fname, mode) == -1) &&
514 END_PROFILE(syscall_mkdir);
518 static int vfswrap_rmdir(vfs_handle_struct *handle,
519 const struct smb_filename *smb_fname)
523 START_PROFILE(syscall_rmdir);
524 result = rmdir(smb_fname->base_name);
525 END_PROFILE(syscall_rmdir);
529 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
533 START_PROFILE(syscall_closedir);
534 result = closedir(dirp);
535 END_PROFILE(syscall_closedir);
539 static void vfswrap_init_search_op(vfs_handle_struct *handle,
542 /* Default behavior is a NOOP */
545 /* File operations */
547 static int vfswrap_open(vfs_handle_struct *handle,
548 struct smb_filename *smb_fname,
549 files_struct *fsp, int flags, mode_t mode)
553 START_PROFILE(syscall_open);
555 if (smb_fname->stream_name) {
560 result = open(smb_fname->base_name, flags, mode);
562 END_PROFILE(syscall_open);
566 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
567 struct smb_request *req,
568 uint16_t root_dir_fid,
569 struct smb_filename *smb_fname,
570 uint32_t access_mask,
571 uint32_t share_access,
572 uint32_t create_disposition,
573 uint32_t create_options,
574 uint32_t file_attributes,
575 uint32_t oplock_request,
576 struct smb2_lease *lease,
577 uint64_t allocation_size,
578 uint32_t private_flags,
579 struct security_descriptor *sd,
580 struct ea_list *ea_list,
581 files_struct **result,
583 const struct smb2_create_blobs *in_context_blobs,
584 struct smb2_create_blobs *out_context_blobs)
586 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
587 access_mask, share_access,
588 create_disposition, create_options,
589 file_attributes, oplock_request, lease,
590 allocation_size, private_flags,
592 pinfo, in_context_blobs, out_context_blobs);
595 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
599 START_PROFILE(syscall_close);
600 result = fd_close_posix(fsp);
601 END_PROFILE(syscall_close);
605 static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
609 START_PROFILE_BYTES(syscall_read, n);
610 result = sys_read(fsp->fh->fd, data, n);
611 END_PROFILE_BYTES(syscall_read);
615 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
616 size_t n, off_t offset)
620 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
621 START_PROFILE_BYTES(syscall_pread, n);
622 result = sys_pread(fsp->fh->fd, data, n, offset);
623 END_PROFILE_BYTES(syscall_pread);
625 if (result == -1 && errno == ESPIPE) {
626 /* Maintain the fiction that pipes can be seeked (sought?) on. */
627 result = SMB_VFS_READ(fsp, data, n);
631 #else /* HAVE_PREAD */
635 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
636 if (curr == -1 && errno == ESPIPE) {
637 /* Maintain the fiction that pipes can be seeked (sought?) on. */
638 result = SMB_VFS_READ(fsp, data, n);
643 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
648 result = SMB_VFS_READ(fsp, data, n);
651 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
654 #endif /* HAVE_PREAD */
659 static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
663 START_PROFILE_BYTES(syscall_write, n);
664 result = sys_write(fsp->fh->fd, data, n);
665 END_PROFILE_BYTES(syscall_write);
669 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
670 size_t n, off_t offset)
674 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
675 START_PROFILE_BYTES(syscall_pwrite, n);
676 result = sys_pwrite(fsp->fh->fd, data, n, offset);
677 END_PROFILE_BYTES(syscall_pwrite);
679 if (result == -1 && errno == ESPIPE) {
680 /* Maintain the fiction that pipes can be sought on. */
681 result = SMB_VFS_WRITE(fsp, data, n);
684 #else /* HAVE_PWRITE */
688 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
693 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
697 result = SMB_VFS_WRITE(fsp, data, n);
700 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
703 #endif /* HAVE_PWRITE */
708 static int vfswrap_init_pool(struct smbd_server_connection *conn)
712 if (conn->pool != NULL) {
716 ret = pthreadpool_tevent_init(conn, lp_aio_max_threads(),
721 struct vfswrap_pread_state {
729 struct vfs_aio_state vfs_aio_state;
730 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
733 static void vfs_pread_do(void *private_data);
734 static void vfs_pread_done(struct tevent_req *subreq);
736 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
738 struct tevent_context *ev,
739 struct files_struct *fsp,
741 size_t n, off_t offset)
743 struct tevent_req *req, *subreq;
744 struct vfswrap_pread_state *state;
747 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
752 ret = vfswrap_init_pool(handle->conn->sconn);
753 if (tevent_req_error(req, ret)) {
754 return tevent_req_post(req, ev);
758 state->fd = fsp->fh->fd;
761 state->offset = offset;
763 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
764 state->profile_bytes, n);
765 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
767 subreq = pthreadpool_tevent_job_send(
768 state, ev, handle->conn->sconn->pool,
769 vfs_pread_do, state);
770 if (tevent_req_nomem(subreq, req)) {
771 return tevent_req_post(req, ev);
773 tevent_req_set_callback(subreq, vfs_pread_done, req);
778 static void vfs_pread_do(void *private_data)
780 struct vfswrap_pread_state *state = talloc_get_type_abort(
781 private_data, struct vfswrap_pread_state);
782 struct timespec start_time;
783 struct timespec end_time;
785 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
787 PROFILE_TIMESTAMP(&start_time);
790 state->ret = pread(state->fd, state->buf, state->count,
792 } while ((state->ret == -1) && (errno == EINTR));
796 PROFILE_TIMESTAMP(&end_time);
798 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
800 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
803 static void vfs_pread_done(struct tevent_req *subreq)
805 struct tevent_req *req = tevent_req_callback_data(
806 subreq, struct tevent_req);
808 struct vfswrap_pread_state *state = tevent_req_data(
809 req, struct vfswrap_pread_state);
813 ret = pthreadpool_tevent_job_recv(subreq);
815 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
816 if (tevent_req_error(req, ret)) {
820 tevent_req_done(req);
823 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
824 struct vfs_aio_state *vfs_aio_state)
826 struct vfswrap_pread_state *state = tevent_req_data(
827 req, struct vfswrap_pread_state);
829 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
833 *vfs_aio_state = state->vfs_aio_state;
837 struct vfswrap_pwrite_state {
845 struct vfs_aio_state vfs_aio_state;
846 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
849 static void vfs_pwrite_do(void *private_data);
850 static void vfs_pwrite_done(struct tevent_req *subreq);
852 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
854 struct tevent_context *ev,
855 struct files_struct *fsp,
857 size_t n, off_t offset)
859 struct tevent_req *req, *subreq;
860 struct vfswrap_pwrite_state *state;
863 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
868 ret = vfswrap_init_pool(handle->conn->sconn);
869 if (tevent_req_error(req, ret)) {
870 return tevent_req_post(req, ev);
874 state->fd = fsp->fh->fd;
877 state->offset = offset;
879 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
880 state->profile_bytes, n);
881 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
883 subreq = pthreadpool_tevent_job_send(
884 state, ev, handle->conn->sconn->pool,
885 vfs_pwrite_do, state);
886 if (tevent_req_nomem(subreq, req)) {
887 return tevent_req_post(req, ev);
889 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
894 static void vfs_pwrite_do(void *private_data)
896 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
897 private_data, struct vfswrap_pwrite_state);
898 struct timespec start_time;
899 struct timespec end_time;
901 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
903 PROFILE_TIMESTAMP(&start_time);
906 state->ret = pwrite(state->fd, state->buf, state->count,
908 } while ((state->ret == -1) && (errno == EINTR));
912 PROFILE_TIMESTAMP(&end_time);
914 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
916 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
919 static void vfs_pwrite_done(struct tevent_req *subreq)
921 struct tevent_req *req = tevent_req_callback_data(
922 subreq, struct tevent_req);
924 struct vfswrap_pwrite_state *state = tevent_req_data(
925 req, struct vfswrap_pwrite_state);
929 ret = pthreadpool_tevent_job_recv(subreq);
931 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
932 if (tevent_req_error(req, ret)) {
936 tevent_req_done(req);
939 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
940 struct vfs_aio_state *vfs_aio_state)
942 struct vfswrap_pwrite_state *state = tevent_req_data(
943 req, struct vfswrap_pwrite_state);
945 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
949 *vfs_aio_state = state->vfs_aio_state;
953 struct vfswrap_fsync_state {
958 struct vfs_aio_state vfs_aio_state;
959 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
962 static void vfs_fsync_do(void *private_data);
963 static void vfs_fsync_done(struct tevent_req *subreq);
965 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
967 struct tevent_context *ev,
968 struct files_struct *fsp)
970 struct tevent_req *req, *subreq;
971 struct vfswrap_fsync_state *state;
974 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
979 ret = vfswrap_init_pool(handle->conn->sconn);
980 if (tevent_req_error(req, ret)) {
981 return tevent_req_post(req, ev);
985 state->fd = fsp->fh->fd;
987 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
988 state->profile_basic);
990 subreq = pthreadpool_tevent_job_send(
991 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
992 if (tevent_req_nomem(subreq, req)) {
993 return tevent_req_post(req, ev);
995 tevent_req_set_callback(subreq, vfs_fsync_done, req);
1000 static void vfs_fsync_do(void *private_data)
1002 struct vfswrap_fsync_state *state = talloc_get_type_abort(
1003 private_data, struct vfswrap_fsync_state);
1004 struct timespec start_time;
1005 struct timespec end_time;
1007 PROFILE_TIMESTAMP(&start_time);
1010 state->ret = fsync(state->fd);
1011 } while ((state->ret == -1) && (errno == EINTR));
1015 PROFILE_TIMESTAMP(&end_time);
1017 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1020 static void vfs_fsync_done(struct tevent_req *subreq)
1022 struct tevent_req *req = tevent_req_callback_data(
1023 subreq, struct tevent_req);
1025 struct vfswrap_fsync_state *state = tevent_req_data(
1026 req, struct vfswrap_fsync_state);
1030 ret = pthreadpool_tevent_job_recv(subreq);
1031 TALLOC_FREE(subreq);
1032 SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
1033 if (tevent_req_error(req, ret)) {
1037 tevent_req_done(req);
1040 static int vfswrap_fsync_recv(struct tevent_req *req,
1041 struct vfs_aio_state *vfs_aio_state)
1043 struct vfswrap_fsync_state *state = tevent_req_data(
1044 req, struct vfswrap_fsync_state);
1046 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1050 *vfs_aio_state = state->vfs_aio_state;
1054 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1058 START_PROFILE(syscall_lseek);
1060 /* Cope with 'stat' file opens. */
1061 if (fsp->fh->fd != -1)
1062 result = lseek(fsp->fh->fd, offset, whence);
1065 * We want to maintain the fiction that we can seek
1066 * on a fifo for file system purposes. This allows
1067 * people to set up UNIX fifo's that feed data to Windows
1068 * applications. JRA.
1071 if((result == -1) && (errno == ESPIPE)) {
1076 END_PROFILE(syscall_lseek);
1080 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1081 off_t offset, size_t n)
1085 START_PROFILE_BYTES(syscall_sendfile, n);
1086 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
1087 END_PROFILE_BYTES(syscall_sendfile);
1091 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1093 files_struct *tofsp,
1099 START_PROFILE_BYTES(syscall_recvfile, n);
1100 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
1101 END_PROFILE_BYTES(syscall_recvfile);
1105 static int vfswrap_rename(vfs_handle_struct *handle,
1106 const struct smb_filename *smb_fname_src,
1107 const struct smb_filename *smb_fname_dst)
1111 START_PROFILE(syscall_rename);
1113 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
1118 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
1121 END_PROFILE(syscall_rename);
1125 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
1130 START_PROFILE(syscall_fsync);
1131 result = fsync(fsp->fh->fd);
1132 END_PROFILE(syscall_fsync);
1139 static int vfswrap_stat(vfs_handle_struct *handle,
1140 struct smb_filename *smb_fname)
1144 START_PROFILE(syscall_stat);
1146 if (smb_fname->stream_name) {
1151 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1152 lp_fake_directory_create_times(SNUM(handle->conn)));
1154 END_PROFILE(syscall_stat);
1158 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1162 START_PROFILE(syscall_fstat);
1163 result = sys_fstat(fsp->fh->fd,
1164 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1165 END_PROFILE(syscall_fstat);
1169 static int vfswrap_lstat(vfs_handle_struct *handle,
1170 struct smb_filename *smb_fname)
1174 START_PROFILE(syscall_lstat);
1176 if (smb_fname->stream_name) {
1181 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1182 lp_fake_directory_create_times(SNUM(handle->conn)));
1184 END_PROFILE(syscall_lstat);
1188 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1190 enum vfs_translate_direction direction,
1191 TALLOC_CTX *mem_ctx,
1194 return NT_STATUS_NONE_MAPPED;
1198 * Implement the default fsctl operation.
1200 static bool vfswrap_logged_ioctl_message = false;
1202 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1203 struct files_struct *fsp,
1206 uint16_t req_flags, /* Needed for UNICODE ... */
1207 const uint8_t *_in_data,
1209 uint8_t **_out_data,
1210 uint32_t max_out_len,
1213 const char *in_data = (const char *)_in_data;
1214 char **out_data = (char **)_out_data;
1218 case FSCTL_SET_SPARSE:
1220 bool set_sparse = true;
1222 if (in_len >= 1 && in_data[0] == 0) {
1226 status = file_set_sparse(handle->conn, fsp, set_sparse);
1228 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1229 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1230 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1231 nt_errstr(status)));
1236 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1238 unsigned char objid[16];
1239 char *return_data = NULL;
1241 /* This should return the object-id on this file.
1242 * I think I'll make this be the inode+dev. JRA.
1245 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1246 fsp_fnum_dbg(fsp)));
1248 *out_len = MIN(max_out_len, 64);
1250 /* Hmmm, will this cause problems if less data asked for? */
1251 return_data = talloc_array(ctx, char, 64);
1252 if (return_data == NULL) {
1253 return NT_STATUS_NO_MEMORY;
1256 /* For backwards compatibility only store the dev/inode. */
1257 push_file_id_16(return_data, &fsp->file_id);
1258 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1259 push_file_id_16(return_data+32, &fsp->file_id);
1260 memset(return_data+48, 0, 16);
1261 *out_data = return_data;
1262 return NT_STATUS_OK;
1265 case FSCTL_GET_REPARSE_POINT:
1267 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1268 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1269 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1270 return NT_STATUS_NOT_A_REPARSE_POINT;
1273 case FSCTL_SET_REPARSE_POINT:
1275 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1276 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1277 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1278 return NT_STATUS_NOT_A_REPARSE_POINT;
1281 case FSCTL_GET_SHADOW_COPY_DATA:
1284 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1285 * and return their volume names. If max_data_count is 16, then it is just
1286 * asking for the number of volumes and length of the combined names.
1288 * pdata is the data allocated by our caller, but that uses
1289 * total_data_count (which is 0 in our case) rather than max_data_count.
1290 * Allocate the correct amount and return the pointer to let
1291 * it be deallocated when we return.
1293 struct shadow_copy_data *shadow_data = NULL;
1294 bool labels = False;
1295 uint32_t labels_data_count = 0;
1297 char *cur_pdata = NULL;
1299 if (max_out_len < 16) {
1300 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1302 return NT_STATUS_INVALID_PARAMETER;
1305 if (max_out_len > 16) {
1309 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1310 if (shadow_data == NULL) {
1311 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1312 return NT_STATUS_NO_MEMORY;
1316 * Call the VFS routine to actually do the work.
1318 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1321 /* broken module didn't set errno on error */
1322 status = NT_STATUS_UNSUCCESSFUL;
1324 status = map_nt_error_from_unix(errno);
1325 if (NT_STATUS_EQUAL(status,
1326 NT_STATUS_NOT_SUPPORTED)) {
1330 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1331 "connectpath %s, failed - %s.\n",
1332 fsp->conn->connectpath,
1333 nt_errstr(status)));
1334 TALLOC_FREE(shadow_data);
1338 labels_data_count = (shadow_data->num_volumes * 2 *
1339 sizeof(SHADOW_COPY_LABEL)) + 2;
1344 *out_len = 12 + labels_data_count;
1347 if (max_out_len < *out_len) {
1348 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1349 max_out_len, *out_len));
1350 TALLOC_FREE(shadow_data);
1351 return NT_STATUS_BUFFER_TOO_SMALL;
1354 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1355 if (cur_pdata == NULL) {
1356 TALLOC_FREE(shadow_data);
1357 return NT_STATUS_NO_MEMORY;
1360 *out_data = cur_pdata;
1362 /* num_volumes 4 bytes */
1363 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1366 /* num_labels 4 bytes */
1367 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1370 /* needed_data_count 4 bytes */
1371 SIVAL(cur_pdata, 8, labels_data_count);
1375 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1376 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1377 if (labels && shadow_data->labels) {
1378 for (i=0; i<shadow_data->num_volumes; i++) {
1380 status = srvstr_push(cur_pdata, req_flags,
1381 cur_pdata, shadow_data->labels[i],
1382 2 * sizeof(SHADOW_COPY_LABEL),
1383 STR_UNICODE|STR_TERMINATE, &len);
1384 if (!NT_STATUS_IS_OK(status)) {
1385 TALLOC_FREE(*out_data);
1386 TALLOC_FREE(shadow_data);
1389 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1390 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1394 TALLOC_FREE(shadow_data);
1396 return NT_STATUS_OK;
1399 case FSCTL_FIND_FILES_BY_SID:
1401 /* pretend this succeeded -
1403 * we have to send back a list with all files owned by this SID
1405 * but I have to check that --metze
1411 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1412 fsp_fnum_dbg(fsp)));
1415 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1416 return NT_STATUS_INVALID_PARAMETER;
1419 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1421 /* unknown 4 bytes: this is not the length of the sid :-( */
1422 /*unknown = IVAL(pdata,0);*/
1424 if (!sid_parse(_in_data + 4, sid_len, &sid)) {
1425 return NT_STATUS_INVALID_PARAMETER;
1427 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1429 if (!sid_to_uid(&sid, &uid)) {
1430 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1431 sid_string_dbg(&sid),
1432 (unsigned long)sid_len));
1436 /* we can take a look at the find source :-)
1438 * find ./ -uid $uid -name '*' is what we need here
1441 * and send 4bytes len and then NULL terminated unicode strings
1444 * but I don't know how to deal with the paged results
1445 * (maybe we can hang the result anywhere in the fsp struct)
1447 * but I don't know how to deal with the paged results
1448 * (maybe we can hang the result anywhere in the fsp struct)
1450 * we don't send all files at once
1451 * and at the next we should *not* start from the beginning,
1452 * so we have to cache the result
1457 /* this works for now... */
1458 return NT_STATUS_OK;
1461 case FSCTL_QUERY_ALLOCATED_RANGES:
1463 /* FIXME: This is just a dummy reply, telling that all of the
1464 * file is allocated. MKS cp needs that.
1465 * Adding the real allocated ranges via FIEMAP on Linux
1466 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1467 * this FSCTL correct for sparse files.
1469 uint64_t offset, length;
1470 char *out_data_tmp = NULL;
1473 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1475 return NT_STATUS_INVALID_PARAMETER;
1478 if (max_out_len < 16) {
1479 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1481 return NT_STATUS_INVALID_PARAMETER;
1484 offset = BVAL(in_data,0);
1485 length = BVAL(in_data,8);
1487 if (offset + length < offset) {
1488 /* No 64-bit integer wrap. */
1489 return NT_STATUS_INVALID_PARAMETER;
1492 /* Shouldn't this be SMB_VFS_STAT ... ? */
1493 status = vfs_stat_fsp(fsp);
1494 if (!NT_STATUS_IS_OK(status)) {
1499 out_data_tmp = talloc_array(ctx, char, *out_len);
1500 if (out_data_tmp == NULL) {
1501 DEBUG(10, ("unable to allocate memory for response\n"));
1502 return NT_STATUS_NO_MEMORY;
1505 if (offset > fsp->fsp_name->st.st_ex_size ||
1506 fsp->fsp_name->st.st_ex_size == 0 ||
1508 memset(out_data_tmp, 0, *out_len);
1510 uint64_t end = offset + length;
1511 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1512 SBVAL(out_data_tmp, 0, 0);
1513 SBVAL(out_data_tmp, 8, end);
1516 *out_data = out_data_tmp;
1518 return NT_STATUS_OK;
1521 case FSCTL_IS_VOLUME_DIRTY:
1523 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1524 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1526 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1527 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1529 return NT_STATUS_INVALID_PARAMETER;
1534 * Only print once ... unfortunately there could be lots of
1535 * different FSCTLs that are called.
1537 if (!vfswrap_logged_ioctl_message) {
1538 vfswrap_logged_ioctl_message = true;
1539 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1540 __func__, function));
1544 return NT_STATUS_NOT_SUPPORTED;
1547 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
1548 const struct smb_filename *fname,
1549 SMB_STRUCT_STAT *sbuf);
1551 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1552 struct smb_filename *smb_fname,
1557 offline = vfswrap_is_offline(handle, smb_fname, &smb_fname->st);
1559 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1562 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1565 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1566 struct files_struct *fsp,
1571 offline = vfswrap_is_offline(handle, fsp->fsp_name, &fsp->fsp_name->st);
1573 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1576 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1579 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1580 const struct smb_filename *smb_fname,
1583 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1586 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1587 struct files_struct *fsp,
1590 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1593 struct vfs_cc_state {
1598 static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *handle,
1599 TALLOC_CTX *mem_ctx,
1600 struct tevent_context *ev,
1601 struct files_struct *src_fsp,
1603 struct files_struct *dest_fsp,
1607 struct tevent_req *req;
1608 struct vfs_cc_state *vfs_cc_state;
1611 DEBUG(10, ("performing server side copy chunk of length %lu\n",
1612 (unsigned long)num));
1614 req = tevent_req_create(mem_ctx, &vfs_cc_state, struct vfs_cc_state);
1619 vfs_cc_state->buf = talloc_array(vfs_cc_state, uint8_t,
1620 MIN(num, 8*1024*1024));
1621 if (tevent_req_nomem(vfs_cc_state->buf, req)) {
1622 return tevent_req_post(req, ev);
1625 status = vfs_stat_fsp(src_fsp);
1626 if (tevent_req_nterror(req, status)) {
1627 return tevent_req_post(req, ev);
1630 if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
1632 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1633 * If the SourceOffset or SourceOffset + Length extends beyond
1634 * the end of file, the server SHOULD<240> treat this as a
1635 * STATUS_END_OF_FILE error.
1637 * <240> Section 3.3.5.15.6: Windows servers will return
1638 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1640 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1641 return tevent_req_post(req, ev);
1644 /* could use 2.6.33+ sendfile here to do this in kernel */
1645 while (vfs_cc_state->copied < num) {
1647 struct lock_struct lck;
1650 off_t this_num = MIN(talloc_array_length(vfs_cc_state->buf),
1651 num - vfs_cc_state->copied);
1653 if (src_fsp->op == NULL) {
1654 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1655 return tevent_req_post(req, ev);
1657 init_strict_lock_struct(src_fsp,
1658 src_fsp->op->global->open_persistent_id,
1664 if (!SMB_VFS_STRICT_LOCK(src_fsp->conn, src_fsp, &lck)) {
1665 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1666 return tevent_req_post(req, ev);
1669 ret = SMB_VFS_PREAD(src_fsp, vfs_cc_state->buf,
1672 saved_errno = errno;
1675 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1678 errno = saved_errno;
1679 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1680 return tevent_req_post(req, ev);
1682 if (ret != this_num) {
1683 /* zero tolerance for short reads */
1684 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1685 return tevent_req_post(req, ev);
1690 if (dest_fsp->op == NULL) {
1691 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1692 return tevent_req_post(req, ev);
1695 init_strict_lock_struct(dest_fsp,
1696 dest_fsp->op->global->open_persistent_id,
1702 if (!SMB_VFS_STRICT_LOCK(dest_fsp->conn, dest_fsp, &lck)) {
1703 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1704 return tevent_req_post(req, ev);
1707 ret = SMB_VFS_PWRITE(dest_fsp, vfs_cc_state->buf,
1708 this_num, dest_off);
1710 saved_errno = errno;
1713 SMB_VFS_STRICT_UNLOCK(dest_fsp->conn, dest_fsp, &lck);
1716 errno = saved_errno;
1717 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1718 return tevent_req_post(req, ev);
1720 if (ret != this_num) {
1721 /* zero tolerance for short writes */
1722 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1723 return tevent_req_post(req, ev);
1727 vfs_cc_state->copied += this_num;
1730 tevent_req_done(req);
1731 return tevent_req_post(req, ev);
1734 static NTSTATUS vfswrap_copy_chunk_recv(struct vfs_handle_struct *handle,
1735 struct tevent_req *req,
1738 struct vfs_cc_state *vfs_cc_state = tevent_req_data(req,
1739 struct vfs_cc_state);
1742 if (tevent_req_is_nterror(req, &status)) {
1743 DEBUG(2, ("server side copy chunk failed: %s\n",
1744 nt_errstr(status)));
1746 tevent_req_received(req);
1750 *copied = vfs_cc_state->copied;
1751 DEBUG(10, ("server side copy chunk copied %lu\n",
1752 (unsigned long)*copied));
1753 tevent_req_received(req);
1755 return NT_STATUS_OK;
1758 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1759 TALLOC_CTX *mem_ctx,
1760 struct files_struct *fsp,
1761 struct smb_filename *smb_fname,
1762 uint16_t *_compression_fmt)
1764 return NT_STATUS_INVALID_DEVICE_REQUEST;
1767 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1768 TALLOC_CTX *mem_ctx,
1769 struct files_struct *fsp,
1770 uint16_t compression_fmt)
1772 return NT_STATUS_INVALID_DEVICE_REQUEST;
1775 /********************************************************************
1776 Given a stat buffer return the allocated size on disk, taking into
1777 account sparse files.
1778 ********************************************************************/
1779 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1780 struct files_struct *fsp,
1781 const SMB_STRUCT_STAT *sbuf)
1785 START_PROFILE(syscall_get_alloc_size);
1787 if(S_ISDIR(sbuf->st_ex_mode)) {
1792 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1793 /* The type of st_blocksize is blkcnt_t which *MUST* be
1794 signed (according to POSIX) and can be less than 64-bits.
1795 Ensure when we're converting to 64 bits wide we don't
1797 #if defined(SIZEOF_BLKCNT_T_8)
1798 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1799 #elif defined(SIZEOF_BLKCNT_T_4)
1801 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1802 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1805 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1809 * Some file systems do not allocate a block for very
1810 * small files. But for non-empty file should report a
1814 uint64_t filesize = get_file_size_stat(sbuf);
1816 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
1820 result = get_file_size_stat(sbuf);
1823 if (fsp && fsp->initial_allocation_size)
1824 result = MAX(result,fsp->initial_allocation_size);
1826 result = smb_roundup(handle->conn, result);
1829 END_PROFILE(syscall_get_alloc_size);
1833 static int vfswrap_unlink(vfs_handle_struct *handle,
1834 const struct smb_filename *smb_fname)
1838 START_PROFILE(syscall_unlink);
1840 if (smb_fname->stream_name) {
1844 result = unlink(smb_fname->base_name);
1847 END_PROFILE(syscall_unlink);
1851 static int vfswrap_chmod(vfs_handle_struct *handle,
1852 const struct smb_filename *smb_fname,
1857 START_PROFILE(syscall_chmod);
1860 * We need to do this due to the fact that the default POSIX ACL
1861 * chmod modifies the ACL *mask* for the group owner, not the
1862 * group owner bits directly. JRA.
1867 int saved_errno = errno; /* We might get ENOSYS */
1868 result = SMB_VFS_CHMOD_ACL(handle->conn,
1872 END_PROFILE(syscall_chmod);
1875 /* Error - return the old errno. */
1876 errno = saved_errno;
1879 result = chmod(smb_fname->base_name, mode);
1880 END_PROFILE(syscall_chmod);
1884 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
1888 START_PROFILE(syscall_fchmod);
1891 * We need to do this due to the fact that the default POSIX ACL
1892 * chmod modifies the ACL *mask* for the group owner, not the
1893 * group owner bits directly. JRA.
1897 int saved_errno = errno; /* We might get ENOSYS */
1898 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
1899 END_PROFILE(syscall_fchmod);
1902 /* Error - return the old errno. */
1903 errno = saved_errno;
1906 #if defined(HAVE_FCHMOD)
1907 result = fchmod(fsp->fh->fd, mode);
1913 END_PROFILE(syscall_fchmod);
1917 static int vfswrap_chown(vfs_handle_struct *handle,
1918 const struct smb_filename *smb_fname,
1924 START_PROFILE(syscall_chown);
1925 result = chown(smb_fname->base_name, uid, gid);
1926 END_PROFILE(syscall_chown);
1930 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
1935 START_PROFILE(syscall_fchown);
1936 result = fchown(fsp->fh->fd, uid, gid);
1937 END_PROFILE(syscall_fchown);
1945 static int vfswrap_lchown(vfs_handle_struct *handle,
1946 const struct smb_filename *smb_fname,
1952 START_PROFILE(syscall_lchown);
1953 result = lchown(smb_fname->base_name, uid, gid);
1954 END_PROFILE(syscall_lchown);
1958 static int vfswrap_chdir(vfs_handle_struct *handle, const char *path)
1962 START_PROFILE(syscall_chdir);
1963 result = chdir(path);
1964 END_PROFILE(syscall_chdir);
1968 static char *vfswrap_getwd(vfs_handle_struct *handle)
1972 START_PROFILE(syscall_getwd);
1973 result = sys_getwd();
1974 END_PROFILE(syscall_getwd);
1978 /*********************************************************************
1979 nsec timestamp resolution call. Convert down to whatever the underlying
1980 system will support.
1981 **********************************************************************/
1983 static int vfswrap_ntimes(vfs_handle_struct *handle,
1984 const struct smb_filename *smb_fname,
1985 struct smb_file_time *ft)
1989 START_PROFILE(syscall_ntimes);
1991 if (smb_fname->stream_name) {
1997 if (null_timespec(ft->atime)) {
1998 ft->atime= smb_fname->st.st_ex_atime;
2001 if (null_timespec(ft->mtime)) {
2002 ft->mtime = smb_fname->st.st_ex_mtime;
2005 if (!null_timespec(ft->create_time)) {
2006 set_create_timespec_ea(handle->conn,
2011 if ((timespec_compare(&ft->atime,
2012 &smb_fname->st.st_ex_atime) == 0) &&
2013 (timespec_compare(&ft->mtime,
2014 &smb_fname->st.st_ex_mtime) == 0)) {
2019 #if defined(HAVE_UTIMENSAT)
2021 struct timespec ts[2];
2024 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2026 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2028 if (!((result == -1) && (errno == ENOSYS))) {
2032 #if defined(HAVE_UTIMES)
2034 struct timeval tv[2];
2035 tv[0] = convert_timespec_to_timeval(ft->atime);
2036 tv[1] = convert_timespec_to_timeval(ft->mtime);
2037 result = utimes(smb_fname->base_name, tv);
2039 result = utimes(smb_fname->base_name, NULL);
2041 if (!((result == -1) && (errno == ENOSYS))) {
2045 #if defined(HAVE_UTIME)
2047 struct utimbuf times;
2048 times.actime = convert_timespec_to_time_t(ft->atime);
2049 times.modtime = convert_timespec_to_time_t(ft->mtime);
2050 result = utime(smb_fname->base_name, ×);
2052 result = utime(smb_fname->base_name, NULL);
2054 if (!((result == -1) && (errno == ENOSYS))) {
2062 END_PROFILE(syscall_ntimes);
2066 /*********************************************************************
2067 A version of ftruncate that will write the space on disk if strict
2069 **********************************************************************/
2071 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2073 off_t space_to_write;
2074 uint64_t space_avail;
2075 uint64_t bsize,dfree,dsize;
2078 SMB_STRUCT_STAT *pst;
2080 status = vfs_stat_fsp(fsp);
2081 if (!NT_STATUS_IS_OK(status)) {
2084 pst = &fsp->fsp_name->st;
2087 if (S_ISFIFO(pst->st_ex_mode))
2091 if (pst->st_ex_size == len)
2094 /* Shrink - just ftruncate. */
2095 if (pst->st_ex_size > len)
2096 return ftruncate(fsp->fh->fd, len);
2098 space_to_write = len - pst->st_ex_size;
2100 /* for allocation try fallocate first. This can fail on some
2101 platforms e.g. when the filesystem doesn't support it and no
2102 emulation is being done by the libc (like on AIX with JFS1). In that
2103 case we do our own emulation. fallocate implementations can
2104 return ENOTSUP or EINVAL in cases like that. */
2105 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2106 if (ret == -1 && errno == ENOSPC) {
2112 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2113 "error %d. Falling back to slow manual allocation\n", errno));
2115 /* available disk space is enough or not? */
2117 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2118 /* space_avail is 1k blocks */
2119 if (space_avail == (uint64_t)-1 ||
2120 ((uint64_t)space_to_write/1024 > space_avail) ) {
2125 /* Write out the real space on disk. */
2126 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2134 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2137 SMB_STRUCT_STAT *pst;
2141 START_PROFILE(syscall_ftruncate);
2143 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2144 result = strict_allocate_ftruncate(handle, fsp, len);
2145 END_PROFILE(syscall_ftruncate);
2149 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2150 ftruncate if the system supports it. Then I discovered that
2151 you can have some filesystems that support ftruncate
2152 expansion and some that don't! On Linux fat can't do
2153 ftruncate extend but ext2 can. */
2155 result = ftruncate(fsp->fh->fd, len);
2157 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2158 extend a file with ftruncate. Provide alternate implementation
2161 /* Do an fstat to see if the file is longer than the requested
2162 size in which case the ftruncate above should have
2163 succeeded or shorter, in which case seek to len - 1 and
2164 write 1 byte of zero */
2165 status = vfs_stat_fsp(fsp);
2166 if (!NT_STATUS_IS_OK(status)) {
2170 /* We need to update the files_struct after successful ftruncate */
2175 pst = &fsp->fsp_name->st;
2178 if (S_ISFIFO(pst->st_ex_mode)) {
2184 if (pst->st_ex_size == len) {
2189 if (pst->st_ex_size > len) {
2190 /* the ftruncate should have worked */
2194 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2202 END_PROFILE(syscall_ftruncate);
2206 static int vfswrap_fallocate(vfs_handle_struct *handle,
2214 START_PROFILE(syscall_fallocate);
2216 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2218 * posix_fallocate returns 0 on success, errno on error
2219 * and doesn't set errno. Make it behave like fallocate()
2220 * which returns -1, and sets errno on failure.
2227 /* sys_fallocate handles filtering of unsupported mode flags */
2228 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2230 END_PROFILE(syscall_fallocate);
2234 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2238 START_PROFILE(syscall_fcntl_lock);
2240 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2242 "force process locks",
2244 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2247 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2248 END_PROFILE(syscall_fcntl_lock);
2252 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2253 uint32_t share_mode, uint32_t access_mask)
2255 START_PROFILE(syscall_kernel_flock);
2256 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2257 END_PROFILE(syscall_kernel_flock);
2261 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2266 START_PROFILE(syscall_fcntl_getlock);
2268 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2270 "force process locks",
2272 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2275 result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2276 END_PROFILE(syscall_fcntl_getlock);
2280 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2285 START_PROFILE(syscall_linux_setlease);
2287 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2288 result = linux_setlease(fsp->fh->fd, leasetype);
2292 END_PROFILE(syscall_linux_setlease);
2296 static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2300 START_PROFILE(syscall_symlink);
2301 result = symlink(oldpath, newpath);
2302 END_PROFILE(syscall_symlink);
2306 static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
2310 START_PROFILE(syscall_readlink);
2311 result = readlink(path, buf, bufsiz);
2312 END_PROFILE(syscall_readlink);
2316 static int vfswrap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2320 START_PROFILE(syscall_link);
2321 result = link(oldpath, newpath);
2322 END_PROFILE(syscall_link);
2326 static int vfswrap_mknod(vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev)
2330 START_PROFILE(syscall_mknod);
2331 result = sys_mknod(pathname, mode, dev);
2332 END_PROFILE(syscall_mknod);
2336 static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
2340 START_PROFILE(syscall_realpath);
2341 result = sys_realpath(path);
2342 END_PROFILE(syscall_realpath);
2346 static int vfswrap_chflags(vfs_handle_struct *handle, const char *path,
2350 return chflags(path, flags);
2357 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2358 const SMB_STRUCT_STAT *sbuf)
2362 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2366 key.devid = sbuf->st_ex_dev;
2367 key.inode = sbuf->st_ex_ino;
2368 /* key.extid is unused by default. */
2373 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2374 struct files_struct *fsp,
2375 const struct smb_filename *smb_fname,
2376 TALLOC_CTX *mem_ctx,
2377 unsigned int *pnum_streams,
2378 struct stream_struct **pstreams)
2380 SMB_STRUCT_STAT sbuf;
2381 struct stream_struct *tmp_streams = NULL;
2384 if ((fsp != NULL) && (fsp->is_directory)) {
2386 * No default streams on directories
2391 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2392 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2395 struct smb_filename smb_fname_cp;
2397 ZERO_STRUCT(smb_fname_cp);
2398 smb_fname_cp.base_name = discard_const_p(char,
2399 smb_fname->base_name);
2400 smb_fname_cp.flags = smb_fname->flags;
2402 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
2403 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2405 ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2407 sbuf = smb_fname_cp.st;
2411 return map_nt_error_from_unix(errno);
2414 if (S_ISDIR(sbuf.st_ex_mode)) {
2418 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2419 (*pnum_streams) + 1);
2420 if (tmp_streams == NULL) {
2421 return NT_STATUS_NO_MEMORY;
2423 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2424 if (tmp_streams[*pnum_streams].name == NULL) {
2425 return NT_STATUS_NO_MEMORY;
2427 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2428 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2431 *pstreams = tmp_streams;
2433 return NT_STATUS_OK;
2436 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2439 TALLOC_CTX *mem_ctx,
2443 * Don't fall back to get_real_filename so callers can differentiate
2444 * between a full directory scan and an actual case-insensitive stat.
2450 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2453 return handle->conn->connectpath;
2456 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2457 struct byte_range_lock *br_lck,
2458 struct lock_struct *plock,
2461 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2463 /* Note: blr is not used in the default implementation. */
2464 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2467 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2468 struct messaging_context *msg_ctx,
2469 struct byte_range_lock *br_lck,
2470 const struct lock_struct *plock)
2472 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2474 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2477 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2478 struct byte_range_lock *br_lck,
2479 struct lock_struct *plock)
2481 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2483 /* Note: blr is not used in the default implementation. */
2484 return brl_lock_cancel_default(br_lck, plock);
2487 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2489 struct lock_struct *plock)
2491 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2492 plock->lock_type == WRITE_LOCK);
2494 return strict_lock_default(fsp, plock);
2497 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2499 struct lock_struct *plock)
2501 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2502 plock->lock_type == WRITE_LOCK);
2504 strict_unlock_default(fsp, plock);
2507 /* NT ACL operations. */
2509 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2511 uint32_t security_info,
2512 TALLOC_CTX *mem_ctx,
2513 struct security_descriptor **ppdesc)
2517 START_PROFILE(fget_nt_acl);
2518 result = posix_fget_nt_acl(fsp, security_info,
2520 END_PROFILE(fget_nt_acl);
2524 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2525 const struct smb_filename *smb_fname,
2526 uint32_t security_info,
2527 TALLOC_CTX *mem_ctx,
2528 struct security_descriptor **ppdesc)
2532 START_PROFILE(get_nt_acl);
2533 result = posix_get_nt_acl(handle->conn,
2538 END_PROFILE(get_nt_acl);
2542 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2546 START_PROFILE(fset_nt_acl);
2547 result = set_nt_acl(fsp, security_info_sent, psd);
2548 END_PROFILE(fset_nt_acl);
2552 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2553 struct smb_filename *file,
2554 struct security_acl *sacl,
2555 uint32_t access_requested,
2556 uint32_t access_denied)
2558 return NT_STATUS_OK; /* Nothing to do here ... */
2561 static int vfswrap_chmod_acl(vfs_handle_struct *handle,
2562 const struct smb_filename *smb_fname,
2571 START_PROFILE(chmod_acl);
2572 result = chmod_acl(handle->conn, smb_fname->base_name, mode);
2573 END_PROFILE(chmod_acl);
2578 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2586 START_PROFILE(fchmod_acl);
2587 result = fchmod_acl(fsp, mode);
2588 END_PROFILE(fchmod_acl);
2593 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2595 SMB_ACL_TYPE_T type,
2596 TALLOC_CTX *mem_ctx)
2598 return sys_acl_get_file(handle, path_p, type, mem_ctx);
2601 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2603 TALLOC_CTX *mem_ctx)
2605 return sys_acl_get_fd(handle, fsp, mem_ctx);
2608 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2610 return sys_acl_set_file(handle, name, acltype, theacl);
2613 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2615 return sys_acl_set_fd(handle, fsp, theacl);
2618 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
2620 return sys_acl_delete_def_file(handle, path);
2623 /****************************************************************
2624 Extended attribute operations.
2625 *****************************************************************/
2627 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
2629 return getxattr(path, name, value, size);
2632 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2634 return fgetxattr(fsp->fh->fd, name, value, size);
2637 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
2639 return listxattr(path, list, size);
2642 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2644 return flistxattr(fsp->fh->fd, list, size);
2647 static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
2649 return removexattr(path, name);
2652 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2654 return fremovexattr(fsp->fh->fd, name);
2657 static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
2659 return setxattr(path, name, value, size, flags);
2662 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2664 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2667 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2672 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2673 const struct smb_filename *fname,
2674 SMB_STRUCT_STAT *sbuf)
2678 bool offline = false;
2680 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2684 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2685 #if defined(ENOTSUP)
2691 status = get_full_smb_filename(talloc_tos(), fname, &path);
2692 if (!NT_STATUS_IS_OK(status)) {
2693 errno = map_errno_from_nt_status(status);
2697 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2704 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2705 struct files_struct *fsp,
2706 TALLOC_CTX *mem_ctx,
2709 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2712 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2713 struct files_struct *fsp,
2714 const DATA_BLOB old_cookie,
2715 TALLOC_CTX *mem_ctx,
2716 DATA_BLOB *new_cookie)
2718 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2722 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2723 struct smb_request *smb1req,
2724 struct smbXsrv_open *op,
2725 const DATA_BLOB old_cookie,
2726 TALLOC_CTX *mem_ctx,
2727 struct files_struct **fsp,
2728 DATA_BLOB *new_cookie)
2730 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2731 old_cookie, mem_ctx,
2735 static struct vfs_fn_pointers vfs_default_fns = {
2736 /* Disk operations */
2738 .connect_fn = vfswrap_connect,
2739 .disconnect_fn = vfswrap_disconnect,
2740 .disk_free_fn = vfswrap_disk_free,
2741 .get_quota_fn = vfswrap_get_quota,
2742 .set_quota_fn = vfswrap_set_quota,
2743 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2744 .statvfs_fn = vfswrap_statvfs,
2745 .fs_capabilities_fn = vfswrap_fs_capabilities,
2746 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2747 .snap_check_path_fn = vfswrap_snap_check_path,
2748 .snap_create_fn = vfswrap_snap_create,
2749 .snap_delete_fn = vfswrap_snap_delete,
2751 /* Directory operations */
2753 .opendir_fn = vfswrap_opendir,
2754 .fdopendir_fn = vfswrap_fdopendir,
2755 .readdir_fn = vfswrap_readdir,
2756 .readdir_attr_fn = vfswrap_readdir_attr,
2757 .seekdir_fn = vfswrap_seekdir,
2758 .telldir_fn = vfswrap_telldir,
2759 .rewind_dir_fn = vfswrap_rewinddir,
2760 .mkdir_fn = vfswrap_mkdir,
2761 .rmdir_fn = vfswrap_rmdir,
2762 .closedir_fn = vfswrap_closedir,
2763 .init_search_op_fn = vfswrap_init_search_op,
2765 /* File operations */
2767 .open_fn = vfswrap_open,
2768 .create_file_fn = vfswrap_create_file,
2769 .close_fn = vfswrap_close,
2770 .read_fn = vfswrap_read,
2771 .pread_fn = vfswrap_pread,
2772 .pread_send_fn = vfswrap_pread_send,
2773 .pread_recv_fn = vfswrap_pread_recv,
2774 .write_fn = vfswrap_write,
2775 .pwrite_fn = vfswrap_pwrite,
2776 .pwrite_send_fn = vfswrap_pwrite_send,
2777 .pwrite_recv_fn = vfswrap_pwrite_recv,
2778 .lseek_fn = vfswrap_lseek,
2779 .sendfile_fn = vfswrap_sendfile,
2780 .recvfile_fn = vfswrap_recvfile,
2781 .rename_fn = vfswrap_rename,
2782 .fsync_fn = vfswrap_fsync,
2783 .fsync_send_fn = vfswrap_fsync_send,
2784 .fsync_recv_fn = vfswrap_fsync_recv,
2785 .stat_fn = vfswrap_stat,
2786 .fstat_fn = vfswrap_fstat,
2787 .lstat_fn = vfswrap_lstat,
2788 .get_alloc_size_fn = vfswrap_get_alloc_size,
2789 .unlink_fn = vfswrap_unlink,
2790 .chmod_fn = vfswrap_chmod,
2791 .fchmod_fn = vfswrap_fchmod,
2792 .chown_fn = vfswrap_chown,
2793 .fchown_fn = vfswrap_fchown,
2794 .lchown_fn = vfswrap_lchown,
2795 .chdir_fn = vfswrap_chdir,
2796 .getwd_fn = vfswrap_getwd,
2797 .ntimes_fn = vfswrap_ntimes,
2798 .ftruncate_fn = vfswrap_ftruncate,
2799 .fallocate_fn = vfswrap_fallocate,
2800 .lock_fn = vfswrap_lock,
2801 .kernel_flock_fn = vfswrap_kernel_flock,
2802 .linux_setlease_fn = vfswrap_linux_setlease,
2803 .getlock_fn = vfswrap_getlock,
2804 .symlink_fn = vfswrap_symlink,
2805 .readlink_fn = vfswrap_readlink,
2806 .link_fn = vfswrap_link,
2807 .mknod_fn = vfswrap_mknod,
2808 .realpath_fn = vfswrap_realpath,
2809 .chflags_fn = vfswrap_chflags,
2810 .file_id_create_fn = vfswrap_file_id_create,
2811 .streaminfo_fn = vfswrap_streaminfo,
2812 .get_real_filename_fn = vfswrap_get_real_filename,
2813 .connectpath_fn = vfswrap_connectpath,
2814 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2815 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2816 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2817 .strict_lock_fn = vfswrap_strict_lock,
2818 .strict_unlock_fn = vfswrap_strict_unlock,
2819 .translate_name_fn = vfswrap_translate_name,
2820 .fsctl_fn = vfswrap_fsctl,
2821 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
2822 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
2823 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
2824 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
2825 .copy_chunk_send_fn = vfswrap_copy_chunk_send,
2826 .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
2827 .get_compression_fn = vfswrap_get_compression,
2828 .set_compression_fn = vfswrap_set_compression,
2830 /* NT ACL operations. */
2832 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2833 .get_nt_acl_fn = vfswrap_get_nt_acl,
2834 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2835 .audit_file_fn = vfswrap_audit_file,
2837 /* POSIX ACL operations. */
2839 .chmod_acl_fn = vfswrap_chmod_acl,
2840 .fchmod_acl_fn = vfswrap_fchmod_acl,
2842 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2843 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2844 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2845 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2846 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2847 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2848 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2850 /* EA operations. */
2851 .getxattr_fn = vfswrap_getxattr,
2852 .fgetxattr_fn = vfswrap_fgetxattr,
2853 .listxattr_fn = vfswrap_listxattr,
2854 .flistxattr_fn = vfswrap_flistxattr,
2855 .removexattr_fn = vfswrap_removexattr,
2856 .fremovexattr_fn = vfswrap_fremovexattr,
2857 .setxattr_fn = vfswrap_setxattr,
2858 .fsetxattr_fn = vfswrap_fsetxattr,
2860 /* aio operations */
2861 .aio_force_fn = vfswrap_aio_force,
2863 /* durable handle operations */
2864 .durable_cookie_fn = vfswrap_durable_cookie,
2865 .durable_disconnect_fn = vfswrap_durable_disconnect,
2866 .durable_reconnect_fn = vfswrap_durable_reconnect,
2869 NTSTATUS vfs_default_init(void);
2870 NTSTATUS vfs_default_init(void)
2872 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
2873 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);