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, const char *path, vfs_statvfs_struct *statbuf)
117 return sys_statvfs(path, statbuf);
120 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
121 enum timestamp_set_resolution *p_ts_res)
123 connection_struct *conn = handle->conn;
124 uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
125 struct smb_filename *smb_fname_cpath = NULL;
126 struct vfs_statvfs_struct statbuf;
129 ZERO_STRUCT(statbuf);
130 ret = sys_statvfs(conn->connectpath, &statbuf);
132 caps = statbuf.FsCapabilities;
135 *p_ts_res = TIMESTAMP_SET_SECONDS;
137 /* Work out what timestamp resolution we can
138 * use when setting a timestamp. */
140 smb_fname_cpath = synthetic_smb_fname(talloc_tos(), conn->connectpath,
142 if (smb_fname_cpath == NULL) {
146 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
148 TALLOC_FREE(smb_fname_cpath);
152 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
153 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
154 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
155 /* If any of the normal UNIX directory timestamps
156 * have a non-zero tv_nsec component assume
157 * we might be able to set sub-second timestamps.
158 * See what filetime set primitives we have.
160 #if defined(HAVE_UTIMENSAT)
161 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
162 #elif defined(HAVE_UTIMES)
163 /* utimes allows msec timestamps to be set. */
164 *p_ts_res = TIMESTAMP_SET_MSEC;
165 #elif defined(HAVE_UTIME)
166 /* utime only allows sec timestamps to be set. */
167 *p_ts_res = TIMESTAMP_SET_SECONDS;
170 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
172 "available on share %s, directory %s\n",
173 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
174 lp_servicename(talloc_tos(), conn->params->service),
175 conn->connectpath ));
177 TALLOC_FREE(smb_fname_cpath);
181 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
182 struct dfs_GetDFSReferral *r)
184 struct junction_map *junction = NULL;
186 bool self_referral = false;
187 char *pathnamep = NULL;
188 char *local_dfs_path = NULL;
191 uint16_t max_referral_level = r->in.req.max_referral_level;
194 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
197 /* get the junction entry */
198 if (r->in.req.servername == NULL) {
199 return NT_STATUS_NOT_FOUND;
203 * Trim pathname sent by client so it begins with only one backslash.
204 * Two backslashes confuse some dfs clients
207 local_dfs_path = talloc_strdup(r, r->in.req.servername);
208 if (local_dfs_path == NULL) {
209 return NT_STATUS_NO_MEMORY;
211 pathnamep = local_dfs_path;
212 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
213 IS_DIRECTORY_SEP(pathnamep[1])) {
217 junction = talloc_zero(r, struct junction_map);
218 if (junction == NULL) {
219 return NT_STATUS_NO_MEMORY;
222 /* The following call can change cwd. */
223 status = get_referred_path(r, pathnamep,
224 handle->conn->sconn->remote_address,
225 handle->conn->sconn->local_address,
226 !handle->conn->sconn->using_smb2,
227 junction, &consumedcnt, &self_referral);
228 if (!NT_STATUS_IS_OK(status)) {
229 vfs_ChDir(handle->conn, handle->conn->connectpath);
232 vfs_ChDir(handle->conn, handle->conn->connectpath);
234 if (!self_referral) {
235 pathnamep[consumedcnt] = '\0';
238 dbgtext("Path %s to alternate path(s):",
240 for (i=0; i < junction->referral_count; i++) {
242 junction->referral_list[i].alternate_path);
248 if (r->in.req.max_referral_level <= 2) {
249 max_referral_level = 2;
251 if (r->in.req.max_referral_level >= 3) {
252 max_referral_level = 3;
255 r->out.resp = talloc_zero(r, struct dfs_referral_resp);
256 if (r->out.resp == NULL) {
257 return NT_STATUS_NO_MEMORY;
260 r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
261 r->out.resp->nb_referrals = junction->referral_count;
263 r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
265 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
268 r->out.resp->referral_entries = talloc_zero_array(r,
269 struct dfs_referral_type,
270 r->out.resp->nb_referrals);
271 if (r->out.resp->referral_entries == NULL) {
272 return NT_STATUS_NO_MEMORY;
275 switch (max_referral_level) {
277 for(i=0; i < junction->referral_count; i++) {
278 struct referral *ref = &junction->referral_list[i];
279 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
280 struct dfs_referral_type *t =
281 &r->out.resp->referral_entries[i];
282 struct dfs_referral_v2 *v2 = &t->referral.v2;
285 v2->size = VERSION2_REFERRAL_SIZE;
287 v2->server_type = DFS_SERVER_ROOT;
289 v2->server_type = DFS_SERVER_NON_ROOT;
292 v2->proximity = ref->proximity;
294 v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
295 if (v2->DFS_path == NULL) {
296 return NT_STATUS_NO_MEMORY;
298 v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
299 if (v2->DFS_alt_path == NULL) {
300 return NT_STATUS_NO_MEMORY;
302 v2->netw_address = talloc_strdup(mem_ctx,
303 ref->alternate_path);
304 if (v2->netw_address == NULL) {
305 return NT_STATUS_NO_MEMORY;
311 for(i=0; i < junction->referral_count; i++) {
312 struct referral *ref = &junction->referral_list[i];
313 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
314 struct dfs_referral_type *t =
315 &r->out.resp->referral_entries[i];
316 struct dfs_referral_v3 *v3 = &t->referral.v3;
317 struct dfs_normal_referral *r1 = &v3->referrals.r1;
320 v3->size = VERSION3_REFERRAL_SIZE;
322 v3->server_type = DFS_SERVER_ROOT;
324 v3->server_type = DFS_SERVER_NON_ROOT;
328 r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
329 if (r1->DFS_path == NULL) {
330 return NT_STATUS_NO_MEMORY;
332 r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
333 if (r1->DFS_alt_path == NULL) {
334 return NT_STATUS_NO_MEMORY;
336 r1->netw_address = talloc_strdup(mem_ctx,
337 ref->alternate_path);
338 if (r1->netw_address == NULL) {
339 return NT_STATUS_NO_MEMORY;
344 DEBUG(0,("Invalid dfs referral version: %d\n",
345 max_referral_level));
346 return NT_STATUS_INVALID_LEVEL;
350 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
356 static NTSTATUS vfswrap_snap_check_path(struct vfs_handle_struct *handle,
358 const char *service_path,
361 return NT_STATUS_NOT_SUPPORTED;
364 static NTSTATUS vfswrap_snap_create(struct vfs_handle_struct *handle,
366 const char *base_volume,
372 return NT_STATUS_NOT_SUPPORTED;
375 static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle,
380 return NT_STATUS_NOT_SUPPORTED;
383 /* Directory operations */
385 static DIR *vfswrap_opendir(vfs_handle_struct *handle,
386 const struct smb_filename *smb_fname,
392 START_PROFILE(syscall_opendir);
393 result = opendir(smb_fname->base_name);
394 END_PROFILE(syscall_opendir);
398 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
405 START_PROFILE(syscall_fdopendir);
406 result = sys_fdopendir(fsp->fh->fd);
407 END_PROFILE(syscall_fdopendir);
412 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
414 SMB_STRUCT_STAT *sbuf)
416 struct dirent *result;
418 START_PROFILE(syscall_readdir);
419 result = readdir(dirp);
420 END_PROFILE(syscall_readdir);
422 /* Default Posix readdir() does not give us stat info.
423 * Set to invalid to indicate we didn't return this info. */
424 SET_STAT_INVALID(*sbuf);
425 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
426 if (result != NULL) {
427 /* See if we can efficiently return this. */
429 int flags = AT_SYMLINK_NOFOLLOW;
430 int ret = fstatat(dirfd(dirp),
435 * As this is an optimization,
436 * ignore it if we stat'ed a
437 * symlink. Make the caller
438 * do it again as we don't
439 * know if they wanted the link
440 * info, or its target info.
442 if ((ret == 0) && (!S_ISLNK(st.st_mode))) {
443 init_stat_ex_from_stat(sbuf,
445 lp_fake_directory_create_times(
446 SNUM(handle->conn)));
454 static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
455 const struct smb_filename *fname,
457 struct readdir_attr_data **attr_data)
459 return NT_STATUS_NOT_SUPPORTED;
462 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
464 START_PROFILE(syscall_seekdir);
465 seekdir(dirp, offset);
466 END_PROFILE(syscall_seekdir);
469 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
472 START_PROFILE(syscall_telldir);
473 result = telldir(dirp);
474 END_PROFILE(syscall_telldir);
478 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
480 START_PROFILE(syscall_rewinddir);
482 END_PROFILE(syscall_rewinddir);
485 static int vfswrap_mkdir(vfs_handle_struct *handle,
486 const struct smb_filename *smb_fname,
490 bool has_dacl = False;
491 const char *path = smb_fname->base_name;
494 START_PROFILE(syscall_mkdir);
496 if (lp_inherit_acls(SNUM(handle->conn))
497 && parent_dirname(talloc_tos(), path, &parent, NULL)
498 && (has_dacl = directory_has_default_acl(handle->conn, parent))) {
499 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
504 result = mkdir(path, mode);
506 if (result == 0 && !has_dacl) {
508 * We need to do this as the default behavior of POSIX ACLs
509 * is to set the mask to be the requested group permission
510 * bits, not the group permission bits to be the requested
511 * group permission bits. This is not what we want, as it will
512 * mess up any inherited ACL bits that were set. JRA.
514 int saved_errno = errno; /* We may get ENOSYS */
515 if ((SMB_VFS_CHMOD_ACL(handle->conn, smb_fname, mode) == -1) &&
521 END_PROFILE(syscall_mkdir);
525 static int vfswrap_rmdir(vfs_handle_struct *handle,
526 const struct smb_filename *smb_fname)
530 START_PROFILE(syscall_rmdir);
531 result = rmdir(smb_fname->base_name);
532 END_PROFILE(syscall_rmdir);
536 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
540 START_PROFILE(syscall_closedir);
541 result = closedir(dirp);
542 END_PROFILE(syscall_closedir);
546 static void vfswrap_init_search_op(vfs_handle_struct *handle,
549 /* Default behavior is a NOOP */
552 /* File operations */
554 static int vfswrap_open(vfs_handle_struct *handle,
555 struct smb_filename *smb_fname,
556 files_struct *fsp, int flags, mode_t mode)
560 START_PROFILE(syscall_open);
562 if (smb_fname->stream_name) {
567 result = open(smb_fname->base_name, flags, mode);
569 END_PROFILE(syscall_open);
573 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
574 struct smb_request *req,
575 uint16_t root_dir_fid,
576 struct smb_filename *smb_fname,
577 uint32_t access_mask,
578 uint32_t share_access,
579 uint32_t create_disposition,
580 uint32_t create_options,
581 uint32_t file_attributes,
582 uint32_t oplock_request,
583 struct smb2_lease *lease,
584 uint64_t allocation_size,
585 uint32_t private_flags,
586 struct security_descriptor *sd,
587 struct ea_list *ea_list,
588 files_struct **result,
590 const struct smb2_create_blobs *in_context_blobs,
591 struct smb2_create_blobs *out_context_blobs)
593 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
594 access_mask, share_access,
595 create_disposition, create_options,
596 file_attributes, oplock_request, lease,
597 allocation_size, private_flags,
599 pinfo, in_context_blobs, out_context_blobs);
602 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
606 START_PROFILE(syscall_close);
607 result = fd_close_posix(fsp);
608 END_PROFILE(syscall_close);
612 static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
616 START_PROFILE_BYTES(syscall_read, n);
617 result = sys_read(fsp->fh->fd, data, n);
618 END_PROFILE_BYTES(syscall_read);
622 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
623 size_t n, off_t offset)
627 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
628 START_PROFILE_BYTES(syscall_pread, n);
629 result = sys_pread(fsp->fh->fd, data, n, offset);
630 END_PROFILE_BYTES(syscall_pread);
632 if (result == -1 && errno == ESPIPE) {
633 /* Maintain the fiction that pipes can be seeked (sought?) on. */
634 result = SMB_VFS_READ(fsp, data, n);
638 #else /* HAVE_PREAD */
642 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
643 if (curr == -1 && errno == ESPIPE) {
644 /* Maintain the fiction that pipes can be seeked (sought?) on. */
645 result = SMB_VFS_READ(fsp, data, n);
650 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
655 result = SMB_VFS_READ(fsp, data, n);
658 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
661 #endif /* HAVE_PREAD */
666 static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
670 START_PROFILE_BYTES(syscall_write, n);
671 result = sys_write(fsp->fh->fd, data, n);
672 END_PROFILE_BYTES(syscall_write);
676 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
677 size_t n, off_t offset)
681 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
682 START_PROFILE_BYTES(syscall_pwrite, n);
683 result = sys_pwrite(fsp->fh->fd, data, n, offset);
684 END_PROFILE_BYTES(syscall_pwrite);
686 if (result == -1 && errno == ESPIPE) {
687 /* Maintain the fiction that pipes can be sought on. */
688 result = SMB_VFS_WRITE(fsp, data, n);
691 #else /* HAVE_PWRITE */
695 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
700 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
704 result = SMB_VFS_WRITE(fsp, data, n);
707 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
710 #endif /* HAVE_PWRITE */
715 static int vfswrap_init_pool(struct smbd_server_connection *conn)
719 if (conn->pool != NULL) {
723 ret = pthreadpool_tevent_init(conn, lp_aio_max_threads(),
728 struct vfswrap_pread_state {
736 struct vfs_aio_state vfs_aio_state;
737 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
740 static void vfs_pread_do(void *private_data);
741 static void vfs_pread_done(struct tevent_req *subreq);
743 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
745 struct tevent_context *ev,
746 struct files_struct *fsp,
748 size_t n, off_t offset)
750 struct tevent_req *req, *subreq;
751 struct vfswrap_pread_state *state;
754 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
759 ret = vfswrap_init_pool(handle->conn->sconn);
760 if (tevent_req_error(req, ret)) {
761 return tevent_req_post(req, ev);
765 state->fd = fsp->fh->fd;
768 state->offset = offset;
770 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
771 state->profile_bytes, n);
772 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
774 subreq = pthreadpool_tevent_job_send(
775 state, ev, handle->conn->sconn->pool,
776 vfs_pread_do, state);
777 if (tevent_req_nomem(subreq, req)) {
778 return tevent_req_post(req, ev);
780 tevent_req_set_callback(subreq, vfs_pread_done, req);
785 static void vfs_pread_do(void *private_data)
787 struct vfswrap_pread_state *state = talloc_get_type_abort(
788 private_data, struct vfswrap_pread_state);
789 struct timespec start_time;
790 struct timespec end_time;
792 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
794 PROFILE_TIMESTAMP(&start_time);
797 state->ret = pread(state->fd, state->buf, state->count,
799 } while ((state->ret == -1) && (errno == EINTR));
803 PROFILE_TIMESTAMP(&end_time);
805 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
807 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
810 static void vfs_pread_done(struct tevent_req *subreq)
812 struct tevent_req *req = tevent_req_callback_data(
813 subreq, struct tevent_req);
815 struct vfswrap_pread_state *state = tevent_req_data(
816 req, struct vfswrap_pread_state);
820 ret = pthreadpool_tevent_job_recv(subreq);
822 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
823 if (tevent_req_error(req, ret)) {
827 tevent_req_done(req);
830 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
831 struct vfs_aio_state *vfs_aio_state)
833 struct vfswrap_pread_state *state = tevent_req_data(
834 req, struct vfswrap_pread_state);
836 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
840 *vfs_aio_state = state->vfs_aio_state;
844 struct vfswrap_pwrite_state {
852 struct vfs_aio_state vfs_aio_state;
853 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
856 static void vfs_pwrite_do(void *private_data);
857 static void vfs_pwrite_done(struct tevent_req *subreq);
859 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
861 struct tevent_context *ev,
862 struct files_struct *fsp,
864 size_t n, off_t offset)
866 struct tevent_req *req, *subreq;
867 struct vfswrap_pwrite_state *state;
870 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
875 ret = vfswrap_init_pool(handle->conn->sconn);
876 if (tevent_req_error(req, ret)) {
877 return tevent_req_post(req, ev);
881 state->fd = fsp->fh->fd;
884 state->offset = offset;
886 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
887 state->profile_bytes, n);
888 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
890 subreq = pthreadpool_tevent_job_send(
891 state, ev, handle->conn->sconn->pool,
892 vfs_pwrite_do, state);
893 if (tevent_req_nomem(subreq, req)) {
894 return tevent_req_post(req, ev);
896 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
901 static void vfs_pwrite_do(void *private_data)
903 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
904 private_data, struct vfswrap_pwrite_state);
905 struct timespec start_time;
906 struct timespec end_time;
908 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
910 PROFILE_TIMESTAMP(&start_time);
913 state->ret = pwrite(state->fd, state->buf, state->count,
915 } while ((state->ret == -1) && (errno == EINTR));
919 PROFILE_TIMESTAMP(&end_time);
921 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
923 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
926 static void vfs_pwrite_done(struct tevent_req *subreq)
928 struct tevent_req *req = tevent_req_callback_data(
929 subreq, struct tevent_req);
931 struct vfswrap_pwrite_state *state = tevent_req_data(
932 req, struct vfswrap_pwrite_state);
936 ret = pthreadpool_tevent_job_recv(subreq);
938 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
939 if (tevent_req_error(req, ret)) {
943 tevent_req_done(req);
946 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
947 struct vfs_aio_state *vfs_aio_state)
949 struct vfswrap_pwrite_state *state = tevent_req_data(
950 req, struct vfswrap_pwrite_state);
952 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
956 *vfs_aio_state = state->vfs_aio_state;
960 struct vfswrap_fsync_state {
965 struct vfs_aio_state vfs_aio_state;
966 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
969 static void vfs_fsync_do(void *private_data);
970 static void vfs_fsync_done(struct tevent_req *subreq);
972 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
974 struct tevent_context *ev,
975 struct files_struct *fsp)
977 struct tevent_req *req, *subreq;
978 struct vfswrap_fsync_state *state;
981 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
986 ret = vfswrap_init_pool(handle->conn->sconn);
987 if (tevent_req_error(req, ret)) {
988 return tevent_req_post(req, ev);
992 state->fd = fsp->fh->fd;
994 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
995 state->profile_basic);
997 subreq = pthreadpool_tevent_job_send(
998 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
999 if (tevent_req_nomem(subreq, req)) {
1000 return tevent_req_post(req, ev);
1002 tevent_req_set_callback(subreq, vfs_fsync_done, req);
1007 static void vfs_fsync_do(void *private_data)
1009 struct vfswrap_fsync_state *state = talloc_get_type_abort(
1010 private_data, struct vfswrap_fsync_state);
1011 struct timespec start_time;
1012 struct timespec end_time;
1014 PROFILE_TIMESTAMP(&start_time);
1017 state->ret = fsync(state->fd);
1018 } while ((state->ret == -1) && (errno == EINTR));
1022 PROFILE_TIMESTAMP(&end_time);
1024 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1027 static void vfs_fsync_done(struct tevent_req *subreq)
1029 struct tevent_req *req = tevent_req_callback_data(
1030 subreq, struct tevent_req);
1032 struct vfswrap_fsync_state *state = tevent_req_data(
1033 req, struct vfswrap_fsync_state);
1037 ret = pthreadpool_tevent_job_recv(subreq);
1038 TALLOC_FREE(subreq);
1039 SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
1040 if (tevent_req_error(req, ret)) {
1044 tevent_req_done(req);
1047 static int vfswrap_fsync_recv(struct tevent_req *req,
1048 struct vfs_aio_state *vfs_aio_state)
1050 struct vfswrap_fsync_state *state = tevent_req_data(
1051 req, struct vfswrap_fsync_state);
1053 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1057 *vfs_aio_state = state->vfs_aio_state;
1061 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1065 START_PROFILE(syscall_lseek);
1067 /* Cope with 'stat' file opens. */
1068 if (fsp->fh->fd != -1)
1069 result = lseek(fsp->fh->fd, offset, whence);
1072 * We want to maintain the fiction that we can seek
1073 * on a fifo for file system purposes. This allows
1074 * people to set up UNIX fifo's that feed data to Windows
1075 * applications. JRA.
1078 if((result == -1) && (errno == ESPIPE)) {
1083 END_PROFILE(syscall_lseek);
1087 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1088 off_t offset, size_t n)
1092 START_PROFILE_BYTES(syscall_sendfile, n);
1093 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
1094 END_PROFILE_BYTES(syscall_sendfile);
1098 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1100 files_struct *tofsp,
1106 START_PROFILE_BYTES(syscall_recvfile, n);
1107 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
1108 END_PROFILE_BYTES(syscall_recvfile);
1112 static int vfswrap_rename(vfs_handle_struct *handle,
1113 const struct smb_filename *smb_fname_src,
1114 const struct smb_filename *smb_fname_dst)
1118 START_PROFILE(syscall_rename);
1120 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
1125 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
1128 END_PROFILE(syscall_rename);
1132 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
1137 START_PROFILE(syscall_fsync);
1138 result = fsync(fsp->fh->fd);
1139 END_PROFILE(syscall_fsync);
1146 static int vfswrap_stat(vfs_handle_struct *handle,
1147 struct smb_filename *smb_fname)
1151 START_PROFILE(syscall_stat);
1153 if (smb_fname->stream_name) {
1158 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1159 lp_fake_directory_create_times(SNUM(handle->conn)));
1161 END_PROFILE(syscall_stat);
1165 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1169 START_PROFILE(syscall_fstat);
1170 result = sys_fstat(fsp->fh->fd,
1171 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1172 END_PROFILE(syscall_fstat);
1176 static int vfswrap_lstat(vfs_handle_struct *handle,
1177 struct smb_filename *smb_fname)
1181 START_PROFILE(syscall_lstat);
1183 if (smb_fname->stream_name) {
1188 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1189 lp_fake_directory_create_times(SNUM(handle->conn)));
1191 END_PROFILE(syscall_lstat);
1195 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1197 enum vfs_translate_direction direction,
1198 TALLOC_CTX *mem_ctx,
1201 return NT_STATUS_NONE_MAPPED;
1205 * Implement the default fsctl operation.
1207 static bool vfswrap_logged_ioctl_message = false;
1209 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1210 struct files_struct *fsp,
1213 uint16_t req_flags, /* Needed for UNICODE ... */
1214 const uint8_t *_in_data,
1216 uint8_t **_out_data,
1217 uint32_t max_out_len,
1220 const char *in_data = (const char *)_in_data;
1221 char **out_data = (char **)_out_data;
1225 case FSCTL_SET_SPARSE:
1227 bool set_sparse = true;
1229 if (in_len >= 1 && in_data[0] == 0) {
1233 status = file_set_sparse(handle->conn, fsp, set_sparse);
1235 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1236 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1237 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1238 nt_errstr(status)));
1243 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1245 unsigned char objid[16];
1246 char *return_data = NULL;
1248 /* This should return the object-id on this file.
1249 * I think I'll make this be the inode+dev. JRA.
1252 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1253 fsp_fnum_dbg(fsp)));
1255 *out_len = MIN(max_out_len, 64);
1257 /* Hmmm, will this cause problems if less data asked for? */
1258 return_data = talloc_array(ctx, char, 64);
1259 if (return_data == NULL) {
1260 return NT_STATUS_NO_MEMORY;
1263 /* For backwards compatibility only store the dev/inode. */
1264 push_file_id_16(return_data, &fsp->file_id);
1265 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1266 push_file_id_16(return_data+32, &fsp->file_id);
1267 memset(return_data+48, 0, 16);
1268 *out_data = return_data;
1269 return NT_STATUS_OK;
1272 case FSCTL_GET_REPARSE_POINT:
1274 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1275 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1276 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1277 return NT_STATUS_NOT_A_REPARSE_POINT;
1280 case FSCTL_SET_REPARSE_POINT:
1282 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1283 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1284 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1285 return NT_STATUS_NOT_A_REPARSE_POINT;
1288 case FSCTL_GET_SHADOW_COPY_DATA:
1291 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1292 * and return their volume names. If max_data_count is 16, then it is just
1293 * asking for the number of volumes and length of the combined names.
1295 * pdata is the data allocated by our caller, but that uses
1296 * total_data_count (which is 0 in our case) rather than max_data_count.
1297 * Allocate the correct amount and return the pointer to let
1298 * it be deallocated when we return.
1300 struct shadow_copy_data *shadow_data = NULL;
1301 bool labels = False;
1302 uint32_t labels_data_count = 0;
1304 char *cur_pdata = NULL;
1306 if (max_out_len < 16) {
1307 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1309 return NT_STATUS_INVALID_PARAMETER;
1312 if (max_out_len > 16) {
1316 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1317 if (shadow_data == NULL) {
1318 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1319 return NT_STATUS_NO_MEMORY;
1323 * Call the VFS routine to actually do the work.
1325 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1328 /* broken module didn't set errno on error */
1329 status = NT_STATUS_UNSUCCESSFUL;
1331 status = map_nt_error_from_unix(errno);
1332 if (NT_STATUS_EQUAL(status,
1333 NT_STATUS_NOT_SUPPORTED)) {
1337 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1338 "connectpath %s, failed - %s.\n",
1339 fsp->conn->connectpath,
1340 nt_errstr(status)));
1341 TALLOC_FREE(shadow_data);
1345 labels_data_count = (shadow_data->num_volumes * 2 *
1346 sizeof(SHADOW_COPY_LABEL)) + 2;
1351 *out_len = 12 + labels_data_count;
1354 if (max_out_len < *out_len) {
1355 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1356 max_out_len, *out_len));
1357 TALLOC_FREE(shadow_data);
1358 return NT_STATUS_BUFFER_TOO_SMALL;
1361 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1362 if (cur_pdata == NULL) {
1363 TALLOC_FREE(shadow_data);
1364 return NT_STATUS_NO_MEMORY;
1367 *out_data = cur_pdata;
1369 /* num_volumes 4 bytes */
1370 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1373 /* num_labels 4 bytes */
1374 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1377 /* needed_data_count 4 bytes */
1378 SIVAL(cur_pdata, 8, labels_data_count);
1382 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1383 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1384 if (labels && shadow_data->labels) {
1385 for (i=0; i<shadow_data->num_volumes; i++) {
1387 status = srvstr_push(cur_pdata, req_flags,
1388 cur_pdata, shadow_data->labels[i],
1389 2 * sizeof(SHADOW_COPY_LABEL),
1390 STR_UNICODE|STR_TERMINATE, &len);
1391 if (!NT_STATUS_IS_OK(status)) {
1392 TALLOC_FREE(*out_data);
1393 TALLOC_FREE(shadow_data);
1396 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1397 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1401 TALLOC_FREE(shadow_data);
1403 return NT_STATUS_OK;
1406 case FSCTL_FIND_FILES_BY_SID:
1408 /* pretend this succeeded -
1410 * we have to send back a list with all files owned by this SID
1412 * but I have to check that --metze
1418 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1419 fsp_fnum_dbg(fsp)));
1422 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1423 return NT_STATUS_INVALID_PARAMETER;
1426 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1428 /* unknown 4 bytes: this is not the length of the sid :-( */
1429 /*unknown = IVAL(pdata,0);*/
1431 if (!sid_parse(_in_data + 4, sid_len, &sid)) {
1432 return NT_STATUS_INVALID_PARAMETER;
1434 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1436 if (!sid_to_uid(&sid, &uid)) {
1437 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1438 sid_string_dbg(&sid),
1439 (unsigned long)sid_len));
1443 /* we can take a look at the find source :-)
1445 * find ./ -uid $uid -name '*' is what we need here
1448 * and send 4bytes len and then NULL terminated unicode strings
1451 * but I don't know how to deal with the paged results
1452 * (maybe we can hang the result anywhere in the fsp struct)
1454 * but I don't know how to deal with the paged results
1455 * (maybe we can hang the result anywhere in the fsp struct)
1457 * we don't send all files at once
1458 * and at the next we should *not* start from the beginning,
1459 * so we have to cache the result
1464 /* this works for now... */
1465 return NT_STATUS_OK;
1468 case FSCTL_QUERY_ALLOCATED_RANGES:
1470 /* FIXME: This is just a dummy reply, telling that all of the
1471 * file is allocated. MKS cp needs that.
1472 * Adding the real allocated ranges via FIEMAP on Linux
1473 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1474 * this FSCTL correct for sparse files.
1476 uint64_t offset, length;
1477 char *out_data_tmp = NULL;
1480 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1482 return NT_STATUS_INVALID_PARAMETER;
1485 if (max_out_len < 16) {
1486 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1488 return NT_STATUS_INVALID_PARAMETER;
1491 offset = BVAL(in_data,0);
1492 length = BVAL(in_data,8);
1494 if (offset + length < offset) {
1495 /* No 64-bit integer wrap. */
1496 return NT_STATUS_INVALID_PARAMETER;
1499 /* Shouldn't this be SMB_VFS_STAT ... ? */
1500 status = vfs_stat_fsp(fsp);
1501 if (!NT_STATUS_IS_OK(status)) {
1506 out_data_tmp = talloc_array(ctx, char, *out_len);
1507 if (out_data_tmp == NULL) {
1508 DEBUG(10, ("unable to allocate memory for response\n"));
1509 return NT_STATUS_NO_MEMORY;
1512 if (offset > fsp->fsp_name->st.st_ex_size ||
1513 fsp->fsp_name->st.st_ex_size == 0 ||
1515 memset(out_data_tmp, 0, *out_len);
1517 uint64_t end = offset + length;
1518 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1519 SBVAL(out_data_tmp, 0, 0);
1520 SBVAL(out_data_tmp, 8, end);
1523 *out_data = out_data_tmp;
1525 return NT_STATUS_OK;
1528 case FSCTL_IS_VOLUME_DIRTY:
1530 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1531 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1533 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1534 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1536 return NT_STATUS_INVALID_PARAMETER;
1541 * Only print once ... unfortunately there could be lots of
1542 * different FSCTLs that are called.
1544 if (!vfswrap_logged_ioctl_message) {
1545 vfswrap_logged_ioctl_message = true;
1546 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1547 __func__, function));
1551 return NT_STATUS_NOT_SUPPORTED;
1554 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
1555 const struct smb_filename *fname,
1556 SMB_STRUCT_STAT *sbuf);
1558 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1559 struct smb_filename *smb_fname,
1564 offline = vfswrap_is_offline(handle, smb_fname, &smb_fname->st);
1566 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1569 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1572 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1573 struct files_struct *fsp,
1578 offline = vfswrap_is_offline(handle, fsp->fsp_name, &fsp->fsp_name->st);
1580 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1583 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1586 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1587 const struct smb_filename *smb_fname,
1590 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1593 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1594 struct files_struct *fsp,
1597 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1600 struct vfs_cc_state {
1601 struct tevent_context *ev;
1603 bool read_lck_locked;
1604 struct lock_struct read_lck;
1605 bool write_lck_locked;
1606 struct lock_struct write_lck;
1607 struct files_struct *src_fsp;
1609 struct files_struct *dst_fsp;
1613 size_t next_io_size;
1617 static NTSTATUS copy_chunk_loop(struct tevent_req *req);
1619 static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *handle,
1620 TALLOC_CTX *mem_ctx,
1621 struct tevent_context *ev,
1622 struct files_struct *src_fsp,
1624 struct files_struct *dest_fsp,
1629 struct tevent_req *req;
1630 struct vfs_cc_state *state = NULL;
1631 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
1634 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
1636 req = tevent_req_create(mem_ctx, &state, struct vfs_cc_state);
1641 if (flags & ~VFS_COPY_CHUNK_FL_MASK_ALL) {
1642 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1643 return tevent_req_post(req, ev);
1646 if (flags & VFS_COPY_CHUNK_FL_MUST_CLONE) {
1647 DEBUG(10, ("COW clones not supported by vfs_default\n"));
1648 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1649 return tevent_req_post(req, ev);
1652 *state = (struct vfs_cc_state) {
1656 .dst_fsp = dest_fsp,
1657 .dst_off = dest_off,
1659 .remaining = to_copy,
1662 state->buf = talloc_array(state, uint8_t, num);
1663 if (tevent_req_nomem(state->buf, req)) {
1664 return tevent_req_post(req, ev);
1667 status = vfs_stat_fsp(src_fsp);
1668 if (tevent_req_nterror(req, status)) {
1669 return tevent_req_post(req, ev);
1672 if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
1674 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1675 * If the SourceOffset or SourceOffset + Length extends beyond
1676 * the end of file, the server SHOULD<240> treat this as a
1677 * STATUS_END_OF_FILE error.
1679 * <240> Section 3.3.5.15.6: Windows servers will return
1680 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1682 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1683 return tevent_req_post(req, ev);
1686 if (src_fsp->op == NULL) {
1687 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1688 return tevent_req_post(req, ev);
1691 if (dest_fsp->op == NULL) {
1692 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1693 return tevent_req_post(req, ev);
1696 status = copy_chunk_loop(req);
1697 if (!NT_STATUS_IS_OK(status)) {
1698 tevent_req_nterror(req, status);
1699 return tevent_req_post(req, ev);
1705 static void vfswrap_copy_chunk_read_done(struct tevent_req *subreq);
1707 static NTSTATUS copy_chunk_loop(struct tevent_req *req)
1709 struct vfs_cc_state *state = tevent_req_data(req, struct vfs_cc_state);
1710 struct tevent_req *subreq = NULL;
1713 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
1715 if (!(state->flags & VFS_COPY_CHUNK_FL_IGNORE_LOCKS)) {
1716 init_strict_lock_struct(state->src_fsp,
1717 state->src_fsp->op->global->open_persistent_id,
1719 state->next_io_size,
1723 ok = SMB_VFS_STRICT_LOCK(state->src_fsp->conn,
1727 return NT_STATUS_FILE_LOCK_CONFLICT;
1731 subreq = SMB_VFS_PREAD_SEND(state,
1732 state->src_fsp->conn->sconn->ev_ctx,
1735 state->next_io_size,
1737 if (subreq == NULL) {
1738 return NT_STATUS_NO_MEMORY;
1740 tevent_req_set_callback(subreq, vfswrap_copy_chunk_read_done, req);
1742 return NT_STATUS_OK;
1745 static void vfswrap_copy_chunk_write_done(struct tevent_req *subreq);
1747 static void vfswrap_copy_chunk_read_done(struct tevent_req *subreq)
1749 struct tevent_req *req = tevent_req_callback_data(
1750 subreq, struct tevent_req);
1751 struct vfs_cc_state *state = tevent_req_data(req, struct vfs_cc_state);
1752 struct vfs_aio_state aio_state;
1756 if (!(state->flags & VFS_COPY_CHUNK_FL_IGNORE_LOCKS)) {
1757 SMB_VFS_STRICT_UNLOCK(state->src_fsp->conn,
1760 ZERO_STRUCT(state->read_lck);
1763 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
1764 TALLOC_FREE(subreq);
1766 DBG_ERR("read failed: %s\n", strerror(errno));
1767 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1770 if (nread != state->next_io_size) {
1771 DBG_ERR("Short read, only %zd of %zu\n",
1772 nread, state->next_io_size);
1773 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1777 state->src_off += nread;
1779 if (!(state->flags & VFS_COPY_CHUNK_FL_IGNORE_LOCKS)) {
1780 init_strict_lock_struct(state->dst_fsp,
1781 state->dst_fsp->op->global->open_persistent_id,
1783 state->next_io_size,
1787 ok = SMB_VFS_STRICT_LOCK(state->dst_fsp->conn,
1791 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1796 subreq = SMB_VFS_PWRITE_SEND(state,
1800 state->next_io_size,
1802 if (subreq == NULL) {
1803 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1806 tevent_req_set_callback(subreq, vfswrap_copy_chunk_write_done, req);
1809 static void vfswrap_copy_chunk_write_done(struct tevent_req *subreq)
1811 struct tevent_req *req = tevent_req_callback_data(
1812 subreq, struct tevent_req);
1813 struct vfs_cc_state *state = tevent_req_data(req, struct vfs_cc_state);
1814 struct vfs_aio_state aio_state;
1818 if (!(state->flags & VFS_COPY_CHUNK_FL_IGNORE_LOCKS)) {
1819 SMB_VFS_STRICT_UNLOCK(state->dst_fsp->conn,
1822 ZERO_STRUCT(state->write_lck);
1825 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
1826 TALLOC_FREE(subreq);
1827 if (nwritten == -1) {
1828 DBG_ERR("write failed: %s\n", strerror(errno));
1829 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1832 if (nwritten != state->next_io_size) {
1833 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
1834 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1838 state->dst_off += nwritten;
1840 if (state->remaining < nwritten) {
1841 /* Paranoia check */
1842 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1845 state->remaining -= nwritten;
1846 if (state->remaining == 0) {
1847 tevent_req_done(req);
1851 status = copy_chunk_loop(req);
1852 if (!NT_STATUS_IS_OK(status)) {
1853 tevent_req_nterror(req, status);
1860 static NTSTATUS vfswrap_copy_chunk_recv(struct vfs_handle_struct *handle,
1861 struct tevent_req *req,
1864 struct vfs_cc_state *state = tevent_req_data(req, struct vfs_cc_state);
1867 if (tevent_req_is_nterror(req, &status)) {
1868 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
1870 tevent_req_received(req);
1874 *copied = state->to_copy;
1875 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
1876 tevent_req_received(req);
1878 return NT_STATUS_OK;
1881 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1882 TALLOC_CTX *mem_ctx,
1883 struct files_struct *fsp,
1884 struct smb_filename *smb_fname,
1885 uint16_t *_compression_fmt)
1887 return NT_STATUS_INVALID_DEVICE_REQUEST;
1890 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1891 TALLOC_CTX *mem_ctx,
1892 struct files_struct *fsp,
1893 uint16_t compression_fmt)
1895 return NT_STATUS_INVALID_DEVICE_REQUEST;
1898 /********************************************************************
1899 Given a stat buffer return the allocated size on disk, taking into
1900 account sparse files.
1901 ********************************************************************/
1902 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1903 struct files_struct *fsp,
1904 const SMB_STRUCT_STAT *sbuf)
1908 START_PROFILE(syscall_get_alloc_size);
1910 if(S_ISDIR(sbuf->st_ex_mode)) {
1915 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1916 /* The type of st_blocksize is blkcnt_t which *MUST* be
1917 signed (according to POSIX) and can be less than 64-bits.
1918 Ensure when we're converting to 64 bits wide we don't
1920 #if defined(SIZEOF_BLKCNT_T_8)
1921 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1922 #elif defined(SIZEOF_BLKCNT_T_4)
1924 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1925 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1928 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1932 * Some file systems do not allocate a block for very
1933 * small files. But for non-empty file should report a
1937 uint64_t filesize = get_file_size_stat(sbuf);
1939 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
1943 result = get_file_size_stat(sbuf);
1946 if (fsp && fsp->initial_allocation_size)
1947 result = MAX(result,fsp->initial_allocation_size);
1949 result = smb_roundup(handle->conn, result);
1952 END_PROFILE(syscall_get_alloc_size);
1956 static int vfswrap_unlink(vfs_handle_struct *handle,
1957 const struct smb_filename *smb_fname)
1961 START_PROFILE(syscall_unlink);
1963 if (smb_fname->stream_name) {
1967 result = unlink(smb_fname->base_name);
1970 END_PROFILE(syscall_unlink);
1974 static int vfswrap_chmod(vfs_handle_struct *handle,
1975 const struct smb_filename *smb_fname,
1980 START_PROFILE(syscall_chmod);
1983 * We need to do this due to the fact that the default POSIX ACL
1984 * chmod modifies the ACL *mask* for the group owner, not the
1985 * group owner bits directly. JRA.
1990 int saved_errno = errno; /* We might get ENOSYS */
1991 result = SMB_VFS_CHMOD_ACL(handle->conn,
1995 END_PROFILE(syscall_chmod);
1998 /* Error - return the old errno. */
1999 errno = saved_errno;
2002 result = chmod(smb_fname->base_name, mode);
2003 END_PROFILE(syscall_chmod);
2007 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2011 START_PROFILE(syscall_fchmod);
2014 * We need to do this due to the fact that the default POSIX ACL
2015 * chmod modifies the ACL *mask* for the group owner, not the
2016 * group owner bits directly. JRA.
2020 int saved_errno = errno; /* We might get ENOSYS */
2021 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
2022 END_PROFILE(syscall_fchmod);
2025 /* Error - return the old errno. */
2026 errno = saved_errno;
2029 #if defined(HAVE_FCHMOD)
2030 result = fchmod(fsp->fh->fd, mode);
2036 END_PROFILE(syscall_fchmod);
2040 static int vfswrap_chown(vfs_handle_struct *handle,
2041 const struct smb_filename *smb_fname,
2047 START_PROFILE(syscall_chown);
2048 result = chown(smb_fname->base_name, uid, gid);
2049 END_PROFILE(syscall_chown);
2053 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2058 START_PROFILE(syscall_fchown);
2059 result = fchown(fsp->fh->fd, uid, gid);
2060 END_PROFILE(syscall_fchown);
2068 static int vfswrap_lchown(vfs_handle_struct *handle,
2069 const struct smb_filename *smb_fname,
2075 START_PROFILE(syscall_lchown);
2076 result = lchown(smb_fname->base_name, uid, gid);
2077 END_PROFILE(syscall_lchown);
2081 static int vfswrap_chdir(vfs_handle_struct *handle, const char *path)
2085 START_PROFILE(syscall_chdir);
2086 result = chdir(path);
2087 END_PROFILE(syscall_chdir);
2091 static char *vfswrap_getwd(vfs_handle_struct *handle)
2095 START_PROFILE(syscall_getwd);
2096 result = sys_getwd();
2097 END_PROFILE(syscall_getwd);
2101 /*********************************************************************
2102 nsec timestamp resolution call. Convert down to whatever the underlying
2103 system will support.
2104 **********************************************************************/
2106 static int vfswrap_ntimes(vfs_handle_struct *handle,
2107 const struct smb_filename *smb_fname,
2108 struct smb_file_time *ft)
2112 START_PROFILE(syscall_ntimes);
2114 if (smb_fname->stream_name) {
2120 if (null_timespec(ft->atime)) {
2121 ft->atime= smb_fname->st.st_ex_atime;
2124 if (null_timespec(ft->mtime)) {
2125 ft->mtime = smb_fname->st.st_ex_mtime;
2128 if (!null_timespec(ft->create_time)) {
2129 set_create_timespec_ea(handle->conn,
2134 if ((timespec_compare(&ft->atime,
2135 &smb_fname->st.st_ex_atime) == 0) &&
2136 (timespec_compare(&ft->mtime,
2137 &smb_fname->st.st_ex_mtime) == 0)) {
2142 #if defined(HAVE_UTIMENSAT)
2144 struct timespec ts[2];
2147 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2149 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2151 if (!((result == -1) && (errno == ENOSYS))) {
2155 #if defined(HAVE_UTIMES)
2157 struct timeval tv[2];
2158 tv[0] = convert_timespec_to_timeval(ft->atime);
2159 tv[1] = convert_timespec_to_timeval(ft->mtime);
2160 result = utimes(smb_fname->base_name, tv);
2162 result = utimes(smb_fname->base_name, NULL);
2164 if (!((result == -1) && (errno == ENOSYS))) {
2168 #if defined(HAVE_UTIME)
2170 struct utimbuf times;
2171 times.actime = convert_timespec_to_time_t(ft->atime);
2172 times.modtime = convert_timespec_to_time_t(ft->mtime);
2173 result = utime(smb_fname->base_name, ×);
2175 result = utime(smb_fname->base_name, NULL);
2177 if (!((result == -1) && (errno == ENOSYS))) {
2185 END_PROFILE(syscall_ntimes);
2189 /*********************************************************************
2190 A version of ftruncate that will write the space on disk if strict
2192 **********************************************************************/
2194 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2196 off_t space_to_write;
2197 uint64_t space_avail;
2198 uint64_t bsize,dfree,dsize;
2201 SMB_STRUCT_STAT *pst;
2203 status = vfs_stat_fsp(fsp);
2204 if (!NT_STATUS_IS_OK(status)) {
2207 pst = &fsp->fsp_name->st;
2210 if (S_ISFIFO(pst->st_ex_mode))
2214 if (pst->st_ex_size == len)
2217 /* Shrink - just ftruncate. */
2218 if (pst->st_ex_size > len)
2219 return ftruncate(fsp->fh->fd, len);
2221 space_to_write = len - pst->st_ex_size;
2223 /* for allocation try fallocate first. This can fail on some
2224 platforms e.g. when the filesystem doesn't support it and no
2225 emulation is being done by the libc (like on AIX with JFS1). In that
2226 case we do our own emulation. fallocate implementations can
2227 return ENOTSUP or EINVAL in cases like that. */
2228 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2229 if (ret == -1 && errno == ENOSPC) {
2235 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2236 "error %d. Falling back to slow manual allocation\n", errno));
2238 /* available disk space is enough or not? */
2240 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2241 /* space_avail is 1k blocks */
2242 if (space_avail == (uint64_t)-1 ||
2243 ((uint64_t)space_to_write/1024 > space_avail) ) {
2248 /* Write out the real space on disk. */
2249 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2257 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2260 SMB_STRUCT_STAT *pst;
2264 START_PROFILE(syscall_ftruncate);
2266 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2267 result = strict_allocate_ftruncate(handle, fsp, len);
2268 END_PROFILE(syscall_ftruncate);
2272 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2273 ftruncate if the system supports it. Then I discovered that
2274 you can have some filesystems that support ftruncate
2275 expansion and some that don't! On Linux fat can't do
2276 ftruncate extend but ext2 can. */
2278 result = ftruncate(fsp->fh->fd, len);
2280 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2281 extend a file with ftruncate. Provide alternate implementation
2284 /* Do an fstat to see if the file is longer than the requested
2285 size in which case the ftruncate above should have
2286 succeeded or shorter, in which case seek to len - 1 and
2287 write 1 byte of zero */
2288 status = vfs_stat_fsp(fsp);
2289 if (!NT_STATUS_IS_OK(status)) {
2293 /* We need to update the files_struct after successful ftruncate */
2298 pst = &fsp->fsp_name->st;
2301 if (S_ISFIFO(pst->st_ex_mode)) {
2307 if (pst->st_ex_size == len) {
2312 if (pst->st_ex_size > len) {
2313 /* the ftruncate should have worked */
2317 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2325 END_PROFILE(syscall_ftruncate);
2329 static int vfswrap_fallocate(vfs_handle_struct *handle,
2337 START_PROFILE(syscall_fallocate);
2339 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2341 * posix_fallocate returns 0 on success, errno on error
2342 * and doesn't set errno. Make it behave like fallocate()
2343 * which returns -1, and sets errno on failure.
2350 /* sys_fallocate handles filtering of unsupported mode flags */
2351 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2353 END_PROFILE(syscall_fallocate);
2357 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2361 START_PROFILE(syscall_fcntl_lock);
2363 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2365 "force process locks",
2367 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2370 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2371 END_PROFILE(syscall_fcntl_lock);
2375 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2376 uint32_t share_mode, uint32_t access_mask)
2378 START_PROFILE(syscall_kernel_flock);
2379 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2380 END_PROFILE(syscall_kernel_flock);
2384 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2389 START_PROFILE(syscall_fcntl_getlock);
2391 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2393 "force process locks",
2395 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2398 result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2399 END_PROFILE(syscall_fcntl_getlock);
2403 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2408 START_PROFILE(syscall_linux_setlease);
2410 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2411 result = linux_setlease(fsp->fh->fd, leasetype);
2415 END_PROFILE(syscall_linux_setlease);
2419 static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2423 START_PROFILE(syscall_symlink);
2424 result = symlink(oldpath, newpath);
2425 END_PROFILE(syscall_symlink);
2429 static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
2433 START_PROFILE(syscall_readlink);
2434 result = readlink(path, buf, bufsiz);
2435 END_PROFILE(syscall_readlink);
2439 static int vfswrap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2443 START_PROFILE(syscall_link);
2444 result = link(oldpath, newpath);
2445 END_PROFILE(syscall_link);
2449 static int vfswrap_mknod(vfs_handle_struct *handle,
2450 const struct smb_filename *smb_fname,
2456 START_PROFILE(syscall_mknod);
2457 result = sys_mknod(smb_fname->base_name, mode, dev);
2458 END_PROFILE(syscall_mknod);
2462 static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
2466 START_PROFILE(syscall_realpath);
2467 result = sys_realpath(path);
2468 END_PROFILE(syscall_realpath);
2472 static int vfswrap_chflags(vfs_handle_struct *handle,
2473 const struct smb_filename *smb_fname,
2477 return chflags(smb_fname->base_name, flags);
2484 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2485 const SMB_STRUCT_STAT *sbuf)
2489 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2493 key.devid = sbuf->st_ex_dev;
2494 key.inode = sbuf->st_ex_ino;
2495 /* key.extid is unused by default. */
2500 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2501 struct files_struct *fsp,
2502 const struct smb_filename *smb_fname,
2503 TALLOC_CTX *mem_ctx,
2504 unsigned int *pnum_streams,
2505 struct stream_struct **pstreams)
2507 SMB_STRUCT_STAT sbuf;
2508 struct stream_struct *tmp_streams = NULL;
2511 if ((fsp != NULL) && (fsp->is_directory)) {
2513 * No default streams on directories
2518 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2519 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2522 struct smb_filename smb_fname_cp;
2524 ZERO_STRUCT(smb_fname_cp);
2525 smb_fname_cp.base_name = discard_const_p(char,
2526 smb_fname->base_name);
2527 smb_fname_cp.flags = smb_fname->flags;
2529 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
2530 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2532 ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2534 sbuf = smb_fname_cp.st;
2538 return map_nt_error_from_unix(errno);
2541 if (S_ISDIR(sbuf.st_ex_mode)) {
2545 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2546 (*pnum_streams) + 1);
2547 if (tmp_streams == NULL) {
2548 return NT_STATUS_NO_MEMORY;
2550 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2551 if (tmp_streams[*pnum_streams].name == NULL) {
2552 return NT_STATUS_NO_MEMORY;
2554 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2555 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2558 *pstreams = tmp_streams;
2560 return NT_STATUS_OK;
2563 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2566 TALLOC_CTX *mem_ctx,
2570 * Don't fall back to get_real_filename so callers can differentiate
2571 * between a full directory scan and an actual case-insensitive stat.
2577 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2580 return handle->conn->connectpath;
2583 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2584 struct byte_range_lock *br_lck,
2585 struct lock_struct *plock,
2588 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2590 /* Note: blr is not used in the default implementation. */
2591 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2594 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2595 struct messaging_context *msg_ctx,
2596 struct byte_range_lock *br_lck,
2597 const struct lock_struct *plock)
2599 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2601 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2604 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2605 struct byte_range_lock *br_lck,
2606 struct lock_struct *plock)
2608 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2610 /* Note: blr is not used in the default implementation. */
2611 return brl_lock_cancel_default(br_lck, plock);
2614 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2616 struct lock_struct *plock)
2618 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2619 plock->lock_type == WRITE_LOCK);
2621 return strict_lock_default(fsp, plock);
2624 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2626 struct lock_struct *plock)
2628 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2629 plock->lock_type == WRITE_LOCK);
2631 strict_unlock_default(fsp, plock);
2634 /* NT ACL operations. */
2636 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2638 uint32_t security_info,
2639 TALLOC_CTX *mem_ctx,
2640 struct security_descriptor **ppdesc)
2644 START_PROFILE(fget_nt_acl);
2645 result = posix_fget_nt_acl(fsp, security_info,
2647 END_PROFILE(fget_nt_acl);
2651 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2652 const struct smb_filename *smb_fname,
2653 uint32_t security_info,
2654 TALLOC_CTX *mem_ctx,
2655 struct security_descriptor **ppdesc)
2659 START_PROFILE(get_nt_acl);
2660 result = posix_get_nt_acl(handle->conn,
2665 END_PROFILE(get_nt_acl);
2669 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2673 START_PROFILE(fset_nt_acl);
2674 result = set_nt_acl(fsp, security_info_sent, psd);
2675 END_PROFILE(fset_nt_acl);
2679 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2680 struct smb_filename *file,
2681 struct security_acl *sacl,
2682 uint32_t access_requested,
2683 uint32_t access_denied)
2685 return NT_STATUS_OK; /* Nothing to do here ... */
2688 static int vfswrap_chmod_acl(vfs_handle_struct *handle,
2689 const struct smb_filename *smb_fname,
2698 START_PROFILE(chmod_acl);
2699 result = chmod_acl(handle->conn, smb_fname, mode);
2700 END_PROFILE(chmod_acl);
2705 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2713 START_PROFILE(fchmod_acl);
2714 result = fchmod_acl(fsp, mode);
2715 END_PROFILE(fchmod_acl);
2720 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2721 const struct smb_filename *smb_fname,
2722 SMB_ACL_TYPE_T type,
2723 TALLOC_CTX *mem_ctx)
2725 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
2728 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2730 TALLOC_CTX *mem_ctx)
2732 return sys_acl_get_fd(handle, fsp, mem_ctx);
2735 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
2736 const struct smb_filename *smb_fname,
2737 SMB_ACL_TYPE_T acltype,
2740 return sys_acl_set_file(handle, smb_fname, acltype, theacl);
2743 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2745 return sys_acl_set_fd(handle, fsp, theacl);
2748 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
2749 const struct smb_filename *smb_fname)
2751 return sys_acl_delete_def_file(handle, smb_fname);
2754 /****************************************************************
2755 Extended attribute operations.
2756 *****************************************************************/
2758 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
2759 const struct smb_filename *smb_fname,
2764 return getxattr(smb_fname->base_name, name, value, size);
2767 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2769 return fgetxattr(fsp->fh->fd, name, value, size);
2772 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
2773 const struct smb_filename *smb_fname,
2777 return listxattr(smb_fname->base_name, list, size);
2780 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2782 return flistxattr(fsp->fh->fd, list, size);
2785 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
2786 const struct smb_filename *smb_fname,
2789 return removexattr(smb_fname->base_name, name);
2792 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2794 return fremovexattr(fsp->fh->fd, name);
2797 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
2798 const struct smb_filename *smb_fname,
2804 return setxattr(smb_fname->base_name, name, value, size, flags);
2807 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2809 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2812 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2817 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2818 const struct smb_filename *fname,
2819 SMB_STRUCT_STAT *sbuf)
2823 bool offline = false;
2825 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2829 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2830 #if defined(ENOTSUP)
2836 status = get_full_smb_filename(talloc_tos(), fname, &path);
2837 if (!NT_STATUS_IS_OK(status)) {
2838 errno = map_errno_from_nt_status(status);
2842 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2849 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2850 struct files_struct *fsp,
2851 TALLOC_CTX *mem_ctx,
2854 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2857 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2858 struct files_struct *fsp,
2859 const DATA_BLOB old_cookie,
2860 TALLOC_CTX *mem_ctx,
2861 DATA_BLOB *new_cookie)
2863 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2867 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2868 struct smb_request *smb1req,
2869 struct smbXsrv_open *op,
2870 const DATA_BLOB old_cookie,
2871 TALLOC_CTX *mem_ctx,
2872 struct files_struct **fsp,
2873 DATA_BLOB *new_cookie)
2875 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2876 old_cookie, mem_ctx,
2880 static struct vfs_fn_pointers vfs_default_fns = {
2881 /* Disk operations */
2883 .connect_fn = vfswrap_connect,
2884 .disconnect_fn = vfswrap_disconnect,
2885 .disk_free_fn = vfswrap_disk_free,
2886 .get_quota_fn = vfswrap_get_quota,
2887 .set_quota_fn = vfswrap_set_quota,
2888 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2889 .statvfs_fn = vfswrap_statvfs,
2890 .fs_capabilities_fn = vfswrap_fs_capabilities,
2891 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2892 .snap_check_path_fn = vfswrap_snap_check_path,
2893 .snap_create_fn = vfswrap_snap_create,
2894 .snap_delete_fn = vfswrap_snap_delete,
2896 /* Directory operations */
2898 .opendir_fn = vfswrap_opendir,
2899 .fdopendir_fn = vfswrap_fdopendir,
2900 .readdir_fn = vfswrap_readdir,
2901 .readdir_attr_fn = vfswrap_readdir_attr,
2902 .seekdir_fn = vfswrap_seekdir,
2903 .telldir_fn = vfswrap_telldir,
2904 .rewind_dir_fn = vfswrap_rewinddir,
2905 .mkdir_fn = vfswrap_mkdir,
2906 .rmdir_fn = vfswrap_rmdir,
2907 .closedir_fn = vfswrap_closedir,
2908 .init_search_op_fn = vfswrap_init_search_op,
2910 /* File operations */
2912 .open_fn = vfswrap_open,
2913 .create_file_fn = vfswrap_create_file,
2914 .close_fn = vfswrap_close,
2915 .read_fn = vfswrap_read,
2916 .pread_fn = vfswrap_pread,
2917 .pread_send_fn = vfswrap_pread_send,
2918 .pread_recv_fn = vfswrap_pread_recv,
2919 .write_fn = vfswrap_write,
2920 .pwrite_fn = vfswrap_pwrite,
2921 .pwrite_send_fn = vfswrap_pwrite_send,
2922 .pwrite_recv_fn = vfswrap_pwrite_recv,
2923 .lseek_fn = vfswrap_lseek,
2924 .sendfile_fn = vfswrap_sendfile,
2925 .recvfile_fn = vfswrap_recvfile,
2926 .rename_fn = vfswrap_rename,
2927 .fsync_fn = vfswrap_fsync,
2928 .fsync_send_fn = vfswrap_fsync_send,
2929 .fsync_recv_fn = vfswrap_fsync_recv,
2930 .stat_fn = vfswrap_stat,
2931 .fstat_fn = vfswrap_fstat,
2932 .lstat_fn = vfswrap_lstat,
2933 .get_alloc_size_fn = vfswrap_get_alloc_size,
2934 .unlink_fn = vfswrap_unlink,
2935 .chmod_fn = vfswrap_chmod,
2936 .fchmod_fn = vfswrap_fchmod,
2937 .chown_fn = vfswrap_chown,
2938 .fchown_fn = vfswrap_fchown,
2939 .lchown_fn = vfswrap_lchown,
2940 .chdir_fn = vfswrap_chdir,
2941 .getwd_fn = vfswrap_getwd,
2942 .ntimes_fn = vfswrap_ntimes,
2943 .ftruncate_fn = vfswrap_ftruncate,
2944 .fallocate_fn = vfswrap_fallocate,
2945 .lock_fn = vfswrap_lock,
2946 .kernel_flock_fn = vfswrap_kernel_flock,
2947 .linux_setlease_fn = vfswrap_linux_setlease,
2948 .getlock_fn = vfswrap_getlock,
2949 .symlink_fn = vfswrap_symlink,
2950 .readlink_fn = vfswrap_readlink,
2951 .link_fn = vfswrap_link,
2952 .mknod_fn = vfswrap_mknod,
2953 .realpath_fn = vfswrap_realpath,
2954 .chflags_fn = vfswrap_chflags,
2955 .file_id_create_fn = vfswrap_file_id_create,
2956 .streaminfo_fn = vfswrap_streaminfo,
2957 .get_real_filename_fn = vfswrap_get_real_filename,
2958 .connectpath_fn = vfswrap_connectpath,
2959 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2960 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2961 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2962 .strict_lock_fn = vfswrap_strict_lock,
2963 .strict_unlock_fn = vfswrap_strict_unlock,
2964 .translate_name_fn = vfswrap_translate_name,
2965 .fsctl_fn = vfswrap_fsctl,
2966 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
2967 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
2968 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
2969 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
2970 .copy_chunk_send_fn = vfswrap_copy_chunk_send,
2971 .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
2972 .get_compression_fn = vfswrap_get_compression,
2973 .set_compression_fn = vfswrap_set_compression,
2975 /* NT ACL operations. */
2977 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2978 .get_nt_acl_fn = vfswrap_get_nt_acl,
2979 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2980 .audit_file_fn = vfswrap_audit_file,
2982 /* POSIX ACL operations. */
2984 .chmod_acl_fn = vfswrap_chmod_acl,
2985 .fchmod_acl_fn = vfswrap_fchmod_acl,
2987 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2988 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2989 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2990 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2991 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2992 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2993 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2995 /* EA operations. */
2996 .getxattr_fn = vfswrap_getxattr,
2997 .fgetxattr_fn = vfswrap_fgetxattr,
2998 .listxattr_fn = vfswrap_listxattr,
2999 .flistxattr_fn = vfswrap_flistxattr,
3000 .removexattr_fn = vfswrap_removexattr,
3001 .fremovexattr_fn = vfswrap_fremovexattr,
3002 .setxattr_fn = vfswrap_setxattr,
3003 .fsetxattr_fn = vfswrap_fsetxattr,
3005 /* aio operations */
3006 .aio_force_fn = vfswrap_aio_force,
3008 /* durable handle operations */
3009 .durable_cookie_fn = vfswrap_durable_cookie,
3010 .durable_disconnect_fn = vfswrap_durable_disconnect,
3011 .durable_reconnect_fn = vfswrap_durable_reconnect,
3014 NTSTATUS vfs_default_init(TALLOC_CTX *);
3015 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3017 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3018 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);