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/asys/asys.h"
34 #include "lib/util/tevent_ntstatus.h"
35 #include "lib/util/sys_rw.h"
36 #include "lib/pthreadpool/pthreadpool_tevent.h"
39 #define DBGC_CLASS DBGC_VFS
41 /* Check for NULL pointer parameters in vfswrap_* functions */
43 /* We don't want to have NULL function pointers lying around. Someone
44 is sure to try and execute them. These stubs are used to prevent
47 static int vfswrap_connect(vfs_handle_struct *handle, const char *service, const char *user)
49 return 0; /* Return >= 0 for success */
52 static void vfswrap_disconnect(vfs_handle_struct *handle)
58 static uint64_t vfswrap_disk_free(vfs_handle_struct *handle, const char *path,
59 uint64_t *bsize, uint64_t *dfree,
62 if (sys_fsusage(path, dfree, dsize) != 0) {
70 static int vfswrap_get_quota(struct vfs_handle_struct *handle, const char *path,
71 enum SMB_QUOTA_TYPE qtype, unid_t id,
74 #ifdef HAVE_SYS_QUOTAS
77 START_PROFILE(syscall_get_quota);
78 result = sys_get_quota(path, qtype, id, qt);
79 END_PROFILE(syscall_get_quota);
87 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
89 #ifdef HAVE_SYS_QUOTAS
92 START_PROFILE(syscall_set_quota);
93 result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
94 END_PROFILE(syscall_set_quota);
102 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
103 struct files_struct *fsp,
104 struct shadow_copy_data *shadow_copy_data,
108 return -1; /* Not implemented. */
111 static int vfswrap_statvfs(struct vfs_handle_struct *handle, const char *path, vfs_statvfs_struct *statbuf)
113 return sys_statvfs(path, statbuf);
116 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
117 enum timestamp_set_resolution *p_ts_res)
119 connection_struct *conn = handle->conn;
120 uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
121 struct smb_filename *smb_fname_cpath = NULL;
122 struct vfs_statvfs_struct statbuf;
125 ZERO_STRUCT(statbuf);
126 ret = sys_statvfs(conn->connectpath, &statbuf);
128 caps = statbuf.FsCapabilities;
131 *p_ts_res = TIMESTAMP_SET_SECONDS;
133 /* Work out what timestamp resolution we can
134 * use when setting a timestamp. */
136 smb_fname_cpath = synthetic_smb_fname(talloc_tos(), conn->connectpath,
138 if (smb_fname_cpath == NULL) {
142 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
144 TALLOC_FREE(smb_fname_cpath);
148 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
149 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
150 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
151 /* If any of the normal UNIX directory timestamps
152 * have a non-zero tv_nsec component assume
153 * we might be able to set sub-second timestamps.
154 * See what filetime set primitives we have.
156 #if defined(HAVE_UTIMENSAT)
157 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
158 #elif defined(HAVE_UTIMES)
159 /* utimes allows msec timestamps to be set. */
160 *p_ts_res = TIMESTAMP_SET_MSEC;
161 #elif defined(HAVE_UTIME)
162 /* utime only allows sec timestamps to be set. */
163 *p_ts_res = TIMESTAMP_SET_SECONDS;
166 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
168 "available on share %s, directory %s\n",
169 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
170 lp_servicename(talloc_tos(), conn->params->service),
171 conn->connectpath ));
173 TALLOC_FREE(smb_fname_cpath);
177 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
178 struct dfs_GetDFSReferral *r)
180 struct junction_map *junction = NULL;
182 bool self_referral = false;
183 char *pathnamep = NULL;
184 char *local_dfs_path = NULL;
187 uint16_t max_referral_level = r->in.req.max_referral_level;
190 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
193 /* get the junction entry */
194 if (r->in.req.servername == NULL) {
195 return NT_STATUS_NOT_FOUND;
199 * Trim pathname sent by client so it begins with only one backslash.
200 * Two backslashes confuse some dfs clients
203 local_dfs_path = talloc_strdup(r, r->in.req.servername);
204 if (local_dfs_path == NULL) {
205 return NT_STATUS_NO_MEMORY;
207 pathnamep = local_dfs_path;
208 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
209 IS_DIRECTORY_SEP(pathnamep[1])) {
213 junction = talloc_zero(r, struct junction_map);
214 if (junction == NULL) {
215 return NT_STATUS_NO_MEMORY;
218 /* The following call can change cwd. */
219 status = get_referred_path(r, pathnamep,
220 !handle->conn->sconn->using_smb2,
221 junction, &consumedcnt, &self_referral);
222 if (!NT_STATUS_IS_OK(status)) {
223 vfs_ChDir(handle->conn, handle->conn->connectpath);
226 vfs_ChDir(handle->conn, handle->conn->connectpath);
228 if (!self_referral) {
229 pathnamep[consumedcnt] = '\0';
232 dbgtext("Path %s to alternate path(s):",
234 for (i=0; i < junction->referral_count; i++) {
236 junction->referral_list[i].alternate_path);
242 if (r->in.req.max_referral_level <= 2) {
243 max_referral_level = 2;
245 if (r->in.req.max_referral_level >= 3) {
246 max_referral_level = 3;
249 r->out.resp = talloc_zero(r, struct dfs_referral_resp);
250 if (r->out.resp == NULL) {
251 return NT_STATUS_NO_MEMORY;
254 r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
255 r->out.resp->nb_referrals = junction->referral_count;
257 r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
259 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
262 r->out.resp->referral_entries = talloc_zero_array(r,
263 struct dfs_referral_type,
264 r->out.resp->nb_referrals);
265 if (r->out.resp->referral_entries == NULL) {
266 return NT_STATUS_NO_MEMORY;
269 switch (max_referral_level) {
271 for(i=0; i < junction->referral_count; i++) {
272 struct referral *ref = &junction->referral_list[i];
273 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
274 struct dfs_referral_type *t =
275 &r->out.resp->referral_entries[i];
276 struct dfs_referral_v2 *v2 = &t->referral.v2;
279 v2->size = VERSION2_REFERRAL_SIZE;
281 v2->server_type = DFS_SERVER_ROOT;
283 v2->server_type = DFS_SERVER_NON_ROOT;
286 v2->proximity = ref->proximity;
288 v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
289 if (v2->DFS_path == NULL) {
290 return NT_STATUS_NO_MEMORY;
292 v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
293 if (v2->DFS_alt_path == NULL) {
294 return NT_STATUS_NO_MEMORY;
296 v2->netw_address = talloc_strdup(mem_ctx,
297 ref->alternate_path);
298 if (v2->netw_address == NULL) {
299 return NT_STATUS_NO_MEMORY;
305 for(i=0; i < junction->referral_count; i++) {
306 struct referral *ref = &junction->referral_list[i];
307 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
308 struct dfs_referral_type *t =
309 &r->out.resp->referral_entries[i];
310 struct dfs_referral_v3 *v3 = &t->referral.v3;
311 struct dfs_normal_referral *r1 = &v3->referrals.r1;
314 v3->size = VERSION3_REFERRAL_SIZE;
316 v3->server_type = DFS_SERVER_ROOT;
318 v3->server_type = DFS_SERVER_NON_ROOT;
322 r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
323 if (r1->DFS_path == NULL) {
324 return NT_STATUS_NO_MEMORY;
326 r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
327 if (r1->DFS_alt_path == NULL) {
328 return NT_STATUS_NO_MEMORY;
330 r1->netw_address = talloc_strdup(mem_ctx,
331 ref->alternate_path);
332 if (r1->netw_address == NULL) {
333 return NT_STATUS_NO_MEMORY;
338 DEBUG(0,("Invalid dfs referral version: %d\n",
339 max_referral_level));
340 return NT_STATUS_INVALID_LEVEL;
344 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
350 static NTSTATUS vfswrap_snap_check_path(struct vfs_handle_struct *handle,
352 const char *service_path,
355 return NT_STATUS_NOT_SUPPORTED;
358 static NTSTATUS vfswrap_snap_create(struct vfs_handle_struct *handle,
360 const char *base_volume,
366 return NT_STATUS_NOT_SUPPORTED;
369 static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle,
374 return NT_STATUS_NOT_SUPPORTED;
377 /* Directory operations */
379 static DIR *vfswrap_opendir(vfs_handle_struct *handle,
380 const struct smb_filename *smb_fname,
386 START_PROFILE(syscall_opendir);
387 result = opendir(smb_fname->base_name);
388 END_PROFILE(syscall_opendir);
392 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
399 START_PROFILE(syscall_fdopendir);
400 result = sys_fdopendir(fsp->fh->fd);
401 END_PROFILE(syscall_fdopendir);
406 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
408 SMB_STRUCT_STAT *sbuf)
410 struct dirent *result;
412 START_PROFILE(syscall_readdir);
413 result = readdir(dirp);
414 END_PROFILE(syscall_readdir);
416 /* Default Posix readdir() does not give us stat info.
417 * Set to invalid to indicate we didn't return this info. */
418 SET_STAT_INVALID(*sbuf);
419 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
420 if (result != NULL) {
421 /* See if we can efficiently return this. */
423 int flags = AT_SYMLINK_NOFOLLOW;
424 int ret = fstatat(dirfd(dirp),
429 * As this is an optimization,
430 * ignore it if we stat'ed a
431 * symlink. Make the caller
432 * do it again as we don't
433 * know if they wanted the link
434 * info, or its target info.
436 if ((ret == 0) && (!S_ISLNK(st.st_mode))) {
437 init_stat_ex_from_stat(sbuf,
439 lp_fake_directory_create_times(
440 SNUM(handle->conn)));
448 static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
449 const struct smb_filename *fname,
451 struct readdir_attr_data **attr_data)
453 return NT_STATUS_NOT_SUPPORTED;
456 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
458 START_PROFILE(syscall_seekdir);
459 seekdir(dirp, offset);
460 END_PROFILE(syscall_seekdir);
463 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
466 START_PROFILE(syscall_telldir);
467 result = telldir(dirp);
468 END_PROFILE(syscall_telldir);
472 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
474 START_PROFILE(syscall_rewinddir);
476 END_PROFILE(syscall_rewinddir);
479 static int vfswrap_mkdir(vfs_handle_struct *handle,
480 const struct smb_filename *smb_fname,
484 bool has_dacl = False;
485 const char *path = smb_fname->base_name;
488 START_PROFILE(syscall_mkdir);
490 if (lp_inherit_acls(SNUM(handle->conn))
491 && parent_dirname(talloc_tos(), path, &parent, NULL)
492 && (has_dacl = directory_has_default_acl(handle->conn, parent))) {
493 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
498 result = mkdir(path, mode);
500 if (result == 0 && !has_dacl) {
502 * We need to do this as the default behavior of POSIX ACLs
503 * is to set the mask to be the requested group permission
504 * bits, not the group permission bits to be the requested
505 * group permission bits. This is not what we want, as it will
506 * mess up any inherited ACL bits that were set. JRA.
508 int saved_errno = errno; /* We may get ENOSYS */
509 if ((SMB_VFS_CHMOD_ACL(handle->conn, smb_fname, mode) == -1) &&
515 END_PROFILE(syscall_mkdir);
519 static int vfswrap_rmdir(vfs_handle_struct *handle,
520 const struct smb_filename *smb_fname)
524 START_PROFILE(syscall_rmdir);
525 result = rmdir(smb_fname->base_name);
526 END_PROFILE(syscall_rmdir);
530 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
534 START_PROFILE(syscall_closedir);
535 result = closedir(dirp);
536 END_PROFILE(syscall_closedir);
540 static void vfswrap_init_search_op(vfs_handle_struct *handle,
543 /* Default behavior is a NOOP */
546 /* File operations */
548 static int vfswrap_open(vfs_handle_struct *handle,
549 struct smb_filename *smb_fname,
550 files_struct *fsp, int flags, mode_t mode)
554 START_PROFILE(syscall_open);
556 if (smb_fname->stream_name) {
561 result = open(smb_fname->base_name, flags, mode);
563 END_PROFILE(syscall_open);
567 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
568 struct smb_request *req,
569 uint16_t root_dir_fid,
570 struct smb_filename *smb_fname,
571 uint32_t access_mask,
572 uint32_t share_access,
573 uint32_t create_disposition,
574 uint32_t create_options,
575 uint32_t file_attributes,
576 uint32_t oplock_request,
577 struct smb2_lease *lease,
578 uint64_t allocation_size,
579 uint32_t private_flags,
580 struct security_descriptor *sd,
581 struct ea_list *ea_list,
582 files_struct **result,
584 const struct smb2_create_blobs *in_context_blobs,
585 struct smb2_create_blobs *out_context_blobs)
587 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
588 access_mask, share_access,
589 create_disposition, create_options,
590 file_attributes, oplock_request, lease,
591 allocation_size, private_flags,
593 pinfo, in_context_blobs, out_context_blobs);
596 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
600 START_PROFILE(syscall_close);
601 result = fd_close_posix(fsp);
602 END_PROFILE(syscall_close);
606 static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
610 START_PROFILE_BYTES(syscall_read, n);
611 result = sys_read(fsp->fh->fd, data, n);
612 END_PROFILE_BYTES(syscall_read);
616 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
617 size_t n, off_t offset)
621 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
622 START_PROFILE_BYTES(syscall_pread, n);
623 result = sys_pread(fsp->fh->fd, data, n, offset);
624 END_PROFILE_BYTES(syscall_pread);
626 if (result == -1 && errno == ESPIPE) {
627 /* Maintain the fiction that pipes can be seeked (sought?) on. */
628 result = SMB_VFS_READ(fsp, data, n);
632 #else /* HAVE_PREAD */
636 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
637 if (curr == -1 && errno == ESPIPE) {
638 /* Maintain the fiction that pipes can be seeked (sought?) on. */
639 result = SMB_VFS_READ(fsp, data, n);
644 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
649 result = SMB_VFS_READ(fsp, data, n);
652 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
655 #endif /* HAVE_PREAD */
660 static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
664 START_PROFILE_BYTES(syscall_write, n);
665 result = sys_write(fsp->fh->fd, data, n);
666 END_PROFILE_BYTES(syscall_write);
670 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
671 size_t n, off_t offset)
675 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
676 START_PROFILE_BYTES(syscall_pwrite, n);
677 result = sys_pwrite(fsp->fh->fd, data, n, offset);
678 END_PROFILE_BYTES(syscall_pwrite);
680 if (result == -1 && errno == ESPIPE) {
681 /* Maintain the fiction that pipes can be sought on. */
682 result = SMB_VFS_WRITE(fsp, data, n);
685 #else /* HAVE_PWRITE */
689 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
694 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
698 result = SMB_VFS_WRITE(fsp, data, n);
701 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
704 #endif /* HAVE_PWRITE */
709 static void vfswrap_asys_finished(struct tevent_context *ev,
710 struct tevent_fd *fde,
711 uint16_t flags, void *p);
713 static bool vfswrap_init_asys_ctx(struct smbd_server_connection *conn)
715 struct asys_context *ctx;
716 struct tevent_fd *fde;
720 if (conn->asys_ctx != NULL) {
724 ret = asys_context_init(&ctx, lp_aio_max_threads());
726 DEBUG(1, ("asys_context_init failed: %s\n", strerror(ret)));
730 fd = asys_signalfd(ctx);
732 ret = set_blocking(fd, false);
734 DBG_WARNING("set_blocking failed: %s\n", strerror(errno));
738 fde = tevent_add_fd(conn->ev_ctx, conn, fd, TEVENT_FD_READ,
739 vfswrap_asys_finished, ctx);
741 DEBUG(1, ("tevent_add_fd failed\n"));
745 conn->asys_ctx = ctx;
746 conn->asys_fde = fde;
750 asys_context_destroy(ctx);
754 static int vfswrap_init_pool(struct smbd_server_connection *conn)
758 if (conn->pool != NULL) {
762 ret = pthreadpool_tevent_init(conn, lp_aio_max_threads(),
768 struct vfswrap_asys_state {
769 struct asys_context *asys_ctx;
770 struct tevent_req *req;
772 struct vfs_aio_state vfs_aio_state;
773 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
774 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
777 static int vfswrap_asys_state_destructor(struct vfswrap_asys_state *s)
779 asys_cancel(s->asys_ctx, s->req);
783 struct vfswrap_pread_state {
791 struct vfs_aio_state vfs_aio_state;
792 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
795 static void vfs_pread_do(void *private_data);
796 static void vfs_pread_done(struct tevent_req *subreq);
798 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
800 struct tevent_context *ev,
801 struct files_struct *fsp,
803 size_t n, off_t offset)
805 struct tevent_req *req, *subreq;
806 struct vfswrap_pread_state *state;
809 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
814 ret = vfswrap_init_pool(handle->conn->sconn);
815 if (tevent_req_error(req, ret)) {
816 return tevent_req_post(req, ev);
820 state->fd = fsp->fh->fd;
823 state->offset = offset;
825 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
826 state->profile_bytes, n);
827 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
829 subreq = pthreadpool_tevent_job_send(
830 state, ev, handle->conn->sconn->pool,
831 vfs_pread_do, state);
832 if (tevent_req_nomem(subreq, req)) {
833 return tevent_req_post(req, ev);
835 tevent_req_set_callback(subreq, vfs_pread_done, req);
840 static void vfs_pread_do(void *private_data)
842 struct vfswrap_pread_state *state = talloc_get_type_abort(
843 private_data, struct vfswrap_pread_state);
844 struct timespec start_time;
845 struct timespec end_time;
847 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
849 PROFILE_TIMESTAMP(&start_time);
852 state->ret = pread(state->fd, state->buf, state->count,
854 } while ((state->ret == -1) && (errno == EINTR));
858 PROFILE_TIMESTAMP(&end_time);
860 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
862 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
865 static void vfs_pread_done(struct tevent_req *subreq)
867 struct tevent_req *req = tevent_req_callback_data(
868 subreq, struct tevent_req);
870 struct vfswrap_pread_state *state = tevent_req_data(
871 req, struct vfswrap_pread_state);
875 ret = pthreadpool_tevent_job_recv(subreq);
877 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
878 if (tevent_req_error(req, ret)) {
882 tevent_req_done(req);
885 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
886 struct vfs_aio_state *vfs_aio_state)
888 struct vfswrap_pread_state *state = tevent_req_data(
889 req, struct vfswrap_pread_state);
891 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
895 *vfs_aio_state = state->vfs_aio_state;
899 struct vfswrap_pwrite_state {
907 struct vfs_aio_state vfs_aio_state;
908 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
911 static void vfs_pwrite_do(void *private_data);
912 static void vfs_pwrite_done(struct tevent_req *subreq);
914 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
916 struct tevent_context *ev,
917 struct files_struct *fsp,
919 size_t n, off_t offset)
921 struct tevent_req *req, *subreq;
922 struct vfswrap_pwrite_state *state;
925 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
930 ret = vfswrap_init_pool(handle->conn->sconn);
931 if (tevent_req_error(req, ret)) {
932 return tevent_req_post(req, ev);
936 state->fd = fsp->fh->fd;
939 state->offset = offset;
941 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
942 state->profile_bytes, n);
943 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
945 subreq = pthreadpool_tevent_job_send(
946 state, ev, handle->conn->sconn->pool,
947 vfs_pwrite_do, state);
948 if (tevent_req_nomem(subreq, req)) {
949 return tevent_req_post(req, ev);
951 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
956 static void vfs_pwrite_do(void *private_data)
958 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
959 private_data, struct vfswrap_pwrite_state);
960 struct timespec start_time;
961 struct timespec end_time;
963 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
965 PROFILE_TIMESTAMP(&start_time);
968 state->ret = pwrite(state->fd, state->buf, state->count,
970 } while ((state->ret == -1) && (errno == EINTR));
974 PROFILE_TIMESTAMP(&end_time);
976 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
978 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
981 static void vfs_pwrite_done(struct tevent_req *subreq)
983 struct tevent_req *req = tevent_req_callback_data(
984 subreq, struct tevent_req);
986 struct vfswrap_pwrite_state *state = tevent_req_data(
987 req, struct vfswrap_pwrite_state);
991 ret = pthreadpool_tevent_job_recv(subreq);
993 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
994 if (tevent_req_error(req, ret)) {
998 tevent_req_done(req);
1001 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
1002 struct vfs_aio_state *vfs_aio_state)
1004 struct vfswrap_pwrite_state *state = tevent_req_data(
1005 req, struct vfswrap_pwrite_state);
1007 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1011 *vfs_aio_state = state->vfs_aio_state;
1015 struct vfswrap_fsync_state {
1020 struct vfs_aio_state vfs_aio_state;
1021 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
1024 static void vfs_fsync_do(void *private_data);
1025 static void vfs_fsync_done(struct tevent_req *subreq);
1027 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
1028 TALLOC_CTX *mem_ctx,
1029 struct tevent_context *ev,
1030 struct files_struct *fsp)
1032 struct tevent_req *req, *subreq;
1033 struct vfswrap_fsync_state *state;
1036 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
1041 ret = vfswrap_init_pool(handle->conn->sconn);
1042 if (tevent_req_error(req, ret)) {
1043 return tevent_req_post(req, ev);
1047 state->fd = fsp->fh->fd;
1049 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
1050 state->profile_basic);
1052 subreq = pthreadpool_tevent_job_send(
1053 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
1054 if (tevent_req_nomem(subreq, req)) {
1055 return tevent_req_post(req, ev);
1057 tevent_req_set_callback(subreq, vfs_fsync_done, req);
1062 static void vfs_fsync_do(void *private_data)
1064 struct vfswrap_fsync_state *state = talloc_get_type_abort(
1065 private_data, struct vfswrap_fsync_state);
1066 struct timespec start_time;
1067 struct timespec end_time;
1069 PROFILE_TIMESTAMP(&start_time);
1072 state->ret = fsync(state->fd);
1073 } while ((state->ret == -1) && (errno == EINTR));
1077 PROFILE_TIMESTAMP(&end_time);
1079 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1082 static void vfs_fsync_done(struct tevent_req *subreq)
1084 struct tevent_req *req = tevent_req_callback_data(
1085 subreq, struct tevent_req);
1087 struct vfswrap_fsync_state *state = tevent_req_data(
1088 req, struct vfswrap_fsync_state);
1092 ret = pthreadpool_tevent_job_recv(subreq);
1093 TALLOC_FREE(subreq);
1094 SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
1095 if (tevent_req_error(req, ret)) {
1099 tevent_req_done(req);
1102 static int vfswrap_fsync_recv(struct tevent_req *req,
1103 struct vfs_aio_state *vfs_aio_state)
1105 struct vfswrap_fsync_state *state = tevent_req_data(
1106 req, struct vfswrap_fsync_state);
1108 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1112 *vfs_aio_state = state->vfs_aio_state;
1116 static void vfswrap_asys_finished(struct tevent_context *ev,
1117 struct tevent_fd *fde,
1118 uint16_t flags, void *p)
1120 struct asys_context *asys_ctx = (struct asys_context *)p;
1121 struct asys_result results[get_outstanding_aio_calls()];
1124 if ((flags & TEVENT_FD_READ) == 0) {
1128 ret = asys_results(asys_ctx, results, get_outstanding_aio_calls());
1130 DEBUG(1, ("asys_results returned %s\n", strerror(-ret)));
1134 for (i=0; i<ret; i++) {
1135 struct asys_result *result = &results[i];
1136 struct tevent_req *req;
1137 struct vfswrap_asys_state *state;
1139 if ((result->ret == -1) && (result->err == ECANCELED)) {
1143 req = talloc_get_type_abort(result->private_data,
1145 state = tevent_req_data(req, struct vfswrap_asys_state);
1147 talloc_set_destructor(state, NULL);
1149 SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
1150 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1151 state->ret = result->ret;
1152 state->vfs_aio_state.error = result->err;
1153 state->vfs_aio_state.duration = result->duration;
1154 tevent_req_defer_callback(req, ev);
1155 tevent_req_done(req);
1159 static ssize_t vfswrap_asys_ssize_t_recv(struct tevent_req *req,
1160 struct vfs_aio_state *vfs_aio_state)
1162 struct vfswrap_asys_state *state = tevent_req_data(
1163 req, struct vfswrap_asys_state);
1165 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1168 *vfs_aio_state = state->vfs_aio_state;
1172 static int vfswrap_asys_int_recv(struct tevent_req *req,
1173 struct vfs_aio_state *vfs_aio_state)
1175 struct vfswrap_asys_state *state = tevent_req_data(
1176 req, struct vfswrap_asys_state);
1178 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1181 *vfs_aio_state = state->vfs_aio_state;
1185 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1189 START_PROFILE(syscall_lseek);
1191 /* Cope with 'stat' file opens. */
1192 if (fsp->fh->fd != -1)
1193 result = lseek(fsp->fh->fd, offset, whence);
1196 * We want to maintain the fiction that we can seek
1197 * on a fifo for file system purposes. This allows
1198 * people to set up UNIX fifo's that feed data to Windows
1199 * applications. JRA.
1202 if((result == -1) && (errno == ESPIPE)) {
1207 END_PROFILE(syscall_lseek);
1211 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1212 off_t offset, size_t n)
1216 START_PROFILE_BYTES(syscall_sendfile, n);
1217 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
1218 END_PROFILE_BYTES(syscall_sendfile);
1222 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1224 files_struct *tofsp,
1230 START_PROFILE_BYTES(syscall_recvfile, n);
1231 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
1232 END_PROFILE_BYTES(syscall_recvfile);
1236 static int vfswrap_rename(vfs_handle_struct *handle,
1237 const struct smb_filename *smb_fname_src,
1238 const struct smb_filename *smb_fname_dst)
1242 START_PROFILE(syscall_rename);
1244 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
1249 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
1252 END_PROFILE(syscall_rename);
1256 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
1261 START_PROFILE(syscall_fsync);
1262 result = fsync(fsp->fh->fd);
1263 END_PROFILE(syscall_fsync);
1270 static int vfswrap_stat(vfs_handle_struct *handle,
1271 struct smb_filename *smb_fname)
1275 START_PROFILE(syscall_stat);
1277 if (smb_fname->stream_name) {
1282 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1283 lp_fake_directory_create_times(SNUM(handle->conn)));
1285 END_PROFILE(syscall_stat);
1289 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1293 START_PROFILE(syscall_fstat);
1294 result = sys_fstat(fsp->fh->fd,
1295 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1296 END_PROFILE(syscall_fstat);
1300 static int vfswrap_lstat(vfs_handle_struct *handle,
1301 struct smb_filename *smb_fname)
1305 START_PROFILE(syscall_lstat);
1307 if (smb_fname->stream_name) {
1312 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1313 lp_fake_directory_create_times(SNUM(handle->conn)));
1315 END_PROFILE(syscall_lstat);
1319 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1321 enum vfs_translate_direction direction,
1322 TALLOC_CTX *mem_ctx,
1325 return NT_STATUS_NONE_MAPPED;
1329 * Implement the default fsctl operation.
1331 static bool vfswrap_logged_ioctl_message = false;
1333 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1334 struct files_struct *fsp,
1337 uint16_t req_flags, /* Needed for UNICODE ... */
1338 const uint8_t *_in_data,
1340 uint8_t **_out_data,
1341 uint32_t max_out_len,
1344 const char *in_data = (const char *)_in_data;
1345 char **out_data = (char **)_out_data;
1349 case FSCTL_SET_SPARSE:
1351 bool set_sparse = true;
1353 if (in_len >= 1 && in_data[0] == 0) {
1357 status = file_set_sparse(handle->conn, fsp, set_sparse);
1359 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1360 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1361 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1362 nt_errstr(status)));
1367 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1369 unsigned char objid[16];
1370 char *return_data = NULL;
1372 /* This should return the object-id on this file.
1373 * I think I'll make this be the inode+dev. JRA.
1376 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1377 fsp_fnum_dbg(fsp)));
1379 *out_len = MIN(max_out_len, 64);
1381 /* Hmmm, will this cause problems if less data asked for? */
1382 return_data = talloc_array(ctx, char, 64);
1383 if (return_data == NULL) {
1384 return NT_STATUS_NO_MEMORY;
1387 /* For backwards compatibility only store the dev/inode. */
1388 push_file_id_16(return_data, &fsp->file_id);
1389 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1390 push_file_id_16(return_data+32, &fsp->file_id);
1391 memset(return_data+48, 0, 16);
1392 *out_data = return_data;
1393 return NT_STATUS_OK;
1396 case FSCTL_GET_REPARSE_POINT:
1398 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1399 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1400 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1401 return NT_STATUS_NOT_A_REPARSE_POINT;
1404 case FSCTL_SET_REPARSE_POINT:
1406 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1407 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1408 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1409 return NT_STATUS_NOT_A_REPARSE_POINT;
1412 case FSCTL_GET_SHADOW_COPY_DATA:
1415 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1416 * and return their volume names. If max_data_count is 16, then it is just
1417 * asking for the number of volumes and length of the combined names.
1419 * pdata is the data allocated by our caller, but that uses
1420 * total_data_count (which is 0 in our case) rather than max_data_count.
1421 * Allocate the correct amount and return the pointer to let
1422 * it be deallocated when we return.
1424 struct shadow_copy_data *shadow_data = NULL;
1425 bool labels = False;
1426 uint32_t labels_data_count = 0;
1428 char *cur_pdata = NULL;
1430 if (max_out_len < 16) {
1431 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1433 return NT_STATUS_INVALID_PARAMETER;
1436 if (max_out_len > 16) {
1440 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1441 if (shadow_data == NULL) {
1442 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1443 return NT_STATUS_NO_MEMORY;
1447 * Call the VFS routine to actually do the work.
1449 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1452 /* broken module didn't set errno on error */
1453 status = NT_STATUS_UNSUCCESSFUL;
1455 status = map_nt_error_from_unix(errno);
1456 if (NT_STATUS_EQUAL(status,
1457 NT_STATUS_NOT_SUPPORTED)) {
1461 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1462 "connectpath %s, failed - %s.\n",
1463 fsp->conn->connectpath,
1464 nt_errstr(status)));
1465 TALLOC_FREE(shadow_data);
1469 labels_data_count = (shadow_data->num_volumes * 2 *
1470 sizeof(SHADOW_COPY_LABEL)) + 2;
1475 *out_len = 12 + labels_data_count;
1478 if (max_out_len < *out_len) {
1479 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1480 max_out_len, *out_len));
1481 TALLOC_FREE(shadow_data);
1482 return NT_STATUS_BUFFER_TOO_SMALL;
1485 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1486 if (cur_pdata == NULL) {
1487 TALLOC_FREE(shadow_data);
1488 return NT_STATUS_NO_MEMORY;
1491 *out_data = cur_pdata;
1493 /* num_volumes 4 bytes */
1494 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1497 /* num_labels 4 bytes */
1498 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1501 /* needed_data_count 4 bytes */
1502 SIVAL(cur_pdata, 8, labels_data_count);
1506 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1507 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1508 if (labels && shadow_data->labels) {
1509 for (i=0; i<shadow_data->num_volumes; i++) {
1511 status = srvstr_push(cur_pdata, req_flags,
1512 cur_pdata, shadow_data->labels[i],
1513 2 * sizeof(SHADOW_COPY_LABEL),
1514 STR_UNICODE|STR_TERMINATE, &len);
1515 if (!NT_STATUS_IS_OK(status)) {
1516 TALLOC_FREE(*out_data);
1517 TALLOC_FREE(shadow_data);
1520 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1521 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1525 TALLOC_FREE(shadow_data);
1527 return NT_STATUS_OK;
1530 case FSCTL_FIND_FILES_BY_SID:
1532 /* pretend this succeeded -
1534 * we have to send back a list with all files owned by this SID
1536 * but I have to check that --metze
1542 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1543 fsp_fnum_dbg(fsp)));
1546 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1547 return NT_STATUS_INVALID_PARAMETER;
1550 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1552 /* unknown 4 bytes: this is not the length of the sid :-( */
1553 /*unknown = IVAL(pdata,0);*/
1555 if (!sid_parse(_in_data + 4, sid_len, &sid)) {
1556 return NT_STATUS_INVALID_PARAMETER;
1558 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1560 if (!sid_to_uid(&sid, &uid)) {
1561 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1562 sid_string_dbg(&sid),
1563 (unsigned long)sid_len));
1567 /* we can take a look at the find source :-)
1569 * find ./ -uid $uid -name '*' is what we need here
1572 * and send 4bytes len and then NULL terminated unicode strings
1575 * but I don't know how to deal with the paged results
1576 * (maybe we can hang the result anywhere in the fsp struct)
1578 * but I don't know how to deal with the paged results
1579 * (maybe we can hang the result anywhere in the fsp struct)
1581 * we don't send all files at once
1582 * and at the next we should *not* start from the beginning,
1583 * so we have to cache the result
1588 /* this works for now... */
1589 return NT_STATUS_OK;
1592 case FSCTL_QUERY_ALLOCATED_RANGES:
1594 /* FIXME: This is just a dummy reply, telling that all of the
1595 * file is allocated. MKS cp needs that.
1596 * Adding the real allocated ranges via FIEMAP on Linux
1597 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1598 * this FSCTL correct for sparse files.
1600 uint64_t offset, length;
1601 char *out_data_tmp = NULL;
1604 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1606 return NT_STATUS_INVALID_PARAMETER;
1609 if (max_out_len < 16) {
1610 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1612 return NT_STATUS_INVALID_PARAMETER;
1615 offset = BVAL(in_data,0);
1616 length = BVAL(in_data,8);
1618 if (offset + length < offset) {
1619 /* No 64-bit integer wrap. */
1620 return NT_STATUS_INVALID_PARAMETER;
1623 /* Shouldn't this be SMB_VFS_STAT ... ? */
1624 status = vfs_stat_fsp(fsp);
1625 if (!NT_STATUS_IS_OK(status)) {
1630 out_data_tmp = talloc_array(ctx, char, *out_len);
1631 if (out_data_tmp == NULL) {
1632 DEBUG(10, ("unable to allocate memory for response\n"));
1633 return NT_STATUS_NO_MEMORY;
1636 if (offset > fsp->fsp_name->st.st_ex_size ||
1637 fsp->fsp_name->st.st_ex_size == 0 ||
1639 memset(out_data_tmp, 0, *out_len);
1641 uint64_t end = offset + length;
1642 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1643 SBVAL(out_data_tmp, 0, 0);
1644 SBVAL(out_data_tmp, 8, end);
1647 *out_data = out_data_tmp;
1649 return NT_STATUS_OK;
1652 case FSCTL_IS_VOLUME_DIRTY:
1654 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1655 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1657 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1658 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1660 return NT_STATUS_INVALID_PARAMETER;
1665 * Only print once ... unfortunately there could be lots of
1666 * different FSCTLs that are called.
1668 if (!vfswrap_logged_ioctl_message) {
1669 vfswrap_logged_ioctl_message = true;
1670 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1671 __func__, function));
1675 return NT_STATUS_NOT_SUPPORTED;
1678 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1679 struct smb_filename *smb_fname,
1682 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1685 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1686 struct files_struct *fsp,
1689 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1692 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1693 const struct smb_filename *smb_fname,
1696 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1699 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1700 struct files_struct *fsp,
1703 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1706 struct vfs_cc_state {
1711 static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *handle,
1712 TALLOC_CTX *mem_ctx,
1713 struct tevent_context *ev,
1714 struct files_struct *src_fsp,
1716 struct files_struct *dest_fsp,
1720 struct tevent_req *req;
1721 struct vfs_cc_state *vfs_cc_state;
1724 DEBUG(10, ("performing server side copy chunk of length %lu\n",
1725 (unsigned long)num));
1727 req = tevent_req_create(mem_ctx, &vfs_cc_state, struct vfs_cc_state);
1732 vfs_cc_state->buf = talloc_array(vfs_cc_state, uint8_t,
1733 MIN(num, 8*1024*1024));
1734 if (tevent_req_nomem(vfs_cc_state->buf, req)) {
1735 return tevent_req_post(req, ev);
1738 status = vfs_stat_fsp(src_fsp);
1739 if (tevent_req_nterror(req, status)) {
1740 return tevent_req_post(req, ev);
1743 if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
1745 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1746 * If the SourceOffset or SourceOffset + Length extends beyond
1747 * the end of file, the server SHOULD<240> treat this as a
1748 * STATUS_END_OF_FILE error.
1750 * <240> Section 3.3.5.15.6: Windows servers will return
1751 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1753 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1754 return tevent_req_post(req, ev);
1757 /* could use 2.6.33+ sendfile here to do this in kernel */
1758 while (vfs_cc_state->copied < num) {
1760 struct lock_struct lck;
1763 off_t this_num = MIN(talloc_array_length(vfs_cc_state->buf),
1764 num - vfs_cc_state->copied);
1766 if (src_fsp->op == NULL) {
1767 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1768 return tevent_req_post(req, ev);
1770 init_strict_lock_struct(src_fsp,
1771 src_fsp->op->global->open_persistent_id,
1777 if (!SMB_VFS_STRICT_LOCK(src_fsp->conn, src_fsp, &lck)) {
1778 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1779 return tevent_req_post(req, ev);
1782 ret = SMB_VFS_PREAD(src_fsp, vfs_cc_state->buf,
1785 saved_errno = errno;
1788 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1791 errno = saved_errno;
1792 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1793 return tevent_req_post(req, ev);
1795 if (ret != this_num) {
1796 /* zero tolerance for short reads */
1797 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1798 return tevent_req_post(req, ev);
1803 if (dest_fsp->op == NULL) {
1804 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1805 return tevent_req_post(req, ev);
1808 init_strict_lock_struct(dest_fsp,
1809 dest_fsp->op->global->open_persistent_id,
1815 if (!SMB_VFS_STRICT_LOCK(dest_fsp->conn, dest_fsp, &lck)) {
1816 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1817 return tevent_req_post(req, ev);
1820 ret = SMB_VFS_PWRITE(dest_fsp, vfs_cc_state->buf,
1821 this_num, dest_off);
1823 saved_errno = errno;
1826 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1829 errno = saved_errno;
1830 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1831 return tevent_req_post(req, ev);
1833 if (ret != this_num) {
1834 /* zero tolerance for short writes */
1835 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1836 return tevent_req_post(req, ev);
1840 vfs_cc_state->copied += this_num;
1843 tevent_req_done(req);
1844 return tevent_req_post(req, ev);
1847 static NTSTATUS vfswrap_copy_chunk_recv(struct vfs_handle_struct *handle,
1848 struct tevent_req *req,
1851 struct vfs_cc_state *vfs_cc_state = tevent_req_data(req,
1852 struct vfs_cc_state);
1855 if (tevent_req_is_nterror(req, &status)) {
1856 DEBUG(2, ("server side copy chunk failed: %s\n",
1857 nt_errstr(status)));
1859 tevent_req_received(req);
1863 *copied = vfs_cc_state->copied;
1864 DEBUG(10, ("server side copy chunk copied %lu\n",
1865 (unsigned long)*copied));
1866 tevent_req_received(req);
1868 return NT_STATUS_OK;
1871 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1872 TALLOC_CTX *mem_ctx,
1873 struct files_struct *fsp,
1874 struct smb_filename *smb_fname,
1875 uint16_t *_compression_fmt)
1877 return NT_STATUS_INVALID_DEVICE_REQUEST;
1880 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1881 TALLOC_CTX *mem_ctx,
1882 struct files_struct *fsp,
1883 uint16_t compression_fmt)
1885 return NT_STATUS_INVALID_DEVICE_REQUEST;
1888 /********************************************************************
1889 Given a stat buffer return the allocated size on disk, taking into
1890 account sparse files.
1891 ********************************************************************/
1892 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1893 struct files_struct *fsp,
1894 const SMB_STRUCT_STAT *sbuf)
1898 START_PROFILE(syscall_get_alloc_size);
1900 if(S_ISDIR(sbuf->st_ex_mode)) {
1905 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1906 /* The type of st_blocksize is blkcnt_t which *MUST* be
1907 signed (according to POSIX) and can be less than 64-bits.
1908 Ensure when we're converting to 64 bits wide we don't
1910 #if defined(SIZEOF_BLKCNT_T_8)
1911 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1912 #elif defined(SIZEOF_BLKCNT_T_4)
1914 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1915 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1918 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1922 * Some file systems do not allocate a block for very
1923 * small files. But for non-empty file should report a
1927 uint64_t filesize = get_file_size_stat(sbuf);
1929 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
1933 result = get_file_size_stat(sbuf);
1936 if (fsp && fsp->initial_allocation_size)
1937 result = MAX(result,fsp->initial_allocation_size);
1939 result = smb_roundup(handle->conn, result);
1942 END_PROFILE(syscall_get_alloc_size);
1946 static int vfswrap_unlink(vfs_handle_struct *handle,
1947 const struct smb_filename *smb_fname)
1951 START_PROFILE(syscall_unlink);
1953 if (smb_fname->stream_name) {
1957 result = unlink(smb_fname->base_name);
1960 END_PROFILE(syscall_unlink);
1964 static int vfswrap_chmod(vfs_handle_struct *handle,
1965 const struct smb_filename *smb_fname,
1970 START_PROFILE(syscall_chmod);
1973 * We need to do this due to the fact that the default POSIX ACL
1974 * chmod modifies the ACL *mask* for the group owner, not the
1975 * group owner bits directly. JRA.
1980 int saved_errno = errno; /* We might get ENOSYS */
1981 result = SMB_VFS_CHMOD_ACL(handle->conn,
1985 END_PROFILE(syscall_chmod);
1988 /* Error - return the old errno. */
1989 errno = saved_errno;
1992 result = chmod(smb_fname->base_name, mode);
1993 END_PROFILE(syscall_chmod);
1997 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2001 START_PROFILE(syscall_fchmod);
2004 * We need to do this due to the fact that the default POSIX ACL
2005 * chmod modifies the ACL *mask* for the group owner, not the
2006 * group owner bits directly. JRA.
2010 int saved_errno = errno; /* We might get ENOSYS */
2011 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
2012 END_PROFILE(syscall_fchmod);
2015 /* Error - return the old errno. */
2016 errno = saved_errno;
2019 #if defined(HAVE_FCHMOD)
2020 result = fchmod(fsp->fh->fd, mode);
2026 END_PROFILE(syscall_fchmod);
2030 static int vfswrap_chown(vfs_handle_struct *handle,
2031 const struct smb_filename *smb_fname,
2037 START_PROFILE(syscall_chown);
2038 result = chown(smb_fname->base_name, uid, gid);
2039 END_PROFILE(syscall_chown);
2043 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2048 START_PROFILE(syscall_fchown);
2049 result = fchown(fsp->fh->fd, uid, gid);
2050 END_PROFILE(syscall_fchown);
2058 static int vfswrap_lchown(vfs_handle_struct *handle,
2059 const struct smb_filename *smb_fname,
2065 START_PROFILE(syscall_lchown);
2066 result = lchown(smb_fname->base_name, uid, gid);
2067 END_PROFILE(syscall_lchown);
2071 static int vfswrap_chdir(vfs_handle_struct *handle, const char *path)
2075 START_PROFILE(syscall_chdir);
2076 result = chdir(path);
2077 END_PROFILE(syscall_chdir);
2081 static char *vfswrap_getwd(vfs_handle_struct *handle)
2085 START_PROFILE(syscall_getwd);
2086 result = sys_getwd();
2087 END_PROFILE(syscall_getwd);
2091 /*********************************************************************
2092 nsec timestamp resolution call. Convert down to whatever the underlying
2093 system will support.
2094 **********************************************************************/
2096 static int vfswrap_ntimes(vfs_handle_struct *handle,
2097 const struct smb_filename *smb_fname,
2098 struct smb_file_time *ft)
2102 START_PROFILE(syscall_ntimes);
2104 if (smb_fname->stream_name) {
2110 if (null_timespec(ft->atime)) {
2111 ft->atime= smb_fname->st.st_ex_atime;
2114 if (null_timespec(ft->mtime)) {
2115 ft->mtime = smb_fname->st.st_ex_mtime;
2118 if (!null_timespec(ft->create_time)) {
2119 set_create_timespec_ea(handle->conn,
2124 if ((timespec_compare(&ft->atime,
2125 &smb_fname->st.st_ex_atime) == 0) &&
2126 (timespec_compare(&ft->mtime,
2127 &smb_fname->st.st_ex_mtime) == 0)) {
2132 #if defined(HAVE_UTIMENSAT)
2134 struct timespec ts[2];
2137 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2139 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2141 if (!((result == -1) && (errno == ENOSYS))) {
2145 #if defined(HAVE_UTIMES)
2147 struct timeval tv[2];
2148 tv[0] = convert_timespec_to_timeval(ft->atime);
2149 tv[1] = convert_timespec_to_timeval(ft->mtime);
2150 result = utimes(smb_fname->base_name, tv);
2152 result = utimes(smb_fname->base_name, NULL);
2154 if (!((result == -1) && (errno == ENOSYS))) {
2158 #if defined(HAVE_UTIME)
2160 struct utimbuf times;
2161 times.actime = convert_timespec_to_time_t(ft->atime);
2162 times.modtime = convert_timespec_to_time_t(ft->mtime);
2163 result = utime(smb_fname->base_name, ×);
2165 result = utime(smb_fname->base_name, NULL);
2167 if (!((result == -1) && (errno == ENOSYS))) {
2175 END_PROFILE(syscall_ntimes);
2179 /*********************************************************************
2180 A version of ftruncate that will write the space on disk if strict
2182 **********************************************************************/
2184 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2186 off_t space_to_write;
2187 uint64_t space_avail;
2188 uint64_t bsize,dfree,dsize;
2191 SMB_STRUCT_STAT *pst;
2193 status = vfs_stat_fsp(fsp);
2194 if (!NT_STATUS_IS_OK(status)) {
2197 pst = &fsp->fsp_name->st;
2200 if (S_ISFIFO(pst->st_ex_mode))
2204 if (pst->st_ex_size == len)
2207 /* Shrink - just ftruncate. */
2208 if (pst->st_ex_size > len)
2209 return ftruncate(fsp->fh->fd, len);
2211 space_to_write = len - pst->st_ex_size;
2213 /* for allocation try fallocate first. This can fail on some
2214 platforms e.g. when the filesystem doesn't support it and no
2215 emulation is being done by the libc (like on AIX with JFS1). In that
2216 case we do our own emulation. fallocate implementations can
2217 return ENOTSUP or EINVAL in cases like that. */
2218 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2219 if (ret == -1 && errno == ENOSPC) {
2225 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2226 "error %d. Falling back to slow manual allocation\n", errno));
2228 /* available disk space is enough or not? */
2230 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2231 /* space_avail is 1k blocks */
2232 if (space_avail == (uint64_t)-1 ||
2233 ((uint64_t)space_to_write/1024 > space_avail) ) {
2238 /* Write out the real space on disk. */
2239 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2247 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2250 SMB_STRUCT_STAT *pst;
2254 START_PROFILE(syscall_ftruncate);
2256 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2257 result = strict_allocate_ftruncate(handle, fsp, len);
2258 END_PROFILE(syscall_ftruncate);
2262 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2263 ftruncate if the system supports it. Then I discovered that
2264 you can have some filesystems that support ftruncate
2265 expansion and some that don't! On Linux fat can't do
2266 ftruncate extend but ext2 can. */
2268 result = ftruncate(fsp->fh->fd, len);
2270 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2271 extend a file with ftruncate. Provide alternate implementation
2274 /* Do an fstat to see if the file is longer than the requested
2275 size in which case the ftruncate above should have
2276 succeeded or shorter, in which case seek to len - 1 and
2277 write 1 byte of zero */
2278 status = vfs_stat_fsp(fsp);
2279 if (!NT_STATUS_IS_OK(status)) {
2283 /* We need to update the files_struct after successful ftruncate */
2288 pst = &fsp->fsp_name->st;
2291 if (S_ISFIFO(pst->st_ex_mode)) {
2297 if (pst->st_ex_size == len) {
2302 if (pst->st_ex_size > len) {
2303 /* the ftruncate should have worked */
2307 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2315 END_PROFILE(syscall_ftruncate);
2319 static int vfswrap_fallocate(vfs_handle_struct *handle,
2327 START_PROFILE(syscall_fallocate);
2329 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2331 * posix_fallocate returns 0 on success, errno on error
2332 * and doesn't set errno. Make it behave like fallocate()
2333 * which returns -1, and sets errno on failure.
2340 /* sys_fallocate handles filtering of unsupported mode flags */
2341 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2343 END_PROFILE(syscall_fallocate);
2347 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2351 START_PROFILE(syscall_fcntl_lock);
2353 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2355 "force process locks",
2357 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2360 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2361 END_PROFILE(syscall_fcntl_lock);
2365 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2366 uint32_t share_mode, uint32_t access_mask)
2368 START_PROFILE(syscall_kernel_flock);
2369 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2370 END_PROFILE(syscall_kernel_flock);
2374 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2379 START_PROFILE(syscall_fcntl_getlock);
2381 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2383 "force process locks",
2385 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2388 result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2389 END_PROFILE(syscall_fcntl_getlock);
2393 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2398 START_PROFILE(syscall_linux_setlease);
2400 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2401 result = linux_setlease(fsp->fh->fd, leasetype);
2405 END_PROFILE(syscall_linux_setlease);
2409 static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2413 START_PROFILE(syscall_symlink);
2414 result = symlink(oldpath, newpath);
2415 END_PROFILE(syscall_symlink);
2419 static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
2423 START_PROFILE(syscall_readlink);
2424 result = readlink(path, buf, bufsiz);
2425 END_PROFILE(syscall_readlink);
2429 static int vfswrap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2433 START_PROFILE(syscall_link);
2434 result = link(oldpath, newpath);
2435 END_PROFILE(syscall_link);
2439 static int vfswrap_mknod(vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev)
2443 START_PROFILE(syscall_mknod);
2444 result = sys_mknod(pathname, mode, dev);
2445 END_PROFILE(syscall_mknod);
2449 static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
2453 START_PROFILE(syscall_realpath);
2454 result = sys_realpath(path);
2455 END_PROFILE(syscall_realpath);
2459 static int vfswrap_chflags(vfs_handle_struct *handle, const char *path,
2463 return chflags(path, flags);
2470 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2471 const SMB_STRUCT_STAT *sbuf)
2475 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2479 key.devid = sbuf->st_ex_dev;
2480 key.inode = sbuf->st_ex_ino;
2481 /* key.extid is unused by default. */
2486 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2487 struct files_struct *fsp,
2488 const struct smb_filename *smb_fname,
2489 TALLOC_CTX *mem_ctx,
2490 unsigned int *pnum_streams,
2491 struct stream_struct **pstreams)
2493 SMB_STRUCT_STAT sbuf;
2494 struct stream_struct *tmp_streams = NULL;
2497 if ((fsp != NULL) && (fsp->is_directory)) {
2499 * No default streams on directories
2504 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2505 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2508 struct smb_filename smb_fname_cp;
2510 ZERO_STRUCT(smb_fname_cp);
2511 smb_fname_cp.base_name = discard_const_p(char,
2512 smb_fname->base_name);
2513 smb_fname_cp.flags = smb_fname->flags;
2515 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
2516 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2518 ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2520 sbuf = smb_fname_cp.st;
2524 return map_nt_error_from_unix(errno);
2527 if (S_ISDIR(sbuf.st_ex_mode)) {
2531 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2532 (*pnum_streams) + 1);
2533 if (tmp_streams == NULL) {
2534 return NT_STATUS_NO_MEMORY;
2536 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2537 if (tmp_streams[*pnum_streams].name == NULL) {
2538 return NT_STATUS_NO_MEMORY;
2540 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2541 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2544 *pstreams = tmp_streams;
2546 return NT_STATUS_OK;
2549 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2552 TALLOC_CTX *mem_ctx,
2556 * Don't fall back to get_real_filename so callers can differentiate
2557 * between a full directory scan and an actual case-insensitive stat.
2563 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2566 return handle->conn->connectpath;
2569 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2570 struct byte_range_lock *br_lck,
2571 struct lock_struct *plock,
2574 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2576 /* Note: blr is not used in the default implementation. */
2577 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2580 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2581 struct messaging_context *msg_ctx,
2582 struct byte_range_lock *br_lck,
2583 const struct lock_struct *plock)
2585 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2587 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2590 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2591 struct byte_range_lock *br_lck,
2592 struct lock_struct *plock)
2594 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2596 /* Note: blr is not used in the default implementation. */
2597 return brl_lock_cancel_default(br_lck, plock);
2600 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2602 struct lock_struct *plock)
2604 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2605 plock->lock_type == WRITE_LOCK);
2607 return strict_lock_default(fsp, plock);
2610 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2612 struct lock_struct *plock)
2614 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2615 plock->lock_type == WRITE_LOCK);
2617 strict_unlock_default(fsp, plock);
2620 /* NT ACL operations. */
2622 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2624 uint32_t security_info,
2625 TALLOC_CTX *mem_ctx,
2626 struct security_descriptor **ppdesc)
2630 START_PROFILE(fget_nt_acl);
2631 result = posix_fget_nt_acl(fsp, security_info,
2633 END_PROFILE(fget_nt_acl);
2637 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2638 const struct smb_filename *smb_fname,
2639 uint32_t security_info,
2640 TALLOC_CTX *mem_ctx,
2641 struct security_descriptor **ppdesc)
2645 START_PROFILE(get_nt_acl);
2646 result = posix_get_nt_acl(handle->conn,
2651 END_PROFILE(get_nt_acl);
2655 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2659 START_PROFILE(fset_nt_acl);
2660 result = set_nt_acl(fsp, security_info_sent, psd);
2661 END_PROFILE(fset_nt_acl);
2665 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2666 struct smb_filename *file,
2667 struct security_acl *sacl,
2668 uint32_t access_requested,
2669 uint32_t access_denied)
2671 return NT_STATUS_OK; /* Nothing to do here ... */
2674 static int vfswrap_chmod_acl(vfs_handle_struct *handle,
2675 const struct smb_filename *smb_fname,
2684 START_PROFILE(chmod_acl);
2685 result = chmod_acl(handle->conn, smb_fname->base_name, mode);
2686 END_PROFILE(chmod_acl);
2691 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2699 START_PROFILE(fchmod_acl);
2700 result = fchmod_acl(fsp, mode);
2701 END_PROFILE(fchmod_acl);
2706 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2708 SMB_ACL_TYPE_T type,
2709 TALLOC_CTX *mem_ctx)
2711 return sys_acl_get_file(handle, path_p, type, mem_ctx);
2714 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2716 TALLOC_CTX *mem_ctx)
2718 return sys_acl_get_fd(handle, fsp, mem_ctx);
2721 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2723 return sys_acl_set_file(handle, name, acltype, theacl);
2726 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2728 return sys_acl_set_fd(handle, fsp, theacl);
2731 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
2733 return sys_acl_delete_def_file(handle, path);
2736 /****************************************************************
2737 Extended attribute operations.
2738 *****************************************************************/
2740 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
2742 return getxattr(path, name, value, size);
2745 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2747 return fgetxattr(fsp->fh->fd, name, value, size);
2750 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
2752 return listxattr(path, list, size);
2755 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2757 return flistxattr(fsp->fh->fd, list, size);
2760 static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
2762 return removexattr(path, name);
2765 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2767 return fremovexattr(fsp->fh->fd, name);
2770 static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
2772 return setxattr(path, name, value, size, flags);
2775 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2777 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2780 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2785 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2786 const struct smb_filename *fname,
2787 SMB_STRUCT_STAT *sbuf)
2791 bool offline = false;
2793 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2797 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2798 #if defined(ENOTSUP)
2804 status = get_full_smb_filename(talloc_tos(), fname, &path);
2805 if (!NT_STATUS_IS_OK(status)) {
2806 errno = map_errno_from_nt_status(status);
2810 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2817 static int vfswrap_set_offline(struct vfs_handle_struct *handle,
2818 const struct smb_filename *fname)
2820 /* We don't know how to set offline bit by default, needs to be overriden in the vfs modules */
2821 #if defined(ENOTSUP)
2827 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2828 struct files_struct *fsp,
2829 TALLOC_CTX *mem_ctx,
2832 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2835 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2836 struct files_struct *fsp,
2837 const DATA_BLOB old_cookie,
2838 TALLOC_CTX *mem_ctx,
2839 DATA_BLOB *new_cookie)
2841 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2845 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2846 struct smb_request *smb1req,
2847 struct smbXsrv_open *op,
2848 const DATA_BLOB old_cookie,
2849 TALLOC_CTX *mem_ctx,
2850 struct files_struct **fsp,
2851 DATA_BLOB *new_cookie)
2853 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2854 old_cookie, mem_ctx,
2858 static struct vfs_fn_pointers vfs_default_fns = {
2859 /* Disk operations */
2861 .connect_fn = vfswrap_connect,
2862 .disconnect_fn = vfswrap_disconnect,
2863 .disk_free_fn = vfswrap_disk_free,
2864 .get_quota_fn = vfswrap_get_quota,
2865 .set_quota_fn = vfswrap_set_quota,
2866 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2867 .statvfs_fn = vfswrap_statvfs,
2868 .fs_capabilities_fn = vfswrap_fs_capabilities,
2869 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2870 .snap_check_path_fn = vfswrap_snap_check_path,
2871 .snap_create_fn = vfswrap_snap_create,
2872 .snap_delete_fn = vfswrap_snap_delete,
2874 /* Directory operations */
2876 .opendir_fn = vfswrap_opendir,
2877 .fdopendir_fn = vfswrap_fdopendir,
2878 .readdir_fn = vfswrap_readdir,
2879 .readdir_attr_fn = vfswrap_readdir_attr,
2880 .seekdir_fn = vfswrap_seekdir,
2881 .telldir_fn = vfswrap_telldir,
2882 .rewind_dir_fn = vfswrap_rewinddir,
2883 .mkdir_fn = vfswrap_mkdir,
2884 .rmdir_fn = vfswrap_rmdir,
2885 .closedir_fn = vfswrap_closedir,
2886 .init_search_op_fn = vfswrap_init_search_op,
2888 /* File operations */
2890 .open_fn = vfswrap_open,
2891 .create_file_fn = vfswrap_create_file,
2892 .close_fn = vfswrap_close,
2893 .read_fn = vfswrap_read,
2894 .pread_fn = vfswrap_pread,
2895 .pread_send_fn = vfswrap_pread_send,
2896 .pread_recv_fn = vfswrap_pread_recv,
2897 .write_fn = vfswrap_write,
2898 .pwrite_fn = vfswrap_pwrite,
2899 .pwrite_send_fn = vfswrap_pwrite_send,
2900 .pwrite_recv_fn = vfswrap_pwrite_recv,
2901 .lseek_fn = vfswrap_lseek,
2902 .sendfile_fn = vfswrap_sendfile,
2903 .recvfile_fn = vfswrap_recvfile,
2904 .rename_fn = vfswrap_rename,
2905 .fsync_fn = vfswrap_fsync,
2906 .fsync_send_fn = vfswrap_fsync_send,
2907 .fsync_recv_fn = vfswrap_fsync_recv,
2908 .stat_fn = vfswrap_stat,
2909 .fstat_fn = vfswrap_fstat,
2910 .lstat_fn = vfswrap_lstat,
2911 .get_alloc_size_fn = vfswrap_get_alloc_size,
2912 .unlink_fn = vfswrap_unlink,
2913 .chmod_fn = vfswrap_chmod,
2914 .fchmod_fn = vfswrap_fchmod,
2915 .chown_fn = vfswrap_chown,
2916 .fchown_fn = vfswrap_fchown,
2917 .lchown_fn = vfswrap_lchown,
2918 .chdir_fn = vfswrap_chdir,
2919 .getwd_fn = vfswrap_getwd,
2920 .ntimes_fn = vfswrap_ntimes,
2921 .ftruncate_fn = vfswrap_ftruncate,
2922 .fallocate_fn = vfswrap_fallocate,
2923 .lock_fn = vfswrap_lock,
2924 .kernel_flock_fn = vfswrap_kernel_flock,
2925 .linux_setlease_fn = vfswrap_linux_setlease,
2926 .getlock_fn = vfswrap_getlock,
2927 .symlink_fn = vfswrap_symlink,
2928 .readlink_fn = vfswrap_readlink,
2929 .link_fn = vfswrap_link,
2930 .mknod_fn = vfswrap_mknod,
2931 .realpath_fn = vfswrap_realpath,
2932 .chflags_fn = vfswrap_chflags,
2933 .file_id_create_fn = vfswrap_file_id_create,
2934 .streaminfo_fn = vfswrap_streaminfo,
2935 .get_real_filename_fn = vfswrap_get_real_filename,
2936 .connectpath_fn = vfswrap_connectpath,
2937 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2938 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2939 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2940 .strict_lock_fn = vfswrap_strict_lock,
2941 .strict_unlock_fn = vfswrap_strict_unlock,
2942 .translate_name_fn = vfswrap_translate_name,
2943 .fsctl_fn = vfswrap_fsctl,
2944 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
2945 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
2946 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
2947 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
2948 .copy_chunk_send_fn = vfswrap_copy_chunk_send,
2949 .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
2950 .get_compression_fn = vfswrap_get_compression,
2951 .set_compression_fn = vfswrap_set_compression,
2953 /* NT ACL operations. */
2955 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2956 .get_nt_acl_fn = vfswrap_get_nt_acl,
2957 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2958 .audit_file_fn = vfswrap_audit_file,
2960 /* POSIX ACL operations. */
2962 .chmod_acl_fn = vfswrap_chmod_acl,
2963 .fchmod_acl_fn = vfswrap_fchmod_acl,
2965 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2966 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2967 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2968 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2969 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2970 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2971 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2973 /* EA operations. */
2974 .getxattr_fn = vfswrap_getxattr,
2975 .fgetxattr_fn = vfswrap_fgetxattr,
2976 .listxattr_fn = vfswrap_listxattr,
2977 .flistxattr_fn = vfswrap_flistxattr,
2978 .removexattr_fn = vfswrap_removexattr,
2979 .fremovexattr_fn = vfswrap_fremovexattr,
2980 .setxattr_fn = vfswrap_setxattr,
2981 .fsetxattr_fn = vfswrap_fsetxattr,
2983 /* aio operations */
2984 .aio_force_fn = vfswrap_aio_force,
2986 /* offline operations */
2987 .is_offline_fn = vfswrap_is_offline,
2988 .set_offline_fn = vfswrap_set_offline,
2990 /* durable handle operations */
2991 .durable_cookie_fn = vfswrap_durable_cookie,
2992 .durable_disconnect_fn = vfswrap_durable_disconnect,
2993 .durable_reconnect_fn = vfswrap_durable_reconnect,
2996 NTSTATUS vfs_default_init(void);
2997 NTSTATUS vfs_default_init(void)
2999 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3000 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);