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,
73 const struct smb_filename *smb_fname,
74 enum SMB_QUOTA_TYPE qtype,
78 #ifdef HAVE_SYS_QUOTAS
81 START_PROFILE(syscall_get_quota);
82 result = sys_get_quota(smb_fname->base_name, qtype, id, qt);
83 END_PROFILE(syscall_get_quota);
91 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
93 #ifdef HAVE_SYS_QUOTAS
96 START_PROFILE(syscall_set_quota);
97 result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
98 END_PROFILE(syscall_set_quota);
106 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
107 struct files_struct *fsp,
108 struct shadow_copy_data *shadow_copy_data,
112 return -1; /* Not implemented. */
115 static int vfswrap_statvfs(struct vfs_handle_struct *handle,
116 const struct smb_filename *smb_fname,
117 vfs_statvfs_struct *statbuf)
119 return sys_statvfs(smb_fname->base_name, statbuf);
122 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
123 enum timestamp_set_resolution *p_ts_res)
125 connection_struct *conn = handle->conn;
126 uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
127 struct smb_filename *smb_fname_cpath = NULL;
128 struct vfs_statvfs_struct statbuf;
131 ZERO_STRUCT(statbuf);
132 ret = sys_statvfs(conn->connectpath, &statbuf);
134 caps = statbuf.FsCapabilities;
137 *p_ts_res = TIMESTAMP_SET_SECONDS;
139 /* Work out what timestamp resolution we can
140 * use when setting a timestamp. */
142 smb_fname_cpath = synthetic_smb_fname(talloc_tos(), conn->connectpath,
144 if (smb_fname_cpath == NULL) {
148 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
150 TALLOC_FREE(smb_fname_cpath);
154 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
155 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
156 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
157 /* If any of the normal UNIX directory timestamps
158 * have a non-zero tv_nsec component assume
159 * we might be able to set sub-second timestamps.
160 * See what filetime set primitives we have.
162 #if defined(HAVE_UTIMENSAT)
163 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
164 #elif defined(HAVE_UTIMES)
165 /* utimes allows msec timestamps to be set. */
166 *p_ts_res = TIMESTAMP_SET_MSEC;
167 #elif defined(HAVE_UTIME)
168 /* utime only allows sec timestamps to be set. */
169 *p_ts_res = TIMESTAMP_SET_SECONDS;
172 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
174 "available on share %s, directory %s\n",
175 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
176 lp_servicename(talloc_tos(), conn->params->service),
177 conn->connectpath ));
179 TALLOC_FREE(smb_fname_cpath);
183 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
184 struct dfs_GetDFSReferral *r)
186 struct junction_map *junction = NULL;
188 bool self_referral = false;
189 char *pathnamep = NULL;
190 char *local_dfs_path = NULL;
193 uint16_t max_referral_level = r->in.req.max_referral_level;
196 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
199 /* get the junction entry */
200 if (r->in.req.servername == NULL) {
201 return NT_STATUS_NOT_FOUND;
205 * Trim pathname sent by client so it begins with only one backslash.
206 * Two backslashes confuse some dfs clients
209 local_dfs_path = talloc_strdup(r, r->in.req.servername);
210 if (local_dfs_path == NULL) {
211 return NT_STATUS_NO_MEMORY;
213 pathnamep = local_dfs_path;
214 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
215 IS_DIRECTORY_SEP(pathnamep[1])) {
219 junction = talloc_zero(r, struct junction_map);
220 if (junction == NULL) {
221 return NT_STATUS_NO_MEMORY;
224 /* The following call can change cwd. */
225 status = get_referred_path(r, pathnamep,
226 handle->conn->sconn->remote_address,
227 handle->conn->sconn->local_address,
228 !handle->conn->sconn->using_smb2,
229 junction, &consumedcnt, &self_referral);
230 if (!NT_STATUS_IS_OK(status)) {
231 struct smb_filename connectpath_fname = {
232 .base_name = handle->conn->connectpath
234 vfs_ChDir(handle->conn, &connectpath_fname);
238 struct smb_filename connectpath_fname = {
239 .base_name = handle->conn->connectpath
241 vfs_ChDir(handle->conn, &connectpath_fname);
244 if (!self_referral) {
245 pathnamep[consumedcnt] = '\0';
248 dbgtext("Path %s to alternate path(s):",
250 for (i=0; i < junction->referral_count; i++) {
252 junction->referral_list[i].alternate_path);
258 if (r->in.req.max_referral_level <= 2) {
259 max_referral_level = 2;
261 if (r->in.req.max_referral_level >= 3) {
262 max_referral_level = 3;
265 r->out.resp = talloc_zero(r, struct dfs_referral_resp);
266 if (r->out.resp == NULL) {
267 return NT_STATUS_NO_MEMORY;
270 r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
271 r->out.resp->nb_referrals = junction->referral_count;
273 r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
275 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
278 r->out.resp->referral_entries = talloc_zero_array(r,
279 struct dfs_referral_type,
280 r->out.resp->nb_referrals);
281 if (r->out.resp->referral_entries == NULL) {
282 return NT_STATUS_NO_MEMORY;
285 switch (max_referral_level) {
287 for(i=0; i < junction->referral_count; i++) {
288 struct referral *ref = &junction->referral_list[i];
289 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
290 struct dfs_referral_type *t =
291 &r->out.resp->referral_entries[i];
292 struct dfs_referral_v2 *v2 = &t->referral.v2;
295 v2->size = VERSION2_REFERRAL_SIZE;
297 v2->server_type = DFS_SERVER_ROOT;
299 v2->server_type = DFS_SERVER_NON_ROOT;
302 v2->proximity = ref->proximity;
304 v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
305 if (v2->DFS_path == NULL) {
306 return NT_STATUS_NO_MEMORY;
308 v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
309 if (v2->DFS_alt_path == NULL) {
310 return NT_STATUS_NO_MEMORY;
312 v2->netw_address = talloc_strdup(mem_ctx,
313 ref->alternate_path);
314 if (v2->netw_address == NULL) {
315 return NT_STATUS_NO_MEMORY;
321 for(i=0; i < junction->referral_count; i++) {
322 struct referral *ref = &junction->referral_list[i];
323 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
324 struct dfs_referral_type *t =
325 &r->out.resp->referral_entries[i];
326 struct dfs_referral_v3 *v3 = &t->referral.v3;
327 struct dfs_normal_referral *r1 = &v3->referrals.r1;
330 v3->size = VERSION3_REFERRAL_SIZE;
332 v3->server_type = DFS_SERVER_ROOT;
334 v3->server_type = DFS_SERVER_NON_ROOT;
338 r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
339 if (r1->DFS_path == NULL) {
340 return NT_STATUS_NO_MEMORY;
342 r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
343 if (r1->DFS_alt_path == NULL) {
344 return NT_STATUS_NO_MEMORY;
346 r1->netw_address = talloc_strdup(mem_ctx,
347 ref->alternate_path);
348 if (r1->netw_address == NULL) {
349 return NT_STATUS_NO_MEMORY;
354 DEBUG(0,("Invalid dfs referral version: %d\n",
355 max_referral_level));
356 return NT_STATUS_INVALID_LEVEL;
360 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
366 static NTSTATUS vfswrap_snap_check_path(struct vfs_handle_struct *handle,
368 const char *service_path,
371 return NT_STATUS_NOT_SUPPORTED;
374 static NTSTATUS vfswrap_snap_create(struct vfs_handle_struct *handle,
376 const char *base_volume,
382 return NT_STATUS_NOT_SUPPORTED;
385 static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle,
390 return NT_STATUS_NOT_SUPPORTED;
393 /* Directory operations */
395 static DIR *vfswrap_opendir(vfs_handle_struct *handle,
396 const struct smb_filename *smb_fname,
402 START_PROFILE(syscall_opendir);
403 result = opendir(smb_fname->base_name);
404 END_PROFILE(syscall_opendir);
408 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
415 START_PROFILE(syscall_fdopendir);
416 result = sys_fdopendir(fsp->fh->fd);
417 END_PROFILE(syscall_fdopendir);
422 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
424 SMB_STRUCT_STAT *sbuf)
426 struct dirent *result;
428 START_PROFILE(syscall_readdir);
429 result = readdir(dirp);
430 END_PROFILE(syscall_readdir);
432 /* Default Posix readdir() does not give us stat info.
433 * Set to invalid to indicate we didn't return this info. */
434 SET_STAT_INVALID(*sbuf);
435 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
436 if (result != NULL) {
437 /* See if we can efficiently return this. */
439 int flags = AT_SYMLINK_NOFOLLOW;
440 int ret = fstatat(dirfd(dirp),
445 * As this is an optimization,
446 * ignore it if we stat'ed a
447 * symlink. Make the caller
448 * do it again as we don't
449 * know if they wanted the link
450 * info, or its target info.
452 if ((ret == 0) && (!S_ISLNK(st.st_mode))) {
453 init_stat_ex_from_stat(sbuf,
455 lp_fake_directory_create_times(
456 SNUM(handle->conn)));
464 static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
465 const struct smb_filename *fname,
467 struct readdir_attr_data **attr_data)
469 return NT_STATUS_NOT_SUPPORTED;
472 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
474 START_PROFILE(syscall_seekdir);
475 seekdir(dirp, offset);
476 END_PROFILE(syscall_seekdir);
479 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
482 START_PROFILE(syscall_telldir);
483 result = telldir(dirp);
484 END_PROFILE(syscall_telldir);
488 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
490 START_PROFILE(syscall_rewinddir);
492 END_PROFILE(syscall_rewinddir);
495 static int vfswrap_mkdir(vfs_handle_struct *handle,
496 const struct smb_filename *smb_fname,
500 bool has_dacl = False;
501 const char *path = smb_fname->base_name;
504 START_PROFILE(syscall_mkdir);
506 if (lp_inherit_acls(SNUM(handle->conn))
507 && parent_dirname(talloc_tos(), path, &parent, NULL)
508 && (has_dacl = directory_has_default_acl(handle->conn, parent))) {
509 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
514 result = mkdir(path, mode);
516 if (result == 0 && !has_dacl) {
518 * We need to do this as the default behavior of POSIX ACLs
519 * is to set the mask to be the requested group permission
520 * bits, not the group permission bits to be the requested
521 * group permission bits. This is not what we want, as it will
522 * mess up any inherited ACL bits that were set. JRA.
524 int saved_errno = errno; /* We may get ENOSYS */
525 if ((SMB_VFS_CHMOD_ACL(handle->conn, smb_fname, mode) == -1) &&
531 END_PROFILE(syscall_mkdir);
535 static int vfswrap_rmdir(vfs_handle_struct *handle,
536 const struct smb_filename *smb_fname)
540 START_PROFILE(syscall_rmdir);
541 result = rmdir(smb_fname->base_name);
542 END_PROFILE(syscall_rmdir);
546 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
550 START_PROFILE(syscall_closedir);
551 result = closedir(dirp);
552 END_PROFILE(syscall_closedir);
556 static void vfswrap_init_search_op(vfs_handle_struct *handle,
559 /* Default behavior is a NOOP */
562 /* File operations */
564 static int vfswrap_open(vfs_handle_struct *handle,
565 struct smb_filename *smb_fname,
566 files_struct *fsp, int flags, mode_t mode)
570 START_PROFILE(syscall_open);
572 if (smb_fname->stream_name) {
577 result = open(smb_fname->base_name, flags, mode);
579 END_PROFILE(syscall_open);
583 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
584 struct smb_request *req,
585 uint16_t root_dir_fid,
586 struct smb_filename *smb_fname,
587 uint32_t access_mask,
588 uint32_t share_access,
589 uint32_t create_disposition,
590 uint32_t create_options,
591 uint32_t file_attributes,
592 uint32_t oplock_request,
593 struct smb2_lease *lease,
594 uint64_t allocation_size,
595 uint32_t private_flags,
596 struct security_descriptor *sd,
597 struct ea_list *ea_list,
598 files_struct **result,
600 const struct smb2_create_blobs *in_context_blobs,
601 struct smb2_create_blobs *out_context_blobs)
603 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
604 access_mask, share_access,
605 create_disposition, create_options,
606 file_attributes, oplock_request, lease,
607 allocation_size, private_flags,
609 pinfo, in_context_blobs, out_context_blobs);
612 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
616 START_PROFILE(syscall_close);
617 result = fd_close_posix(fsp);
618 END_PROFILE(syscall_close);
622 static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
626 START_PROFILE_BYTES(syscall_read, n);
627 result = sys_read(fsp->fh->fd, data, n);
628 END_PROFILE_BYTES(syscall_read);
632 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
633 size_t n, off_t offset)
637 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
638 START_PROFILE_BYTES(syscall_pread, n);
639 result = sys_pread(fsp->fh->fd, data, n, offset);
640 END_PROFILE_BYTES(syscall_pread);
642 if (result == -1 && errno == ESPIPE) {
643 /* Maintain the fiction that pipes can be seeked (sought?) on. */
644 result = SMB_VFS_READ(fsp, data, n);
648 #else /* HAVE_PREAD */
652 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
653 if (curr == -1 && errno == ESPIPE) {
654 /* Maintain the fiction that pipes can be seeked (sought?) on. */
655 result = SMB_VFS_READ(fsp, data, n);
660 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
665 result = SMB_VFS_READ(fsp, data, n);
668 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
671 #endif /* HAVE_PREAD */
676 static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
680 START_PROFILE_BYTES(syscall_write, n);
681 result = sys_write(fsp->fh->fd, data, n);
682 END_PROFILE_BYTES(syscall_write);
686 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
687 size_t n, off_t offset)
691 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
692 START_PROFILE_BYTES(syscall_pwrite, n);
693 result = sys_pwrite(fsp->fh->fd, data, n, offset);
694 END_PROFILE_BYTES(syscall_pwrite);
696 if (result == -1 && errno == ESPIPE) {
697 /* Maintain the fiction that pipes can be sought on. */
698 result = SMB_VFS_WRITE(fsp, data, n);
701 #else /* HAVE_PWRITE */
705 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
710 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
714 result = SMB_VFS_WRITE(fsp, data, n);
717 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
720 #endif /* HAVE_PWRITE */
725 static int vfswrap_init_pool(struct smbd_server_connection *conn)
729 if (conn->pool != NULL) {
733 ret = pthreadpool_tevent_init(conn, lp_aio_max_threads(),
738 struct vfswrap_pread_state {
746 struct vfs_aio_state vfs_aio_state;
747 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
750 static void vfs_pread_do(void *private_data);
751 static void vfs_pread_done(struct tevent_req *subreq);
753 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
755 struct tevent_context *ev,
756 struct files_struct *fsp,
758 size_t n, off_t offset)
760 struct tevent_req *req, *subreq;
761 struct vfswrap_pread_state *state;
764 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
769 ret = vfswrap_init_pool(handle->conn->sconn);
770 if (tevent_req_error(req, ret)) {
771 return tevent_req_post(req, ev);
775 state->fd = fsp->fh->fd;
778 state->offset = offset;
780 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
781 state->profile_bytes, n);
782 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
784 subreq = pthreadpool_tevent_job_send(
785 state, ev, handle->conn->sconn->pool,
786 vfs_pread_do, state);
787 if (tevent_req_nomem(subreq, req)) {
788 return tevent_req_post(req, ev);
790 tevent_req_set_callback(subreq, vfs_pread_done, req);
795 static void vfs_pread_do(void *private_data)
797 struct vfswrap_pread_state *state = talloc_get_type_abort(
798 private_data, struct vfswrap_pread_state);
799 struct timespec start_time;
800 struct timespec end_time;
802 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
804 PROFILE_TIMESTAMP(&start_time);
807 state->ret = pread(state->fd, state->buf, state->count,
809 } while ((state->ret == -1) && (errno == EINTR));
813 PROFILE_TIMESTAMP(&end_time);
815 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
817 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
820 static void vfs_pread_done(struct tevent_req *subreq)
822 struct tevent_req *req = tevent_req_callback_data(
823 subreq, struct tevent_req);
825 struct vfswrap_pread_state *state = tevent_req_data(
826 req, struct vfswrap_pread_state);
830 ret = pthreadpool_tevent_job_recv(subreq);
832 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
833 if (tevent_req_error(req, ret)) {
837 tevent_req_done(req);
840 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
841 struct vfs_aio_state *vfs_aio_state)
843 struct vfswrap_pread_state *state = tevent_req_data(
844 req, struct vfswrap_pread_state);
846 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
850 *vfs_aio_state = state->vfs_aio_state;
854 struct vfswrap_pwrite_state {
862 struct vfs_aio_state vfs_aio_state;
863 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
866 static void vfs_pwrite_do(void *private_data);
867 static void vfs_pwrite_done(struct tevent_req *subreq);
869 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
871 struct tevent_context *ev,
872 struct files_struct *fsp,
874 size_t n, off_t offset)
876 struct tevent_req *req, *subreq;
877 struct vfswrap_pwrite_state *state;
880 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
885 ret = vfswrap_init_pool(handle->conn->sconn);
886 if (tevent_req_error(req, ret)) {
887 return tevent_req_post(req, ev);
891 state->fd = fsp->fh->fd;
894 state->offset = offset;
896 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
897 state->profile_bytes, n);
898 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
900 subreq = pthreadpool_tevent_job_send(
901 state, ev, handle->conn->sconn->pool,
902 vfs_pwrite_do, state);
903 if (tevent_req_nomem(subreq, req)) {
904 return tevent_req_post(req, ev);
906 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
911 static void vfs_pwrite_do(void *private_data)
913 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
914 private_data, struct vfswrap_pwrite_state);
915 struct timespec start_time;
916 struct timespec end_time;
918 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
920 PROFILE_TIMESTAMP(&start_time);
923 state->ret = pwrite(state->fd, state->buf, state->count,
925 } while ((state->ret == -1) && (errno == EINTR));
929 PROFILE_TIMESTAMP(&end_time);
931 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
933 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
936 static void vfs_pwrite_done(struct tevent_req *subreq)
938 struct tevent_req *req = tevent_req_callback_data(
939 subreq, struct tevent_req);
941 struct vfswrap_pwrite_state *state = tevent_req_data(
942 req, struct vfswrap_pwrite_state);
946 ret = pthreadpool_tevent_job_recv(subreq);
948 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
949 if (tevent_req_error(req, ret)) {
953 tevent_req_done(req);
956 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
957 struct vfs_aio_state *vfs_aio_state)
959 struct vfswrap_pwrite_state *state = tevent_req_data(
960 req, struct vfswrap_pwrite_state);
962 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
966 *vfs_aio_state = state->vfs_aio_state;
970 struct vfswrap_fsync_state {
975 struct vfs_aio_state vfs_aio_state;
976 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
979 static void vfs_fsync_do(void *private_data);
980 static void vfs_fsync_done(struct tevent_req *subreq);
982 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
984 struct tevent_context *ev,
985 struct files_struct *fsp)
987 struct tevent_req *req, *subreq;
988 struct vfswrap_fsync_state *state;
991 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
996 ret = vfswrap_init_pool(handle->conn->sconn);
997 if (tevent_req_error(req, ret)) {
998 return tevent_req_post(req, ev);
1002 state->fd = fsp->fh->fd;
1004 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
1005 state->profile_basic);
1007 subreq = pthreadpool_tevent_job_send(
1008 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
1009 if (tevent_req_nomem(subreq, req)) {
1010 return tevent_req_post(req, ev);
1012 tevent_req_set_callback(subreq, vfs_fsync_done, req);
1017 static void vfs_fsync_do(void *private_data)
1019 struct vfswrap_fsync_state *state = talloc_get_type_abort(
1020 private_data, struct vfswrap_fsync_state);
1021 struct timespec start_time;
1022 struct timespec end_time;
1024 PROFILE_TIMESTAMP(&start_time);
1027 state->ret = fsync(state->fd);
1028 } while ((state->ret == -1) && (errno == EINTR));
1032 PROFILE_TIMESTAMP(&end_time);
1034 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1037 static void vfs_fsync_done(struct tevent_req *subreq)
1039 struct tevent_req *req = tevent_req_callback_data(
1040 subreq, struct tevent_req);
1042 struct vfswrap_fsync_state *state = tevent_req_data(
1043 req, struct vfswrap_fsync_state);
1047 ret = pthreadpool_tevent_job_recv(subreq);
1048 TALLOC_FREE(subreq);
1049 SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
1050 if (tevent_req_error(req, ret)) {
1054 tevent_req_done(req);
1057 static int vfswrap_fsync_recv(struct tevent_req *req,
1058 struct vfs_aio_state *vfs_aio_state)
1060 struct vfswrap_fsync_state *state = tevent_req_data(
1061 req, struct vfswrap_fsync_state);
1063 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1067 *vfs_aio_state = state->vfs_aio_state;
1071 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1075 START_PROFILE(syscall_lseek);
1077 /* Cope with 'stat' file opens. */
1078 if (fsp->fh->fd != -1)
1079 result = lseek(fsp->fh->fd, offset, whence);
1082 * We want to maintain the fiction that we can seek
1083 * on a fifo for file system purposes. This allows
1084 * people to set up UNIX fifo's that feed data to Windows
1085 * applications. JRA.
1088 if((result == -1) && (errno == ESPIPE)) {
1093 END_PROFILE(syscall_lseek);
1097 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1098 off_t offset, size_t n)
1102 START_PROFILE_BYTES(syscall_sendfile, n);
1103 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
1104 END_PROFILE_BYTES(syscall_sendfile);
1108 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1110 files_struct *tofsp,
1116 START_PROFILE_BYTES(syscall_recvfile, n);
1117 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
1118 END_PROFILE_BYTES(syscall_recvfile);
1122 static int vfswrap_rename(vfs_handle_struct *handle,
1123 const struct smb_filename *smb_fname_src,
1124 const struct smb_filename *smb_fname_dst)
1128 START_PROFILE(syscall_rename);
1130 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
1135 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
1138 END_PROFILE(syscall_rename);
1142 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
1147 START_PROFILE(syscall_fsync);
1148 result = fsync(fsp->fh->fd);
1149 END_PROFILE(syscall_fsync);
1156 static int vfswrap_stat(vfs_handle_struct *handle,
1157 struct smb_filename *smb_fname)
1161 START_PROFILE(syscall_stat);
1163 if (smb_fname->stream_name) {
1168 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1169 lp_fake_directory_create_times(SNUM(handle->conn)));
1171 END_PROFILE(syscall_stat);
1175 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1179 START_PROFILE(syscall_fstat);
1180 result = sys_fstat(fsp->fh->fd,
1181 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1182 END_PROFILE(syscall_fstat);
1186 static int vfswrap_lstat(vfs_handle_struct *handle,
1187 struct smb_filename *smb_fname)
1191 START_PROFILE(syscall_lstat);
1193 if (smb_fname->stream_name) {
1198 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1199 lp_fake_directory_create_times(SNUM(handle->conn)));
1201 END_PROFILE(syscall_lstat);
1205 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1207 enum vfs_translate_direction direction,
1208 TALLOC_CTX *mem_ctx,
1211 return NT_STATUS_NONE_MAPPED;
1215 * Implement the default fsctl operation.
1217 static bool vfswrap_logged_ioctl_message = false;
1219 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1220 struct files_struct *fsp,
1223 uint16_t req_flags, /* Needed for UNICODE ... */
1224 const uint8_t *_in_data,
1226 uint8_t **_out_data,
1227 uint32_t max_out_len,
1230 const char *in_data = (const char *)_in_data;
1231 char **out_data = (char **)_out_data;
1235 case FSCTL_SET_SPARSE:
1237 bool set_sparse = true;
1239 if (in_len >= 1 && in_data[0] == 0) {
1243 status = file_set_sparse(handle->conn, fsp, set_sparse);
1245 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1246 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1247 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1248 nt_errstr(status)));
1253 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1255 unsigned char objid[16];
1256 char *return_data = NULL;
1258 /* This should return the object-id on this file.
1259 * I think I'll make this be the inode+dev. JRA.
1262 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1263 fsp_fnum_dbg(fsp)));
1265 *out_len = MIN(max_out_len, 64);
1267 /* Hmmm, will this cause problems if less data asked for? */
1268 return_data = talloc_array(ctx, char, 64);
1269 if (return_data == NULL) {
1270 return NT_STATUS_NO_MEMORY;
1273 /* For backwards compatibility only store the dev/inode. */
1274 push_file_id_16(return_data, &fsp->file_id);
1275 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1276 push_file_id_16(return_data+32, &fsp->file_id);
1277 memset(return_data+48, 0, 16);
1278 *out_data = return_data;
1279 return NT_STATUS_OK;
1282 case FSCTL_GET_REPARSE_POINT:
1284 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1285 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1286 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1287 return NT_STATUS_NOT_A_REPARSE_POINT;
1290 case FSCTL_SET_REPARSE_POINT:
1292 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1293 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1294 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1295 return NT_STATUS_NOT_A_REPARSE_POINT;
1298 case FSCTL_GET_SHADOW_COPY_DATA:
1301 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1302 * and return their volume names. If max_data_count is 16, then it is just
1303 * asking for the number of volumes and length of the combined names.
1305 * pdata is the data allocated by our caller, but that uses
1306 * total_data_count (which is 0 in our case) rather than max_data_count.
1307 * Allocate the correct amount and return the pointer to let
1308 * it be deallocated when we return.
1310 struct shadow_copy_data *shadow_data = NULL;
1311 bool labels = False;
1312 uint32_t labels_data_count = 0;
1314 char *cur_pdata = NULL;
1316 if (max_out_len < 16) {
1317 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1319 return NT_STATUS_INVALID_PARAMETER;
1322 if (max_out_len > 16) {
1326 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1327 if (shadow_data == NULL) {
1328 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1329 return NT_STATUS_NO_MEMORY;
1333 * Call the VFS routine to actually do the work.
1335 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1338 /* broken module didn't set errno on error */
1339 status = NT_STATUS_UNSUCCESSFUL;
1341 status = map_nt_error_from_unix(errno);
1342 if (NT_STATUS_EQUAL(status,
1343 NT_STATUS_NOT_SUPPORTED)) {
1347 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1348 "connectpath %s, failed - %s.\n",
1349 fsp->conn->connectpath,
1350 nt_errstr(status)));
1351 TALLOC_FREE(shadow_data);
1355 labels_data_count = (shadow_data->num_volumes * 2 *
1356 sizeof(SHADOW_COPY_LABEL)) + 2;
1361 *out_len = 12 + labels_data_count;
1364 if (max_out_len < *out_len) {
1365 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1366 max_out_len, *out_len));
1367 TALLOC_FREE(shadow_data);
1368 return NT_STATUS_BUFFER_TOO_SMALL;
1371 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1372 if (cur_pdata == NULL) {
1373 TALLOC_FREE(shadow_data);
1374 return NT_STATUS_NO_MEMORY;
1377 *out_data = cur_pdata;
1379 /* num_volumes 4 bytes */
1380 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1383 /* num_labels 4 bytes */
1384 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1387 /* needed_data_count 4 bytes */
1388 SIVAL(cur_pdata, 8, labels_data_count);
1392 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1393 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1394 if (labels && shadow_data->labels) {
1395 for (i=0; i<shadow_data->num_volumes; i++) {
1397 status = srvstr_push(cur_pdata, req_flags,
1398 cur_pdata, shadow_data->labels[i],
1399 2 * sizeof(SHADOW_COPY_LABEL),
1400 STR_UNICODE|STR_TERMINATE, &len);
1401 if (!NT_STATUS_IS_OK(status)) {
1402 TALLOC_FREE(*out_data);
1403 TALLOC_FREE(shadow_data);
1406 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1407 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1411 TALLOC_FREE(shadow_data);
1413 return NT_STATUS_OK;
1416 case FSCTL_FIND_FILES_BY_SID:
1418 /* pretend this succeeded -
1420 * we have to send back a list with all files owned by this SID
1422 * but I have to check that --metze
1428 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1429 fsp_fnum_dbg(fsp)));
1432 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1433 return NT_STATUS_INVALID_PARAMETER;
1436 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1438 /* unknown 4 bytes: this is not the length of the sid :-( */
1439 /*unknown = IVAL(pdata,0);*/
1441 if (!sid_parse(_in_data + 4, sid_len, &sid)) {
1442 return NT_STATUS_INVALID_PARAMETER;
1444 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1446 if (!sid_to_uid(&sid, &uid)) {
1447 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1448 sid_string_dbg(&sid),
1449 (unsigned long)sid_len));
1453 /* we can take a look at the find source :-)
1455 * find ./ -uid $uid -name '*' is what we need here
1458 * and send 4bytes len and then NULL terminated unicode strings
1461 * but I don't know how to deal with the paged results
1462 * (maybe we can hang the result anywhere in the fsp struct)
1464 * but I don't know how to deal with the paged results
1465 * (maybe we can hang the result anywhere in the fsp struct)
1467 * we don't send all files at once
1468 * and at the next we should *not* start from the beginning,
1469 * so we have to cache the result
1474 /* this works for now... */
1475 return NT_STATUS_OK;
1478 case FSCTL_QUERY_ALLOCATED_RANGES:
1480 /* FIXME: This is just a dummy reply, telling that all of the
1481 * file is allocated. MKS cp needs that.
1482 * Adding the real allocated ranges via FIEMAP on Linux
1483 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1484 * this FSCTL correct for sparse files.
1486 uint64_t offset, length;
1487 char *out_data_tmp = NULL;
1490 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1492 return NT_STATUS_INVALID_PARAMETER;
1495 if (max_out_len < 16) {
1496 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1498 return NT_STATUS_INVALID_PARAMETER;
1501 offset = BVAL(in_data,0);
1502 length = BVAL(in_data,8);
1504 if (offset + length < offset) {
1505 /* No 64-bit integer wrap. */
1506 return NT_STATUS_INVALID_PARAMETER;
1509 /* Shouldn't this be SMB_VFS_STAT ... ? */
1510 status = vfs_stat_fsp(fsp);
1511 if (!NT_STATUS_IS_OK(status)) {
1516 out_data_tmp = talloc_array(ctx, char, *out_len);
1517 if (out_data_tmp == NULL) {
1518 DEBUG(10, ("unable to allocate memory for response\n"));
1519 return NT_STATUS_NO_MEMORY;
1522 if (offset > fsp->fsp_name->st.st_ex_size ||
1523 fsp->fsp_name->st.st_ex_size == 0 ||
1525 memset(out_data_tmp, 0, *out_len);
1527 uint64_t end = offset + length;
1528 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1529 SBVAL(out_data_tmp, 0, 0);
1530 SBVAL(out_data_tmp, 8, end);
1533 *out_data = out_data_tmp;
1535 return NT_STATUS_OK;
1538 case FSCTL_IS_VOLUME_DIRTY:
1540 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1541 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1543 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1544 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1546 return NT_STATUS_INVALID_PARAMETER;
1551 * Only print once ... unfortunately there could be lots of
1552 * different FSCTLs that are called.
1554 if (!vfswrap_logged_ioctl_message) {
1555 vfswrap_logged_ioctl_message = true;
1556 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1557 __func__, function));
1561 return NT_STATUS_NOT_SUPPORTED;
1564 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
1565 const struct smb_filename *fname,
1566 SMB_STRUCT_STAT *sbuf);
1568 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1569 struct smb_filename *smb_fname,
1574 offline = vfswrap_is_offline(handle, smb_fname, &smb_fname->st);
1576 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1579 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1582 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1583 struct files_struct *fsp,
1588 offline = vfswrap_is_offline(handle, fsp->fsp_name, &fsp->fsp_name->st);
1590 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1593 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1596 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1597 const struct smb_filename *smb_fname,
1600 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1603 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1604 struct files_struct *fsp,
1607 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1610 struct vfs_cc_state {
1611 struct tevent_context *ev;
1613 bool read_lck_locked;
1614 struct lock_struct read_lck;
1615 bool write_lck_locked;
1616 struct lock_struct write_lck;
1617 struct files_struct *src_fsp;
1619 struct files_struct *dst_fsp;
1623 size_t next_io_size;
1627 static NTSTATUS copy_chunk_loop(struct tevent_req *req);
1629 static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *handle,
1630 TALLOC_CTX *mem_ctx,
1631 struct tevent_context *ev,
1632 struct files_struct *src_fsp,
1634 struct files_struct *dest_fsp,
1639 struct tevent_req *req;
1640 struct vfs_cc_state *state = NULL;
1641 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
1644 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
1646 req = tevent_req_create(mem_ctx, &state, struct vfs_cc_state);
1651 if (flags & ~VFS_COPY_CHUNK_FL_MASK_ALL) {
1652 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1653 return tevent_req_post(req, ev);
1656 if (flags & VFS_COPY_CHUNK_FL_MUST_CLONE) {
1657 DEBUG(10, ("COW clones not supported by vfs_default\n"));
1658 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1659 return tevent_req_post(req, ev);
1662 *state = (struct vfs_cc_state) {
1666 .dst_fsp = dest_fsp,
1667 .dst_off = dest_off,
1669 .remaining = to_copy,
1672 state->buf = talloc_array(state, uint8_t, num);
1673 if (tevent_req_nomem(state->buf, req)) {
1674 return tevent_req_post(req, ev);
1677 status = vfs_stat_fsp(src_fsp);
1678 if (tevent_req_nterror(req, status)) {
1679 return tevent_req_post(req, ev);
1682 if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
1684 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1685 * If the SourceOffset or SourceOffset + Length extends beyond
1686 * the end of file, the server SHOULD<240> treat this as a
1687 * STATUS_END_OF_FILE error.
1689 * <240> Section 3.3.5.15.6: Windows servers will return
1690 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1692 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1693 return tevent_req_post(req, ev);
1696 if (src_fsp->op == NULL) {
1697 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1698 return tevent_req_post(req, ev);
1701 if (dest_fsp->op == NULL) {
1702 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1703 return tevent_req_post(req, ev);
1706 status = copy_chunk_loop(req);
1707 if (!NT_STATUS_IS_OK(status)) {
1708 tevent_req_nterror(req, status);
1709 return tevent_req_post(req, ev);
1715 static void vfswrap_copy_chunk_read_done(struct tevent_req *subreq);
1717 static NTSTATUS copy_chunk_loop(struct tevent_req *req)
1719 struct vfs_cc_state *state = tevent_req_data(req, struct vfs_cc_state);
1720 struct tevent_req *subreq = NULL;
1723 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
1725 if (!(state->flags & VFS_COPY_CHUNK_FL_IGNORE_LOCKS)) {
1726 init_strict_lock_struct(state->src_fsp,
1727 state->src_fsp->op->global->open_persistent_id,
1729 state->next_io_size,
1733 ok = SMB_VFS_STRICT_LOCK(state->src_fsp->conn,
1737 return NT_STATUS_FILE_LOCK_CONFLICT;
1741 subreq = SMB_VFS_PREAD_SEND(state,
1742 state->src_fsp->conn->sconn->ev_ctx,
1745 state->next_io_size,
1747 if (subreq == NULL) {
1748 return NT_STATUS_NO_MEMORY;
1750 tevent_req_set_callback(subreq, vfswrap_copy_chunk_read_done, req);
1752 return NT_STATUS_OK;
1755 static void vfswrap_copy_chunk_write_done(struct tevent_req *subreq);
1757 static void vfswrap_copy_chunk_read_done(struct tevent_req *subreq)
1759 struct tevent_req *req = tevent_req_callback_data(
1760 subreq, struct tevent_req);
1761 struct vfs_cc_state *state = tevent_req_data(req, struct vfs_cc_state);
1762 struct vfs_aio_state aio_state;
1766 if (!(state->flags & VFS_COPY_CHUNK_FL_IGNORE_LOCKS)) {
1767 SMB_VFS_STRICT_UNLOCK(state->src_fsp->conn,
1770 ZERO_STRUCT(state->read_lck);
1773 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
1774 TALLOC_FREE(subreq);
1776 DBG_ERR("read failed: %s\n", strerror(errno));
1777 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1780 if (nread != state->next_io_size) {
1781 DBG_ERR("Short read, only %zd of %zu\n",
1782 nread, state->next_io_size);
1783 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1787 state->src_off += nread;
1789 if (!(state->flags & VFS_COPY_CHUNK_FL_IGNORE_LOCKS)) {
1790 init_strict_lock_struct(state->dst_fsp,
1791 state->dst_fsp->op->global->open_persistent_id,
1793 state->next_io_size,
1797 ok = SMB_VFS_STRICT_LOCK(state->dst_fsp->conn,
1801 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1806 subreq = SMB_VFS_PWRITE_SEND(state,
1810 state->next_io_size,
1812 if (subreq == NULL) {
1813 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1816 tevent_req_set_callback(subreq, vfswrap_copy_chunk_write_done, req);
1819 static void vfswrap_copy_chunk_write_done(struct tevent_req *subreq)
1821 struct tevent_req *req = tevent_req_callback_data(
1822 subreq, struct tevent_req);
1823 struct vfs_cc_state *state = tevent_req_data(req, struct vfs_cc_state);
1824 struct vfs_aio_state aio_state;
1828 if (!(state->flags & VFS_COPY_CHUNK_FL_IGNORE_LOCKS)) {
1829 SMB_VFS_STRICT_UNLOCK(state->dst_fsp->conn,
1832 ZERO_STRUCT(state->write_lck);
1835 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
1836 TALLOC_FREE(subreq);
1837 if (nwritten == -1) {
1838 DBG_ERR("write failed: %s\n", strerror(errno));
1839 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1842 if (nwritten != state->next_io_size) {
1843 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
1844 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1848 state->dst_off += nwritten;
1850 if (state->remaining < nwritten) {
1851 /* Paranoia check */
1852 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1855 state->remaining -= nwritten;
1856 if (state->remaining == 0) {
1857 tevent_req_done(req);
1861 status = copy_chunk_loop(req);
1862 if (!NT_STATUS_IS_OK(status)) {
1863 tevent_req_nterror(req, status);
1870 static NTSTATUS vfswrap_copy_chunk_recv(struct vfs_handle_struct *handle,
1871 struct tevent_req *req,
1874 struct vfs_cc_state *state = tevent_req_data(req, struct vfs_cc_state);
1877 if (tevent_req_is_nterror(req, &status)) {
1878 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
1880 tevent_req_received(req);
1884 *copied = state->to_copy;
1885 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
1886 tevent_req_received(req);
1888 return NT_STATUS_OK;
1891 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1892 TALLOC_CTX *mem_ctx,
1893 struct files_struct *fsp,
1894 struct smb_filename *smb_fname,
1895 uint16_t *_compression_fmt)
1897 return NT_STATUS_INVALID_DEVICE_REQUEST;
1900 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1901 TALLOC_CTX *mem_ctx,
1902 struct files_struct *fsp,
1903 uint16_t compression_fmt)
1905 return NT_STATUS_INVALID_DEVICE_REQUEST;
1908 /********************************************************************
1909 Given a stat buffer return the allocated size on disk, taking into
1910 account sparse files.
1911 ********************************************************************/
1912 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1913 struct files_struct *fsp,
1914 const SMB_STRUCT_STAT *sbuf)
1918 START_PROFILE(syscall_get_alloc_size);
1920 if(S_ISDIR(sbuf->st_ex_mode)) {
1925 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1926 /* The type of st_blocksize is blkcnt_t which *MUST* be
1927 signed (according to POSIX) and can be less than 64-bits.
1928 Ensure when we're converting to 64 bits wide we don't
1930 #if defined(SIZEOF_BLKCNT_T_8)
1931 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1932 #elif defined(SIZEOF_BLKCNT_T_4)
1934 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1935 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1938 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1942 * Some file systems do not allocate a block for very
1943 * small files. But for non-empty file should report a
1947 uint64_t filesize = get_file_size_stat(sbuf);
1949 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
1953 result = get_file_size_stat(sbuf);
1956 if (fsp && fsp->initial_allocation_size)
1957 result = MAX(result,fsp->initial_allocation_size);
1959 result = smb_roundup(handle->conn, result);
1962 END_PROFILE(syscall_get_alloc_size);
1966 static int vfswrap_unlink(vfs_handle_struct *handle,
1967 const struct smb_filename *smb_fname)
1971 START_PROFILE(syscall_unlink);
1973 if (smb_fname->stream_name) {
1977 result = unlink(smb_fname->base_name);
1980 END_PROFILE(syscall_unlink);
1984 static int vfswrap_chmod(vfs_handle_struct *handle,
1985 const struct smb_filename *smb_fname,
1990 START_PROFILE(syscall_chmod);
1993 * We need to do this due to the fact that the default POSIX ACL
1994 * chmod modifies the ACL *mask* for the group owner, not the
1995 * group owner bits directly. JRA.
2000 int saved_errno = errno; /* We might get ENOSYS */
2001 result = SMB_VFS_CHMOD_ACL(handle->conn,
2005 END_PROFILE(syscall_chmod);
2008 /* Error - return the old errno. */
2009 errno = saved_errno;
2012 result = chmod(smb_fname->base_name, mode);
2013 END_PROFILE(syscall_chmod);
2017 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2021 START_PROFILE(syscall_fchmod);
2024 * We need to do this due to the fact that the default POSIX ACL
2025 * chmod modifies the ACL *mask* for the group owner, not the
2026 * group owner bits directly. JRA.
2030 int saved_errno = errno; /* We might get ENOSYS */
2031 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
2032 END_PROFILE(syscall_fchmod);
2035 /* Error - return the old errno. */
2036 errno = saved_errno;
2039 #if defined(HAVE_FCHMOD)
2040 result = fchmod(fsp->fh->fd, mode);
2046 END_PROFILE(syscall_fchmod);
2050 static int vfswrap_chown(vfs_handle_struct *handle,
2051 const struct smb_filename *smb_fname,
2057 START_PROFILE(syscall_chown);
2058 result = chown(smb_fname->base_name, uid, gid);
2059 END_PROFILE(syscall_chown);
2063 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2068 START_PROFILE(syscall_fchown);
2069 result = fchown(fsp->fh->fd, uid, gid);
2070 END_PROFILE(syscall_fchown);
2078 static int vfswrap_lchown(vfs_handle_struct *handle,
2079 const struct smb_filename *smb_fname,
2085 START_PROFILE(syscall_lchown);
2086 result = lchown(smb_fname->base_name, uid, gid);
2087 END_PROFILE(syscall_lchown);
2091 static int vfswrap_chdir(vfs_handle_struct *handle,
2092 const struct smb_filename *smb_fname)
2096 START_PROFILE(syscall_chdir);
2097 result = chdir(smb_fname->base_name);
2098 END_PROFILE(syscall_chdir);
2102 static char *vfswrap_getwd(vfs_handle_struct *handle)
2106 START_PROFILE(syscall_getwd);
2107 result = sys_getwd();
2108 END_PROFILE(syscall_getwd);
2112 /*********************************************************************
2113 nsec timestamp resolution call. Convert down to whatever the underlying
2114 system will support.
2115 **********************************************************************/
2117 static int vfswrap_ntimes(vfs_handle_struct *handle,
2118 const struct smb_filename *smb_fname,
2119 struct smb_file_time *ft)
2123 START_PROFILE(syscall_ntimes);
2125 if (smb_fname->stream_name) {
2131 if (null_timespec(ft->atime)) {
2132 ft->atime= smb_fname->st.st_ex_atime;
2135 if (null_timespec(ft->mtime)) {
2136 ft->mtime = smb_fname->st.st_ex_mtime;
2139 if (!null_timespec(ft->create_time)) {
2140 set_create_timespec_ea(handle->conn,
2145 if ((timespec_compare(&ft->atime,
2146 &smb_fname->st.st_ex_atime) == 0) &&
2147 (timespec_compare(&ft->mtime,
2148 &smb_fname->st.st_ex_mtime) == 0)) {
2153 #if defined(HAVE_UTIMENSAT)
2155 struct timespec ts[2];
2158 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2160 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2162 if (!((result == -1) && (errno == ENOSYS))) {
2166 #if defined(HAVE_UTIMES)
2168 struct timeval tv[2];
2169 tv[0] = convert_timespec_to_timeval(ft->atime);
2170 tv[1] = convert_timespec_to_timeval(ft->mtime);
2171 result = utimes(smb_fname->base_name, tv);
2173 result = utimes(smb_fname->base_name, NULL);
2175 if (!((result == -1) && (errno == ENOSYS))) {
2179 #if defined(HAVE_UTIME)
2181 struct utimbuf times;
2182 times.actime = convert_timespec_to_time_t(ft->atime);
2183 times.modtime = convert_timespec_to_time_t(ft->mtime);
2184 result = utime(smb_fname->base_name, ×);
2186 result = utime(smb_fname->base_name, NULL);
2188 if (!((result == -1) && (errno == ENOSYS))) {
2196 END_PROFILE(syscall_ntimes);
2200 /*********************************************************************
2201 A version of ftruncate that will write the space on disk if strict
2203 **********************************************************************/
2205 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2207 off_t space_to_write;
2208 uint64_t space_avail;
2209 uint64_t bsize,dfree,dsize;
2212 SMB_STRUCT_STAT *pst;
2214 status = vfs_stat_fsp(fsp);
2215 if (!NT_STATUS_IS_OK(status)) {
2218 pst = &fsp->fsp_name->st;
2221 if (S_ISFIFO(pst->st_ex_mode))
2225 if (pst->st_ex_size == len)
2228 /* Shrink - just ftruncate. */
2229 if (pst->st_ex_size > len)
2230 return ftruncate(fsp->fh->fd, len);
2232 space_to_write = len - pst->st_ex_size;
2234 /* for allocation try fallocate first. This can fail on some
2235 platforms e.g. when the filesystem doesn't support it and no
2236 emulation is being done by the libc (like on AIX with JFS1). In that
2237 case we do our own emulation. fallocate implementations can
2238 return ENOTSUP or EINVAL in cases like that. */
2239 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2240 if (ret == -1 && errno == ENOSPC) {
2246 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2247 "error %d. Falling back to slow manual allocation\n", errno));
2249 /* available disk space is enough or not? */
2251 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2252 /* space_avail is 1k blocks */
2253 if (space_avail == (uint64_t)-1 ||
2254 ((uint64_t)space_to_write/1024 > space_avail) ) {
2259 /* Write out the real space on disk. */
2260 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2268 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2271 SMB_STRUCT_STAT *pst;
2275 START_PROFILE(syscall_ftruncate);
2277 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2278 result = strict_allocate_ftruncate(handle, fsp, len);
2279 END_PROFILE(syscall_ftruncate);
2283 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2284 ftruncate if the system supports it. Then I discovered that
2285 you can have some filesystems that support ftruncate
2286 expansion and some that don't! On Linux fat can't do
2287 ftruncate extend but ext2 can. */
2289 result = ftruncate(fsp->fh->fd, len);
2291 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2292 extend a file with ftruncate. Provide alternate implementation
2295 /* Do an fstat to see if the file is longer than the requested
2296 size in which case the ftruncate above should have
2297 succeeded or shorter, in which case seek to len - 1 and
2298 write 1 byte of zero */
2299 status = vfs_stat_fsp(fsp);
2300 if (!NT_STATUS_IS_OK(status)) {
2304 /* We need to update the files_struct after successful ftruncate */
2309 pst = &fsp->fsp_name->st;
2312 if (S_ISFIFO(pst->st_ex_mode)) {
2318 if (pst->st_ex_size == len) {
2323 if (pst->st_ex_size > len) {
2324 /* the ftruncate should have worked */
2328 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2336 END_PROFILE(syscall_ftruncate);
2340 static int vfswrap_fallocate(vfs_handle_struct *handle,
2348 START_PROFILE(syscall_fallocate);
2350 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2352 * posix_fallocate returns 0 on success, errno on error
2353 * and doesn't set errno. Make it behave like fallocate()
2354 * which returns -1, and sets errno on failure.
2361 /* sys_fallocate handles filtering of unsupported mode flags */
2362 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2364 END_PROFILE(syscall_fallocate);
2368 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2372 START_PROFILE(syscall_fcntl_lock);
2374 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2376 "force process locks",
2378 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2381 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2382 END_PROFILE(syscall_fcntl_lock);
2386 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2387 uint32_t share_mode, uint32_t access_mask)
2389 START_PROFILE(syscall_kernel_flock);
2390 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2391 END_PROFILE(syscall_kernel_flock);
2395 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2400 START_PROFILE(syscall_fcntl_getlock);
2402 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2404 "force process locks",
2406 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2409 result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2410 END_PROFILE(syscall_fcntl_getlock);
2414 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2419 START_PROFILE(syscall_linux_setlease);
2421 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2422 result = linux_setlease(fsp->fh->fd, leasetype);
2426 END_PROFILE(syscall_linux_setlease);
2430 static int vfswrap_symlink(vfs_handle_struct *handle,
2431 const char *link_target,
2432 const struct smb_filename *new_smb_fname)
2436 START_PROFILE(syscall_symlink);
2437 result = symlink(link_target, new_smb_fname->base_name);
2438 END_PROFILE(syscall_symlink);
2442 static int vfswrap_readlink(vfs_handle_struct *handle,
2443 const struct smb_filename *smb_fname,
2449 START_PROFILE(syscall_readlink);
2450 result = readlink(smb_fname->base_name, buf, bufsiz);
2451 END_PROFILE(syscall_readlink);
2455 static int vfswrap_link(vfs_handle_struct *handle,
2456 const struct smb_filename *old_smb_fname,
2457 const struct smb_filename *new_smb_fname)
2461 START_PROFILE(syscall_link);
2462 result = link(old_smb_fname->base_name, new_smb_fname->base_name);
2463 END_PROFILE(syscall_link);
2467 static int vfswrap_mknod(vfs_handle_struct *handle,
2468 const struct smb_filename *smb_fname,
2474 START_PROFILE(syscall_mknod);
2475 result = sys_mknod(smb_fname->base_name, mode, dev);
2476 END_PROFILE(syscall_mknod);
2480 static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
2484 START_PROFILE(syscall_realpath);
2485 result = sys_realpath(path);
2486 END_PROFILE(syscall_realpath);
2490 static int vfswrap_chflags(vfs_handle_struct *handle,
2491 const struct smb_filename *smb_fname,
2495 return chflags(smb_fname->base_name, flags);
2502 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2503 const SMB_STRUCT_STAT *sbuf)
2507 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2511 key.devid = sbuf->st_ex_dev;
2512 key.inode = sbuf->st_ex_ino;
2513 /* key.extid is unused by default. */
2518 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2519 struct files_struct *fsp,
2520 const struct smb_filename *smb_fname,
2521 TALLOC_CTX *mem_ctx,
2522 unsigned int *pnum_streams,
2523 struct stream_struct **pstreams)
2525 SMB_STRUCT_STAT sbuf;
2526 struct stream_struct *tmp_streams = NULL;
2529 if ((fsp != NULL) && (fsp->is_directory)) {
2531 * No default streams on directories
2536 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2537 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2540 struct smb_filename smb_fname_cp;
2542 ZERO_STRUCT(smb_fname_cp);
2543 smb_fname_cp.base_name = discard_const_p(char,
2544 smb_fname->base_name);
2545 smb_fname_cp.flags = smb_fname->flags;
2547 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
2548 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2550 ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2552 sbuf = smb_fname_cp.st;
2556 return map_nt_error_from_unix(errno);
2559 if (S_ISDIR(sbuf.st_ex_mode)) {
2563 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2564 (*pnum_streams) + 1);
2565 if (tmp_streams == NULL) {
2566 return NT_STATUS_NO_MEMORY;
2568 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2569 if (tmp_streams[*pnum_streams].name == NULL) {
2570 return NT_STATUS_NO_MEMORY;
2572 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2573 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2576 *pstreams = tmp_streams;
2578 return NT_STATUS_OK;
2581 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2584 TALLOC_CTX *mem_ctx,
2588 * Don't fall back to get_real_filename so callers can differentiate
2589 * between a full directory scan and an actual case-insensitive stat.
2595 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2598 return handle->conn->connectpath;
2601 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2602 struct byte_range_lock *br_lck,
2603 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_windows_default(br_lck, plock, blocking_lock);
2612 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2613 struct messaging_context *msg_ctx,
2614 struct byte_range_lock *br_lck,
2615 const struct lock_struct *plock)
2617 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2619 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2622 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2623 struct byte_range_lock *br_lck,
2624 struct lock_struct *plock)
2626 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2628 /* Note: blr is not used in the default implementation. */
2629 return brl_lock_cancel_default(br_lck, plock);
2632 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2634 struct lock_struct *plock)
2636 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2637 plock->lock_type == WRITE_LOCK);
2639 return strict_lock_default(fsp, plock);
2642 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2644 struct lock_struct *plock)
2646 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2647 plock->lock_type == WRITE_LOCK);
2649 strict_unlock_default(fsp, plock);
2652 /* NT ACL operations. */
2654 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2656 uint32_t security_info,
2657 TALLOC_CTX *mem_ctx,
2658 struct security_descriptor **ppdesc)
2662 START_PROFILE(fget_nt_acl);
2663 result = posix_fget_nt_acl(fsp, security_info,
2665 END_PROFILE(fget_nt_acl);
2669 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2670 const struct smb_filename *smb_fname,
2671 uint32_t security_info,
2672 TALLOC_CTX *mem_ctx,
2673 struct security_descriptor **ppdesc)
2677 START_PROFILE(get_nt_acl);
2678 result = posix_get_nt_acl(handle->conn,
2683 END_PROFILE(get_nt_acl);
2687 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2691 START_PROFILE(fset_nt_acl);
2692 result = set_nt_acl(fsp, security_info_sent, psd);
2693 END_PROFILE(fset_nt_acl);
2697 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2698 struct smb_filename *file,
2699 struct security_acl *sacl,
2700 uint32_t access_requested,
2701 uint32_t access_denied)
2703 return NT_STATUS_OK; /* Nothing to do here ... */
2706 static int vfswrap_chmod_acl(vfs_handle_struct *handle,
2707 const struct smb_filename *smb_fname,
2716 START_PROFILE(chmod_acl);
2717 result = chmod_acl(handle->conn, smb_fname, mode);
2718 END_PROFILE(chmod_acl);
2723 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2731 START_PROFILE(fchmod_acl);
2732 result = fchmod_acl(fsp, mode);
2733 END_PROFILE(fchmod_acl);
2738 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2739 const struct smb_filename *smb_fname,
2740 SMB_ACL_TYPE_T type,
2741 TALLOC_CTX *mem_ctx)
2743 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
2746 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2748 TALLOC_CTX *mem_ctx)
2750 return sys_acl_get_fd(handle, fsp, mem_ctx);
2753 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
2754 const struct smb_filename *smb_fname,
2755 SMB_ACL_TYPE_T acltype,
2758 return sys_acl_set_file(handle, smb_fname, acltype, theacl);
2761 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2763 return sys_acl_set_fd(handle, fsp, theacl);
2766 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
2767 const struct smb_filename *smb_fname)
2769 return sys_acl_delete_def_file(handle, smb_fname);
2772 /****************************************************************
2773 Extended attribute operations.
2774 *****************************************************************/
2776 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
2777 const struct smb_filename *smb_fname,
2782 return getxattr(smb_fname->base_name, name, value, size);
2785 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2787 return fgetxattr(fsp->fh->fd, name, value, size);
2790 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
2791 const struct smb_filename *smb_fname,
2795 return listxattr(smb_fname->base_name, list, size);
2798 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2800 return flistxattr(fsp->fh->fd, list, size);
2803 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
2804 const struct smb_filename *smb_fname,
2807 return removexattr(smb_fname->base_name, name);
2810 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2812 return fremovexattr(fsp->fh->fd, name);
2815 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
2816 const struct smb_filename *smb_fname,
2822 return setxattr(smb_fname->base_name, name, value, size, flags);
2825 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2827 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2830 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2835 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2836 const struct smb_filename *fname,
2837 SMB_STRUCT_STAT *sbuf)
2841 bool offline = false;
2843 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2847 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2848 #if defined(ENOTSUP)
2854 status = get_full_smb_filename(talloc_tos(), fname, &path);
2855 if (!NT_STATUS_IS_OK(status)) {
2856 errno = map_errno_from_nt_status(status);
2860 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2867 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2868 struct files_struct *fsp,
2869 TALLOC_CTX *mem_ctx,
2872 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2875 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2876 struct files_struct *fsp,
2877 const DATA_BLOB old_cookie,
2878 TALLOC_CTX *mem_ctx,
2879 DATA_BLOB *new_cookie)
2881 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2885 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2886 struct smb_request *smb1req,
2887 struct smbXsrv_open *op,
2888 const DATA_BLOB old_cookie,
2889 TALLOC_CTX *mem_ctx,
2890 struct files_struct **fsp,
2891 DATA_BLOB *new_cookie)
2893 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2894 old_cookie, mem_ctx,
2898 static struct vfs_fn_pointers vfs_default_fns = {
2899 /* Disk operations */
2901 .connect_fn = vfswrap_connect,
2902 .disconnect_fn = vfswrap_disconnect,
2903 .disk_free_fn = vfswrap_disk_free,
2904 .get_quota_fn = vfswrap_get_quota,
2905 .set_quota_fn = vfswrap_set_quota,
2906 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2907 .statvfs_fn = vfswrap_statvfs,
2908 .fs_capabilities_fn = vfswrap_fs_capabilities,
2909 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2910 .snap_check_path_fn = vfswrap_snap_check_path,
2911 .snap_create_fn = vfswrap_snap_create,
2912 .snap_delete_fn = vfswrap_snap_delete,
2914 /* Directory operations */
2916 .opendir_fn = vfswrap_opendir,
2917 .fdopendir_fn = vfswrap_fdopendir,
2918 .readdir_fn = vfswrap_readdir,
2919 .readdir_attr_fn = vfswrap_readdir_attr,
2920 .seekdir_fn = vfswrap_seekdir,
2921 .telldir_fn = vfswrap_telldir,
2922 .rewind_dir_fn = vfswrap_rewinddir,
2923 .mkdir_fn = vfswrap_mkdir,
2924 .rmdir_fn = vfswrap_rmdir,
2925 .closedir_fn = vfswrap_closedir,
2926 .init_search_op_fn = vfswrap_init_search_op,
2928 /* File operations */
2930 .open_fn = vfswrap_open,
2931 .create_file_fn = vfswrap_create_file,
2932 .close_fn = vfswrap_close,
2933 .read_fn = vfswrap_read,
2934 .pread_fn = vfswrap_pread,
2935 .pread_send_fn = vfswrap_pread_send,
2936 .pread_recv_fn = vfswrap_pread_recv,
2937 .write_fn = vfswrap_write,
2938 .pwrite_fn = vfswrap_pwrite,
2939 .pwrite_send_fn = vfswrap_pwrite_send,
2940 .pwrite_recv_fn = vfswrap_pwrite_recv,
2941 .lseek_fn = vfswrap_lseek,
2942 .sendfile_fn = vfswrap_sendfile,
2943 .recvfile_fn = vfswrap_recvfile,
2944 .rename_fn = vfswrap_rename,
2945 .fsync_fn = vfswrap_fsync,
2946 .fsync_send_fn = vfswrap_fsync_send,
2947 .fsync_recv_fn = vfswrap_fsync_recv,
2948 .stat_fn = vfswrap_stat,
2949 .fstat_fn = vfswrap_fstat,
2950 .lstat_fn = vfswrap_lstat,
2951 .get_alloc_size_fn = vfswrap_get_alloc_size,
2952 .unlink_fn = vfswrap_unlink,
2953 .chmod_fn = vfswrap_chmod,
2954 .fchmod_fn = vfswrap_fchmod,
2955 .chown_fn = vfswrap_chown,
2956 .fchown_fn = vfswrap_fchown,
2957 .lchown_fn = vfswrap_lchown,
2958 .chdir_fn = vfswrap_chdir,
2959 .getwd_fn = vfswrap_getwd,
2960 .ntimes_fn = vfswrap_ntimes,
2961 .ftruncate_fn = vfswrap_ftruncate,
2962 .fallocate_fn = vfswrap_fallocate,
2963 .lock_fn = vfswrap_lock,
2964 .kernel_flock_fn = vfswrap_kernel_flock,
2965 .linux_setlease_fn = vfswrap_linux_setlease,
2966 .getlock_fn = vfswrap_getlock,
2967 .symlink_fn = vfswrap_symlink,
2968 .readlink_fn = vfswrap_readlink,
2969 .link_fn = vfswrap_link,
2970 .mknod_fn = vfswrap_mknod,
2971 .realpath_fn = vfswrap_realpath,
2972 .chflags_fn = vfswrap_chflags,
2973 .file_id_create_fn = vfswrap_file_id_create,
2974 .streaminfo_fn = vfswrap_streaminfo,
2975 .get_real_filename_fn = vfswrap_get_real_filename,
2976 .connectpath_fn = vfswrap_connectpath,
2977 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2978 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2979 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2980 .strict_lock_fn = vfswrap_strict_lock,
2981 .strict_unlock_fn = vfswrap_strict_unlock,
2982 .translate_name_fn = vfswrap_translate_name,
2983 .fsctl_fn = vfswrap_fsctl,
2984 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
2985 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
2986 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
2987 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
2988 .copy_chunk_send_fn = vfswrap_copy_chunk_send,
2989 .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
2990 .get_compression_fn = vfswrap_get_compression,
2991 .set_compression_fn = vfswrap_set_compression,
2993 /* NT ACL operations. */
2995 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2996 .get_nt_acl_fn = vfswrap_get_nt_acl,
2997 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2998 .audit_file_fn = vfswrap_audit_file,
3000 /* POSIX ACL operations. */
3002 .chmod_acl_fn = vfswrap_chmod_acl,
3003 .fchmod_acl_fn = vfswrap_fchmod_acl,
3005 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
3006 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3007 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
3008 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3009 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
3010 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3011 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
3013 /* EA operations. */
3014 .getxattr_fn = vfswrap_getxattr,
3015 .fgetxattr_fn = vfswrap_fgetxattr,
3016 .listxattr_fn = vfswrap_listxattr,
3017 .flistxattr_fn = vfswrap_flistxattr,
3018 .removexattr_fn = vfswrap_removexattr,
3019 .fremovexattr_fn = vfswrap_fremovexattr,
3020 .setxattr_fn = vfswrap_setxattr,
3021 .fsetxattr_fn = vfswrap_fsetxattr,
3023 /* aio operations */
3024 .aio_force_fn = vfswrap_aio_force,
3026 /* durable handle operations */
3027 .durable_cookie_fn = vfswrap_durable_cookie,
3028 .durable_disconnect_fn = vfswrap_durable_disconnect,
3029 .durable_reconnect_fn = vfswrap_durable_reconnect,
3032 NTSTATUS vfs_default_init(TALLOC_CTX *);
3033 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3035 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3036 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);