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 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
901 struct tevent_context *ev,
902 struct files_struct *fsp,
904 size_t n, off_t offset)
906 struct tevent_req *req;
907 struct vfswrap_asys_state *state;
910 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
914 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
916 return tevent_req_post(req, ev);
918 state->asys_ctx = handle->conn->sconn->asys_ctx;
921 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
922 state->profile_bytes, n);
923 ret = asys_pwrite(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
925 tevent_req_error(req, ret);
926 return tevent_req_post(req, ev);
928 talloc_set_destructor(state, vfswrap_asys_state_destructor);
933 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
935 struct tevent_context *ev,
936 struct files_struct *fsp)
938 struct tevent_req *req;
939 struct vfswrap_asys_state *state;
942 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
946 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
948 return tevent_req_post(req, ev);
950 state->asys_ctx = handle->conn->sconn->asys_ctx;
953 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
954 state->profile_basic);
955 ret = asys_fsync(state->asys_ctx, fsp->fh->fd, req);
957 tevent_req_error(req, ret);
958 return tevent_req_post(req, ev);
960 talloc_set_destructor(state, vfswrap_asys_state_destructor);
965 static void vfswrap_asys_finished(struct tevent_context *ev,
966 struct tevent_fd *fde,
967 uint16_t flags, void *p)
969 struct asys_context *asys_ctx = (struct asys_context *)p;
970 struct asys_result results[get_outstanding_aio_calls()];
973 if ((flags & TEVENT_FD_READ) == 0) {
977 ret = asys_results(asys_ctx, results, get_outstanding_aio_calls());
979 DEBUG(1, ("asys_results returned %s\n", strerror(-ret)));
983 for (i=0; i<ret; i++) {
984 struct asys_result *result = &results[i];
985 struct tevent_req *req;
986 struct vfswrap_asys_state *state;
988 if ((result->ret == -1) && (result->err == ECANCELED)) {
992 req = talloc_get_type_abort(result->private_data,
994 state = tevent_req_data(req, struct vfswrap_asys_state);
996 talloc_set_destructor(state, NULL);
998 SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
999 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1000 state->ret = result->ret;
1001 state->vfs_aio_state.error = result->err;
1002 state->vfs_aio_state.duration = result->duration;
1003 tevent_req_defer_callback(req, ev);
1004 tevent_req_done(req);
1008 static ssize_t vfswrap_asys_ssize_t_recv(struct tevent_req *req,
1009 struct vfs_aio_state *vfs_aio_state)
1011 struct vfswrap_asys_state *state = tevent_req_data(
1012 req, struct vfswrap_asys_state);
1014 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1017 *vfs_aio_state = state->vfs_aio_state;
1021 static int vfswrap_asys_int_recv(struct tevent_req *req,
1022 struct vfs_aio_state *vfs_aio_state)
1024 struct vfswrap_asys_state *state = tevent_req_data(
1025 req, struct vfswrap_asys_state);
1027 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1030 *vfs_aio_state = state->vfs_aio_state;
1034 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1038 START_PROFILE(syscall_lseek);
1040 /* Cope with 'stat' file opens. */
1041 if (fsp->fh->fd != -1)
1042 result = lseek(fsp->fh->fd, offset, whence);
1045 * We want to maintain the fiction that we can seek
1046 * on a fifo for file system purposes. This allows
1047 * people to set up UNIX fifo's that feed data to Windows
1048 * applications. JRA.
1051 if((result == -1) && (errno == ESPIPE)) {
1056 END_PROFILE(syscall_lseek);
1060 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1061 off_t offset, size_t n)
1065 START_PROFILE_BYTES(syscall_sendfile, n);
1066 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
1067 END_PROFILE_BYTES(syscall_sendfile);
1071 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1073 files_struct *tofsp,
1079 START_PROFILE_BYTES(syscall_recvfile, n);
1080 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
1081 END_PROFILE_BYTES(syscall_recvfile);
1085 static int vfswrap_rename(vfs_handle_struct *handle,
1086 const struct smb_filename *smb_fname_src,
1087 const struct smb_filename *smb_fname_dst)
1091 START_PROFILE(syscall_rename);
1093 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
1098 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
1101 END_PROFILE(syscall_rename);
1105 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
1110 START_PROFILE(syscall_fsync);
1111 result = fsync(fsp->fh->fd);
1112 END_PROFILE(syscall_fsync);
1119 static int vfswrap_stat(vfs_handle_struct *handle,
1120 struct smb_filename *smb_fname)
1124 START_PROFILE(syscall_stat);
1126 if (smb_fname->stream_name) {
1131 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1132 lp_fake_directory_create_times(SNUM(handle->conn)));
1134 END_PROFILE(syscall_stat);
1138 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1142 START_PROFILE(syscall_fstat);
1143 result = sys_fstat(fsp->fh->fd,
1144 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1145 END_PROFILE(syscall_fstat);
1149 static int vfswrap_lstat(vfs_handle_struct *handle,
1150 struct smb_filename *smb_fname)
1154 START_PROFILE(syscall_lstat);
1156 if (smb_fname->stream_name) {
1161 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1162 lp_fake_directory_create_times(SNUM(handle->conn)));
1164 END_PROFILE(syscall_lstat);
1168 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1170 enum vfs_translate_direction direction,
1171 TALLOC_CTX *mem_ctx,
1174 return NT_STATUS_NONE_MAPPED;
1178 * Implement the default fsctl operation.
1180 static bool vfswrap_logged_ioctl_message = false;
1182 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1183 struct files_struct *fsp,
1186 uint16_t req_flags, /* Needed for UNICODE ... */
1187 const uint8_t *_in_data,
1189 uint8_t **_out_data,
1190 uint32_t max_out_len,
1193 const char *in_data = (const char *)_in_data;
1194 char **out_data = (char **)_out_data;
1198 case FSCTL_SET_SPARSE:
1200 bool set_sparse = true;
1202 if (in_len >= 1 && in_data[0] == 0) {
1206 status = file_set_sparse(handle->conn, fsp, set_sparse);
1208 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1209 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1210 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1211 nt_errstr(status)));
1216 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1218 unsigned char objid[16];
1219 char *return_data = NULL;
1221 /* This should return the object-id on this file.
1222 * I think I'll make this be the inode+dev. JRA.
1225 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1226 fsp_fnum_dbg(fsp)));
1228 *out_len = MIN(max_out_len, 64);
1230 /* Hmmm, will this cause problems if less data asked for? */
1231 return_data = talloc_array(ctx, char, 64);
1232 if (return_data == NULL) {
1233 return NT_STATUS_NO_MEMORY;
1236 /* For backwards compatibility only store the dev/inode. */
1237 push_file_id_16(return_data, &fsp->file_id);
1238 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1239 push_file_id_16(return_data+32, &fsp->file_id);
1240 memset(return_data+48, 0, 16);
1241 *out_data = return_data;
1242 return NT_STATUS_OK;
1245 case FSCTL_GET_REPARSE_POINT:
1247 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1248 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1249 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1250 return NT_STATUS_NOT_A_REPARSE_POINT;
1253 case FSCTL_SET_REPARSE_POINT:
1255 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1256 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1257 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1258 return NT_STATUS_NOT_A_REPARSE_POINT;
1261 case FSCTL_GET_SHADOW_COPY_DATA:
1264 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1265 * and return their volume names. If max_data_count is 16, then it is just
1266 * asking for the number of volumes and length of the combined names.
1268 * pdata is the data allocated by our caller, but that uses
1269 * total_data_count (which is 0 in our case) rather than max_data_count.
1270 * Allocate the correct amount and return the pointer to let
1271 * it be deallocated when we return.
1273 struct shadow_copy_data *shadow_data = NULL;
1274 bool labels = False;
1275 uint32_t labels_data_count = 0;
1277 char *cur_pdata = NULL;
1279 if (max_out_len < 16) {
1280 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1282 return NT_STATUS_INVALID_PARAMETER;
1285 if (max_out_len > 16) {
1289 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1290 if (shadow_data == NULL) {
1291 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1292 return NT_STATUS_NO_MEMORY;
1296 * Call the VFS routine to actually do the work.
1298 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1301 /* broken module didn't set errno on error */
1302 status = NT_STATUS_UNSUCCESSFUL;
1304 status = map_nt_error_from_unix(errno);
1305 if (NT_STATUS_EQUAL(status,
1306 NT_STATUS_NOT_SUPPORTED)) {
1310 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1311 "connectpath %s, failed - %s.\n",
1312 fsp->conn->connectpath,
1313 nt_errstr(status)));
1314 TALLOC_FREE(shadow_data);
1318 labels_data_count = (shadow_data->num_volumes * 2 *
1319 sizeof(SHADOW_COPY_LABEL)) + 2;
1324 *out_len = 12 + labels_data_count;
1327 if (max_out_len < *out_len) {
1328 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1329 max_out_len, *out_len));
1330 TALLOC_FREE(shadow_data);
1331 return NT_STATUS_BUFFER_TOO_SMALL;
1334 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1335 if (cur_pdata == NULL) {
1336 TALLOC_FREE(shadow_data);
1337 return NT_STATUS_NO_MEMORY;
1340 *out_data = cur_pdata;
1342 /* num_volumes 4 bytes */
1343 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1346 /* num_labels 4 bytes */
1347 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1350 /* needed_data_count 4 bytes */
1351 SIVAL(cur_pdata, 8, labels_data_count);
1355 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1356 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1357 if (labels && shadow_data->labels) {
1358 for (i=0; i<shadow_data->num_volumes; i++) {
1360 status = srvstr_push(cur_pdata, req_flags,
1361 cur_pdata, shadow_data->labels[i],
1362 2 * sizeof(SHADOW_COPY_LABEL),
1363 STR_UNICODE|STR_TERMINATE, &len);
1364 if (!NT_STATUS_IS_OK(status)) {
1365 TALLOC_FREE(*out_data);
1366 TALLOC_FREE(shadow_data);
1369 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1370 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1374 TALLOC_FREE(shadow_data);
1376 return NT_STATUS_OK;
1379 case FSCTL_FIND_FILES_BY_SID:
1381 /* pretend this succeeded -
1383 * we have to send back a list with all files owned by this SID
1385 * but I have to check that --metze
1391 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1392 fsp_fnum_dbg(fsp)));
1395 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1396 return NT_STATUS_INVALID_PARAMETER;
1399 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1401 /* unknown 4 bytes: this is not the length of the sid :-( */
1402 /*unknown = IVAL(pdata,0);*/
1404 if (!sid_parse(_in_data + 4, sid_len, &sid)) {
1405 return NT_STATUS_INVALID_PARAMETER;
1407 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1409 if (!sid_to_uid(&sid, &uid)) {
1410 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1411 sid_string_dbg(&sid),
1412 (unsigned long)sid_len));
1416 /* we can take a look at the find source :-)
1418 * find ./ -uid $uid -name '*' is what we need here
1421 * and send 4bytes len and then NULL terminated unicode strings
1424 * but I don't know how to deal with the paged results
1425 * (maybe we can hang the result anywhere in the fsp struct)
1427 * but I don't know how to deal with the paged results
1428 * (maybe we can hang the result anywhere in the fsp struct)
1430 * we don't send all files at once
1431 * and at the next we should *not* start from the beginning,
1432 * so we have to cache the result
1437 /* this works for now... */
1438 return NT_STATUS_OK;
1441 case FSCTL_QUERY_ALLOCATED_RANGES:
1443 /* FIXME: This is just a dummy reply, telling that all of the
1444 * file is allocated. MKS cp needs that.
1445 * Adding the real allocated ranges via FIEMAP on Linux
1446 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1447 * this FSCTL correct for sparse files.
1449 uint64_t offset, length;
1450 char *out_data_tmp = NULL;
1453 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1455 return NT_STATUS_INVALID_PARAMETER;
1458 if (max_out_len < 16) {
1459 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1461 return NT_STATUS_INVALID_PARAMETER;
1464 offset = BVAL(in_data,0);
1465 length = BVAL(in_data,8);
1467 if (offset + length < offset) {
1468 /* No 64-bit integer wrap. */
1469 return NT_STATUS_INVALID_PARAMETER;
1472 /* Shouldn't this be SMB_VFS_STAT ... ? */
1473 status = vfs_stat_fsp(fsp);
1474 if (!NT_STATUS_IS_OK(status)) {
1479 out_data_tmp = talloc_array(ctx, char, *out_len);
1480 if (out_data_tmp == NULL) {
1481 DEBUG(10, ("unable to allocate memory for response\n"));
1482 return NT_STATUS_NO_MEMORY;
1485 if (offset > fsp->fsp_name->st.st_ex_size ||
1486 fsp->fsp_name->st.st_ex_size == 0 ||
1488 memset(out_data_tmp, 0, *out_len);
1490 uint64_t end = offset + length;
1491 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1492 SBVAL(out_data_tmp, 0, 0);
1493 SBVAL(out_data_tmp, 8, end);
1496 *out_data = out_data_tmp;
1498 return NT_STATUS_OK;
1501 case FSCTL_IS_VOLUME_DIRTY:
1503 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1504 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1506 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1507 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1509 return NT_STATUS_INVALID_PARAMETER;
1514 * Only print once ... unfortunately there could be lots of
1515 * different FSCTLs that are called.
1517 if (!vfswrap_logged_ioctl_message) {
1518 vfswrap_logged_ioctl_message = true;
1519 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1520 __func__, function));
1524 return NT_STATUS_NOT_SUPPORTED;
1527 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1528 struct smb_filename *smb_fname,
1531 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1534 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1535 struct files_struct *fsp,
1538 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1541 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1542 const struct smb_filename *smb_fname,
1545 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1548 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1549 struct files_struct *fsp,
1552 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1555 struct vfs_cc_state {
1560 static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *handle,
1561 TALLOC_CTX *mem_ctx,
1562 struct tevent_context *ev,
1563 struct files_struct *src_fsp,
1565 struct files_struct *dest_fsp,
1569 struct tevent_req *req;
1570 struct vfs_cc_state *vfs_cc_state;
1573 DEBUG(10, ("performing server side copy chunk of length %lu\n",
1574 (unsigned long)num));
1576 req = tevent_req_create(mem_ctx, &vfs_cc_state, struct vfs_cc_state);
1581 vfs_cc_state->buf = talloc_array(vfs_cc_state, uint8_t,
1582 MIN(num, 8*1024*1024));
1583 if (tevent_req_nomem(vfs_cc_state->buf, req)) {
1584 return tevent_req_post(req, ev);
1587 status = vfs_stat_fsp(src_fsp);
1588 if (tevent_req_nterror(req, status)) {
1589 return tevent_req_post(req, ev);
1592 if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
1594 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1595 * If the SourceOffset or SourceOffset + Length extends beyond
1596 * the end of file, the server SHOULD<240> treat this as a
1597 * STATUS_END_OF_FILE error.
1599 * <240> Section 3.3.5.15.6: Windows servers will return
1600 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1602 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1603 return tevent_req_post(req, ev);
1606 /* could use 2.6.33+ sendfile here to do this in kernel */
1607 while (vfs_cc_state->copied < num) {
1609 struct lock_struct lck;
1612 off_t this_num = MIN(talloc_array_length(vfs_cc_state->buf),
1613 num - vfs_cc_state->copied);
1615 if (src_fsp->op == NULL) {
1616 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1617 return tevent_req_post(req, ev);
1619 init_strict_lock_struct(src_fsp,
1620 src_fsp->op->global->open_persistent_id,
1626 if (!SMB_VFS_STRICT_LOCK(src_fsp->conn, src_fsp, &lck)) {
1627 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1628 return tevent_req_post(req, ev);
1631 ret = SMB_VFS_PREAD(src_fsp, vfs_cc_state->buf,
1634 saved_errno = errno;
1637 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1640 errno = saved_errno;
1641 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1642 return tevent_req_post(req, ev);
1644 if (ret != this_num) {
1645 /* zero tolerance for short reads */
1646 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1647 return tevent_req_post(req, ev);
1652 if (dest_fsp->op == NULL) {
1653 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1654 return tevent_req_post(req, ev);
1657 init_strict_lock_struct(dest_fsp,
1658 dest_fsp->op->global->open_persistent_id,
1664 if (!SMB_VFS_STRICT_LOCK(dest_fsp->conn, dest_fsp, &lck)) {
1665 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1666 return tevent_req_post(req, ev);
1669 ret = SMB_VFS_PWRITE(dest_fsp, vfs_cc_state->buf,
1670 this_num, dest_off);
1672 saved_errno = errno;
1675 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1678 errno = saved_errno;
1679 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1680 return tevent_req_post(req, ev);
1682 if (ret != this_num) {
1683 /* zero tolerance for short writes */
1684 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1685 return tevent_req_post(req, ev);
1689 vfs_cc_state->copied += this_num;
1692 tevent_req_done(req);
1693 return tevent_req_post(req, ev);
1696 static NTSTATUS vfswrap_copy_chunk_recv(struct vfs_handle_struct *handle,
1697 struct tevent_req *req,
1700 struct vfs_cc_state *vfs_cc_state = tevent_req_data(req,
1701 struct vfs_cc_state);
1704 if (tevent_req_is_nterror(req, &status)) {
1705 DEBUG(2, ("server side copy chunk failed: %s\n",
1706 nt_errstr(status)));
1708 tevent_req_received(req);
1712 *copied = vfs_cc_state->copied;
1713 DEBUG(10, ("server side copy chunk copied %lu\n",
1714 (unsigned long)*copied));
1715 tevent_req_received(req);
1717 return NT_STATUS_OK;
1720 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1721 TALLOC_CTX *mem_ctx,
1722 struct files_struct *fsp,
1723 struct smb_filename *smb_fname,
1724 uint16_t *_compression_fmt)
1726 return NT_STATUS_INVALID_DEVICE_REQUEST;
1729 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1730 TALLOC_CTX *mem_ctx,
1731 struct files_struct *fsp,
1732 uint16_t compression_fmt)
1734 return NT_STATUS_INVALID_DEVICE_REQUEST;
1737 /********************************************************************
1738 Given a stat buffer return the allocated size on disk, taking into
1739 account sparse files.
1740 ********************************************************************/
1741 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1742 struct files_struct *fsp,
1743 const SMB_STRUCT_STAT *sbuf)
1747 START_PROFILE(syscall_get_alloc_size);
1749 if(S_ISDIR(sbuf->st_ex_mode)) {
1754 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1755 /* The type of st_blocksize is blkcnt_t which *MUST* be
1756 signed (according to POSIX) and can be less than 64-bits.
1757 Ensure when we're converting to 64 bits wide we don't
1759 #if defined(SIZEOF_BLKCNT_T_8)
1760 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1761 #elif defined(SIZEOF_BLKCNT_T_4)
1763 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1764 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1767 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1771 * Some file systems do not allocate a block for very
1772 * small files. But for non-empty file should report a
1776 uint64_t filesize = get_file_size_stat(sbuf);
1778 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
1782 result = get_file_size_stat(sbuf);
1785 if (fsp && fsp->initial_allocation_size)
1786 result = MAX(result,fsp->initial_allocation_size);
1788 result = smb_roundup(handle->conn, result);
1791 END_PROFILE(syscall_get_alloc_size);
1795 static int vfswrap_unlink(vfs_handle_struct *handle,
1796 const struct smb_filename *smb_fname)
1800 START_PROFILE(syscall_unlink);
1802 if (smb_fname->stream_name) {
1806 result = unlink(smb_fname->base_name);
1809 END_PROFILE(syscall_unlink);
1813 static int vfswrap_chmod(vfs_handle_struct *handle,
1814 const struct smb_filename *smb_fname,
1819 START_PROFILE(syscall_chmod);
1822 * We need to do this due to the fact that the default POSIX ACL
1823 * chmod modifies the ACL *mask* for the group owner, not the
1824 * group owner bits directly. JRA.
1829 int saved_errno = errno; /* We might get ENOSYS */
1830 result = SMB_VFS_CHMOD_ACL(handle->conn,
1834 END_PROFILE(syscall_chmod);
1837 /* Error - return the old errno. */
1838 errno = saved_errno;
1841 result = chmod(smb_fname->base_name, mode);
1842 END_PROFILE(syscall_chmod);
1846 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
1850 START_PROFILE(syscall_fchmod);
1853 * We need to do this due to the fact that the default POSIX ACL
1854 * chmod modifies the ACL *mask* for the group owner, not the
1855 * group owner bits directly. JRA.
1859 int saved_errno = errno; /* We might get ENOSYS */
1860 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
1861 END_PROFILE(syscall_fchmod);
1864 /* Error - return the old errno. */
1865 errno = saved_errno;
1868 #if defined(HAVE_FCHMOD)
1869 result = fchmod(fsp->fh->fd, mode);
1875 END_PROFILE(syscall_fchmod);
1879 static int vfswrap_chown(vfs_handle_struct *handle,
1880 const struct smb_filename *smb_fname,
1886 START_PROFILE(syscall_chown);
1887 result = chown(smb_fname->base_name, uid, gid);
1888 END_PROFILE(syscall_chown);
1892 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
1897 START_PROFILE(syscall_fchown);
1898 result = fchown(fsp->fh->fd, uid, gid);
1899 END_PROFILE(syscall_fchown);
1907 static int vfswrap_lchown(vfs_handle_struct *handle,
1908 const struct smb_filename *smb_fname,
1914 START_PROFILE(syscall_lchown);
1915 result = lchown(smb_fname->base_name, uid, gid);
1916 END_PROFILE(syscall_lchown);
1920 static int vfswrap_chdir(vfs_handle_struct *handle, const char *path)
1924 START_PROFILE(syscall_chdir);
1925 result = chdir(path);
1926 END_PROFILE(syscall_chdir);
1930 static char *vfswrap_getwd(vfs_handle_struct *handle)
1934 START_PROFILE(syscall_getwd);
1935 result = sys_getwd();
1936 END_PROFILE(syscall_getwd);
1940 /*********************************************************************
1941 nsec timestamp resolution call. Convert down to whatever the underlying
1942 system will support.
1943 **********************************************************************/
1945 static int vfswrap_ntimes(vfs_handle_struct *handle,
1946 const struct smb_filename *smb_fname,
1947 struct smb_file_time *ft)
1951 START_PROFILE(syscall_ntimes);
1953 if (smb_fname->stream_name) {
1959 if (null_timespec(ft->atime)) {
1960 ft->atime= smb_fname->st.st_ex_atime;
1963 if (null_timespec(ft->mtime)) {
1964 ft->mtime = smb_fname->st.st_ex_mtime;
1967 if (!null_timespec(ft->create_time)) {
1968 set_create_timespec_ea(handle->conn,
1973 if ((timespec_compare(&ft->atime,
1974 &smb_fname->st.st_ex_atime) == 0) &&
1975 (timespec_compare(&ft->mtime,
1976 &smb_fname->st.st_ex_mtime) == 0)) {
1981 #if defined(HAVE_UTIMENSAT)
1983 struct timespec ts[2];
1986 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
1988 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
1990 if (!((result == -1) && (errno == ENOSYS))) {
1994 #if defined(HAVE_UTIMES)
1996 struct timeval tv[2];
1997 tv[0] = convert_timespec_to_timeval(ft->atime);
1998 tv[1] = convert_timespec_to_timeval(ft->mtime);
1999 result = utimes(smb_fname->base_name, tv);
2001 result = utimes(smb_fname->base_name, NULL);
2003 if (!((result == -1) && (errno == ENOSYS))) {
2007 #if defined(HAVE_UTIME)
2009 struct utimbuf times;
2010 times.actime = convert_timespec_to_time_t(ft->atime);
2011 times.modtime = convert_timespec_to_time_t(ft->mtime);
2012 result = utime(smb_fname->base_name, ×);
2014 result = utime(smb_fname->base_name, NULL);
2016 if (!((result == -1) && (errno == ENOSYS))) {
2024 END_PROFILE(syscall_ntimes);
2028 /*********************************************************************
2029 A version of ftruncate that will write the space on disk if strict
2031 **********************************************************************/
2033 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2035 off_t space_to_write;
2036 uint64_t space_avail;
2037 uint64_t bsize,dfree,dsize;
2040 SMB_STRUCT_STAT *pst;
2042 status = vfs_stat_fsp(fsp);
2043 if (!NT_STATUS_IS_OK(status)) {
2046 pst = &fsp->fsp_name->st;
2049 if (S_ISFIFO(pst->st_ex_mode))
2053 if (pst->st_ex_size == len)
2056 /* Shrink - just ftruncate. */
2057 if (pst->st_ex_size > len)
2058 return ftruncate(fsp->fh->fd, len);
2060 space_to_write = len - pst->st_ex_size;
2062 /* for allocation try fallocate first. This can fail on some
2063 platforms e.g. when the filesystem doesn't support it and no
2064 emulation is being done by the libc (like on AIX with JFS1). In that
2065 case we do our own emulation. fallocate implementations can
2066 return ENOTSUP or EINVAL in cases like that. */
2067 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2068 if (ret == -1 && errno == ENOSPC) {
2074 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2075 "error %d. Falling back to slow manual allocation\n", errno));
2077 /* available disk space is enough or not? */
2079 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2080 /* space_avail is 1k blocks */
2081 if (space_avail == (uint64_t)-1 ||
2082 ((uint64_t)space_to_write/1024 > space_avail) ) {
2087 /* Write out the real space on disk. */
2088 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2096 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2099 SMB_STRUCT_STAT *pst;
2103 START_PROFILE(syscall_ftruncate);
2105 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2106 result = strict_allocate_ftruncate(handle, fsp, len);
2107 END_PROFILE(syscall_ftruncate);
2111 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2112 ftruncate if the system supports it. Then I discovered that
2113 you can have some filesystems that support ftruncate
2114 expansion and some that don't! On Linux fat can't do
2115 ftruncate extend but ext2 can. */
2117 result = ftruncate(fsp->fh->fd, len);
2119 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2120 extend a file with ftruncate. Provide alternate implementation
2123 /* Do an fstat to see if the file is longer than the requested
2124 size in which case the ftruncate above should have
2125 succeeded or shorter, in which case seek to len - 1 and
2126 write 1 byte of zero */
2127 status = vfs_stat_fsp(fsp);
2128 if (!NT_STATUS_IS_OK(status)) {
2132 /* We need to update the files_struct after successful ftruncate */
2137 pst = &fsp->fsp_name->st;
2140 if (S_ISFIFO(pst->st_ex_mode)) {
2146 if (pst->st_ex_size == len) {
2151 if (pst->st_ex_size > len) {
2152 /* the ftruncate should have worked */
2156 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2164 END_PROFILE(syscall_ftruncate);
2168 static int vfswrap_fallocate(vfs_handle_struct *handle,
2176 START_PROFILE(syscall_fallocate);
2178 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2180 * posix_fallocate returns 0 on success, errno on error
2181 * and doesn't set errno. Make it behave like fallocate()
2182 * which returns -1, and sets errno on failure.
2189 /* sys_fallocate handles filtering of unsupported mode flags */
2190 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2192 END_PROFILE(syscall_fallocate);
2196 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2200 START_PROFILE(syscall_fcntl_lock);
2202 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2204 "force process locks",
2206 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2209 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2210 END_PROFILE(syscall_fcntl_lock);
2214 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2215 uint32_t share_mode, uint32_t access_mask)
2217 START_PROFILE(syscall_kernel_flock);
2218 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2219 END_PROFILE(syscall_kernel_flock);
2223 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2228 START_PROFILE(syscall_fcntl_getlock);
2230 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2232 "force process locks",
2234 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2237 result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2238 END_PROFILE(syscall_fcntl_getlock);
2242 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2247 START_PROFILE(syscall_linux_setlease);
2249 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2250 result = linux_setlease(fsp->fh->fd, leasetype);
2254 END_PROFILE(syscall_linux_setlease);
2258 static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2262 START_PROFILE(syscall_symlink);
2263 result = symlink(oldpath, newpath);
2264 END_PROFILE(syscall_symlink);
2268 static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
2272 START_PROFILE(syscall_readlink);
2273 result = readlink(path, buf, bufsiz);
2274 END_PROFILE(syscall_readlink);
2278 static int vfswrap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2282 START_PROFILE(syscall_link);
2283 result = link(oldpath, newpath);
2284 END_PROFILE(syscall_link);
2288 static int vfswrap_mknod(vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev)
2292 START_PROFILE(syscall_mknod);
2293 result = sys_mknod(pathname, mode, dev);
2294 END_PROFILE(syscall_mknod);
2298 static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
2302 START_PROFILE(syscall_realpath);
2303 result = sys_realpath(path);
2304 END_PROFILE(syscall_realpath);
2308 static int vfswrap_chflags(vfs_handle_struct *handle, const char *path,
2312 return chflags(path, flags);
2319 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2320 const SMB_STRUCT_STAT *sbuf)
2324 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2328 key.devid = sbuf->st_ex_dev;
2329 key.inode = sbuf->st_ex_ino;
2330 /* key.extid is unused by default. */
2335 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2336 struct files_struct *fsp,
2337 const struct smb_filename *smb_fname,
2338 TALLOC_CTX *mem_ctx,
2339 unsigned int *pnum_streams,
2340 struct stream_struct **pstreams)
2342 SMB_STRUCT_STAT sbuf;
2343 struct stream_struct *tmp_streams = NULL;
2346 if ((fsp != NULL) && (fsp->is_directory)) {
2348 * No default streams on directories
2353 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2354 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2357 struct smb_filename smb_fname_cp;
2359 ZERO_STRUCT(smb_fname_cp);
2360 smb_fname_cp.base_name = discard_const_p(char,
2361 smb_fname->base_name);
2362 smb_fname_cp.flags = smb_fname->flags;
2364 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
2365 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2367 ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2369 sbuf = smb_fname_cp.st;
2373 return map_nt_error_from_unix(errno);
2376 if (S_ISDIR(sbuf.st_ex_mode)) {
2380 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2381 (*pnum_streams) + 1);
2382 if (tmp_streams == NULL) {
2383 return NT_STATUS_NO_MEMORY;
2385 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2386 if (tmp_streams[*pnum_streams].name == NULL) {
2387 return NT_STATUS_NO_MEMORY;
2389 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2390 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2393 *pstreams = tmp_streams;
2395 return NT_STATUS_OK;
2398 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2401 TALLOC_CTX *mem_ctx,
2405 * Don't fall back to get_real_filename so callers can differentiate
2406 * between a full directory scan and an actual case-insensitive stat.
2412 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2415 return handle->conn->connectpath;
2418 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2419 struct byte_range_lock *br_lck,
2420 struct lock_struct *plock,
2423 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2425 /* Note: blr is not used in the default implementation. */
2426 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2429 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2430 struct messaging_context *msg_ctx,
2431 struct byte_range_lock *br_lck,
2432 const struct lock_struct *plock)
2434 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2436 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2439 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2440 struct byte_range_lock *br_lck,
2441 struct lock_struct *plock)
2443 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2445 /* Note: blr is not used in the default implementation. */
2446 return brl_lock_cancel_default(br_lck, plock);
2449 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2451 struct lock_struct *plock)
2453 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2454 plock->lock_type == WRITE_LOCK);
2456 return strict_lock_default(fsp, plock);
2459 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2461 struct lock_struct *plock)
2463 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2464 plock->lock_type == WRITE_LOCK);
2466 strict_unlock_default(fsp, plock);
2469 /* NT ACL operations. */
2471 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2473 uint32_t security_info,
2474 TALLOC_CTX *mem_ctx,
2475 struct security_descriptor **ppdesc)
2479 START_PROFILE(fget_nt_acl);
2480 result = posix_fget_nt_acl(fsp, security_info,
2482 END_PROFILE(fget_nt_acl);
2486 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2487 const struct smb_filename *smb_fname,
2488 uint32_t security_info,
2489 TALLOC_CTX *mem_ctx,
2490 struct security_descriptor **ppdesc)
2494 START_PROFILE(get_nt_acl);
2495 result = posix_get_nt_acl(handle->conn,
2500 END_PROFILE(get_nt_acl);
2504 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2508 START_PROFILE(fset_nt_acl);
2509 result = set_nt_acl(fsp, security_info_sent, psd);
2510 END_PROFILE(fset_nt_acl);
2514 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2515 struct smb_filename *file,
2516 struct security_acl *sacl,
2517 uint32_t access_requested,
2518 uint32_t access_denied)
2520 return NT_STATUS_OK; /* Nothing to do here ... */
2523 static int vfswrap_chmod_acl(vfs_handle_struct *handle,
2524 const struct smb_filename *smb_fname,
2533 START_PROFILE(chmod_acl);
2534 result = chmod_acl(handle->conn, smb_fname->base_name, mode);
2535 END_PROFILE(chmod_acl);
2540 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2548 START_PROFILE(fchmod_acl);
2549 result = fchmod_acl(fsp, mode);
2550 END_PROFILE(fchmod_acl);
2555 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2557 SMB_ACL_TYPE_T type,
2558 TALLOC_CTX *mem_ctx)
2560 return sys_acl_get_file(handle, path_p, type, mem_ctx);
2563 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2565 TALLOC_CTX *mem_ctx)
2567 return sys_acl_get_fd(handle, fsp, mem_ctx);
2570 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2572 return sys_acl_set_file(handle, name, acltype, theacl);
2575 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2577 return sys_acl_set_fd(handle, fsp, theacl);
2580 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
2582 return sys_acl_delete_def_file(handle, path);
2585 /****************************************************************
2586 Extended attribute operations.
2587 *****************************************************************/
2589 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
2591 return getxattr(path, name, value, size);
2594 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2596 return fgetxattr(fsp->fh->fd, name, value, size);
2599 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
2601 return listxattr(path, list, size);
2604 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2606 return flistxattr(fsp->fh->fd, list, size);
2609 static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
2611 return removexattr(path, name);
2614 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2616 return fremovexattr(fsp->fh->fd, name);
2619 static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
2621 return setxattr(path, name, value, size, flags);
2624 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2626 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2629 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2634 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2635 const struct smb_filename *fname,
2636 SMB_STRUCT_STAT *sbuf)
2640 bool offline = false;
2642 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2646 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2647 #if defined(ENOTSUP)
2653 status = get_full_smb_filename(talloc_tos(), fname, &path);
2654 if (!NT_STATUS_IS_OK(status)) {
2655 errno = map_errno_from_nt_status(status);
2659 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2666 static int vfswrap_set_offline(struct vfs_handle_struct *handle,
2667 const struct smb_filename *fname)
2669 /* We don't know how to set offline bit by default, needs to be overriden in the vfs modules */
2670 #if defined(ENOTSUP)
2676 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2677 struct files_struct *fsp,
2678 TALLOC_CTX *mem_ctx,
2681 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2684 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2685 struct files_struct *fsp,
2686 const DATA_BLOB old_cookie,
2687 TALLOC_CTX *mem_ctx,
2688 DATA_BLOB *new_cookie)
2690 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2694 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2695 struct smb_request *smb1req,
2696 struct smbXsrv_open *op,
2697 const DATA_BLOB old_cookie,
2698 TALLOC_CTX *mem_ctx,
2699 struct files_struct **fsp,
2700 DATA_BLOB *new_cookie)
2702 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2703 old_cookie, mem_ctx,
2707 static struct vfs_fn_pointers vfs_default_fns = {
2708 /* Disk operations */
2710 .connect_fn = vfswrap_connect,
2711 .disconnect_fn = vfswrap_disconnect,
2712 .disk_free_fn = vfswrap_disk_free,
2713 .get_quota_fn = vfswrap_get_quota,
2714 .set_quota_fn = vfswrap_set_quota,
2715 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2716 .statvfs_fn = vfswrap_statvfs,
2717 .fs_capabilities_fn = vfswrap_fs_capabilities,
2718 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2719 .snap_check_path_fn = vfswrap_snap_check_path,
2720 .snap_create_fn = vfswrap_snap_create,
2721 .snap_delete_fn = vfswrap_snap_delete,
2723 /* Directory operations */
2725 .opendir_fn = vfswrap_opendir,
2726 .fdopendir_fn = vfswrap_fdopendir,
2727 .readdir_fn = vfswrap_readdir,
2728 .readdir_attr_fn = vfswrap_readdir_attr,
2729 .seekdir_fn = vfswrap_seekdir,
2730 .telldir_fn = vfswrap_telldir,
2731 .rewind_dir_fn = vfswrap_rewinddir,
2732 .mkdir_fn = vfswrap_mkdir,
2733 .rmdir_fn = vfswrap_rmdir,
2734 .closedir_fn = vfswrap_closedir,
2735 .init_search_op_fn = vfswrap_init_search_op,
2737 /* File operations */
2739 .open_fn = vfswrap_open,
2740 .create_file_fn = vfswrap_create_file,
2741 .close_fn = vfswrap_close,
2742 .read_fn = vfswrap_read,
2743 .pread_fn = vfswrap_pread,
2744 .pread_send_fn = vfswrap_pread_send,
2745 .pread_recv_fn = vfswrap_pread_recv,
2746 .write_fn = vfswrap_write,
2747 .pwrite_fn = vfswrap_pwrite,
2748 .pwrite_send_fn = vfswrap_pwrite_send,
2749 .pwrite_recv_fn = vfswrap_asys_ssize_t_recv,
2750 .lseek_fn = vfswrap_lseek,
2751 .sendfile_fn = vfswrap_sendfile,
2752 .recvfile_fn = vfswrap_recvfile,
2753 .rename_fn = vfswrap_rename,
2754 .fsync_fn = vfswrap_fsync,
2755 .fsync_send_fn = vfswrap_fsync_send,
2756 .fsync_recv_fn = vfswrap_asys_int_recv,
2757 .stat_fn = vfswrap_stat,
2758 .fstat_fn = vfswrap_fstat,
2759 .lstat_fn = vfswrap_lstat,
2760 .get_alloc_size_fn = vfswrap_get_alloc_size,
2761 .unlink_fn = vfswrap_unlink,
2762 .chmod_fn = vfswrap_chmod,
2763 .fchmod_fn = vfswrap_fchmod,
2764 .chown_fn = vfswrap_chown,
2765 .fchown_fn = vfswrap_fchown,
2766 .lchown_fn = vfswrap_lchown,
2767 .chdir_fn = vfswrap_chdir,
2768 .getwd_fn = vfswrap_getwd,
2769 .ntimes_fn = vfswrap_ntimes,
2770 .ftruncate_fn = vfswrap_ftruncate,
2771 .fallocate_fn = vfswrap_fallocate,
2772 .lock_fn = vfswrap_lock,
2773 .kernel_flock_fn = vfswrap_kernel_flock,
2774 .linux_setlease_fn = vfswrap_linux_setlease,
2775 .getlock_fn = vfswrap_getlock,
2776 .symlink_fn = vfswrap_symlink,
2777 .readlink_fn = vfswrap_readlink,
2778 .link_fn = vfswrap_link,
2779 .mknod_fn = vfswrap_mknod,
2780 .realpath_fn = vfswrap_realpath,
2781 .chflags_fn = vfswrap_chflags,
2782 .file_id_create_fn = vfswrap_file_id_create,
2783 .streaminfo_fn = vfswrap_streaminfo,
2784 .get_real_filename_fn = vfswrap_get_real_filename,
2785 .connectpath_fn = vfswrap_connectpath,
2786 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2787 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2788 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2789 .strict_lock_fn = vfswrap_strict_lock,
2790 .strict_unlock_fn = vfswrap_strict_unlock,
2791 .translate_name_fn = vfswrap_translate_name,
2792 .fsctl_fn = vfswrap_fsctl,
2793 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
2794 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
2795 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
2796 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
2797 .copy_chunk_send_fn = vfswrap_copy_chunk_send,
2798 .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
2799 .get_compression_fn = vfswrap_get_compression,
2800 .set_compression_fn = vfswrap_set_compression,
2802 /* NT ACL operations. */
2804 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2805 .get_nt_acl_fn = vfswrap_get_nt_acl,
2806 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2807 .audit_file_fn = vfswrap_audit_file,
2809 /* POSIX ACL operations. */
2811 .chmod_acl_fn = vfswrap_chmod_acl,
2812 .fchmod_acl_fn = vfswrap_fchmod_acl,
2814 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2815 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2816 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2817 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2818 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2819 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2820 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2822 /* EA operations. */
2823 .getxattr_fn = vfswrap_getxattr,
2824 .fgetxattr_fn = vfswrap_fgetxattr,
2825 .listxattr_fn = vfswrap_listxattr,
2826 .flistxattr_fn = vfswrap_flistxattr,
2827 .removexattr_fn = vfswrap_removexattr,
2828 .fremovexattr_fn = vfswrap_fremovexattr,
2829 .setxattr_fn = vfswrap_setxattr,
2830 .fsetxattr_fn = vfswrap_fsetxattr,
2832 /* aio operations */
2833 .aio_force_fn = vfswrap_aio_force,
2835 /* offline operations */
2836 .is_offline_fn = vfswrap_is_offline,
2837 .set_offline_fn = vfswrap_set_offline,
2839 /* durable handle operations */
2840 .durable_cookie_fn = vfswrap_durable_cookie,
2841 .durable_disconnect_fn = vfswrap_durable_disconnect,
2842 .durable_reconnect_fn = vfswrap_durable_reconnect,
2845 NTSTATUS vfs_default_init(void);
2846 NTSTATUS vfs_default_init(void)
2848 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
2849 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);