2 Unix SMB/CIFS implementation.
3 Wrap disk only vfs functions to sidestep dodgy compilers.
4 Copyright (C) Tim Potter 1998
5 Copyright (C) Jeremy Allison 2007
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "system/time.h"
23 #include "system/filesys.h"
24 #include "smbd/smbd.h"
25 #include "smbd/globals.h"
27 #include "smbprofile.h"
28 #include "../libcli/security/security.h"
29 #include "passdb/lookup_sid.h"
30 #include "source3/include/msdfs.h"
31 #include "librpc/gen_ndr/ndr_dfsblobs.h"
32 #include "lib/util/tevent_unix.h"
33 #include "lib/util/tevent_ntstatus.h"
34 #include "lib/util/sys_rw.h"
35 #include "lib/pthreadpool/pthreadpool_tevent.h"
38 #define DBGC_CLASS DBGC_VFS
40 /* Check for NULL pointer parameters in vfswrap_* functions */
42 /* We don't want to have NULL function pointers lying around. Someone
43 is sure to try and execute them. These stubs are used to prevent
46 static int vfswrap_connect(vfs_handle_struct *handle, const char *service, const char *user)
48 return 0; /* Return >= 0 for success */
51 static void vfswrap_disconnect(vfs_handle_struct *handle)
57 static uint64_t vfswrap_disk_free(vfs_handle_struct *handle, const char *path,
58 uint64_t *bsize, uint64_t *dfree,
61 if (sys_fsusage(path, dfree, dsize) != 0) {
69 static int vfswrap_get_quota(struct vfs_handle_struct *handle, const char *path,
70 enum SMB_QUOTA_TYPE qtype, unid_t id,
73 #ifdef HAVE_SYS_QUOTAS
76 START_PROFILE(syscall_get_quota);
77 result = sys_get_quota(path, qtype, id, qt);
78 END_PROFILE(syscall_get_quota);
86 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
88 #ifdef HAVE_SYS_QUOTAS
91 START_PROFILE(syscall_set_quota);
92 result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
93 END_PROFILE(syscall_set_quota);
101 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
102 struct files_struct *fsp,
103 struct shadow_copy_data *shadow_copy_data,
107 return -1; /* Not implemented. */
110 static int vfswrap_statvfs(struct vfs_handle_struct *handle, const char *path, vfs_statvfs_struct *statbuf)
112 return sys_statvfs(path, statbuf);
115 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
116 enum timestamp_set_resolution *p_ts_res)
118 connection_struct *conn = handle->conn;
119 uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
120 struct smb_filename *smb_fname_cpath = NULL;
121 struct vfs_statvfs_struct statbuf;
124 ZERO_STRUCT(statbuf);
125 ret = sys_statvfs(conn->connectpath, &statbuf);
127 caps = statbuf.FsCapabilities;
130 *p_ts_res = TIMESTAMP_SET_SECONDS;
132 /* Work out what timestamp resolution we can
133 * use when setting a timestamp. */
135 smb_fname_cpath = synthetic_smb_fname(talloc_tos(), conn->connectpath,
137 if (smb_fname_cpath == NULL) {
141 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
143 TALLOC_FREE(smb_fname_cpath);
147 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
148 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
149 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
150 /* If any of the normal UNIX directory timestamps
151 * have a non-zero tv_nsec component assume
152 * we might be able to set sub-second timestamps.
153 * See what filetime set primitives we have.
155 #if defined(HAVE_UTIMENSAT)
156 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
157 #elif defined(HAVE_UTIMES)
158 /* utimes allows msec timestamps to be set. */
159 *p_ts_res = TIMESTAMP_SET_MSEC;
160 #elif defined(HAVE_UTIME)
161 /* utime only allows sec timestamps to be set. */
162 *p_ts_res = TIMESTAMP_SET_SECONDS;
165 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
167 "available on share %s, directory %s\n",
168 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
169 lp_servicename(talloc_tos(), conn->params->service),
170 conn->connectpath ));
172 TALLOC_FREE(smb_fname_cpath);
176 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
177 struct dfs_GetDFSReferral *r)
179 struct junction_map *junction = NULL;
181 bool self_referral = false;
182 char *pathnamep = NULL;
183 char *local_dfs_path = NULL;
186 uint16_t max_referral_level = r->in.req.max_referral_level;
189 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
192 /* get the junction entry */
193 if (r->in.req.servername == NULL) {
194 return NT_STATUS_NOT_FOUND;
198 * Trim pathname sent by client so it begins with only one backslash.
199 * Two backslashes confuse some dfs clients
202 local_dfs_path = talloc_strdup(r, r->in.req.servername);
203 if (local_dfs_path == NULL) {
204 return NT_STATUS_NO_MEMORY;
206 pathnamep = local_dfs_path;
207 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
208 IS_DIRECTORY_SEP(pathnamep[1])) {
212 junction = talloc_zero(r, struct junction_map);
213 if (junction == NULL) {
214 return NT_STATUS_NO_MEMORY;
217 /* The following call can change cwd. */
218 status = get_referred_path(r, pathnamep,
219 !handle->conn->sconn->using_smb2,
220 junction, &consumedcnt, &self_referral);
221 if (!NT_STATUS_IS_OK(status)) {
222 vfs_ChDir(handle->conn, handle->conn->connectpath);
225 vfs_ChDir(handle->conn, handle->conn->connectpath);
227 if (!self_referral) {
228 pathnamep[consumedcnt] = '\0';
231 dbgtext("Path %s to alternate path(s):",
233 for (i=0; i < junction->referral_count; i++) {
235 junction->referral_list[i].alternate_path);
241 if (r->in.req.max_referral_level <= 2) {
242 max_referral_level = 2;
244 if (r->in.req.max_referral_level >= 3) {
245 max_referral_level = 3;
248 r->out.resp = talloc_zero(r, struct dfs_referral_resp);
249 if (r->out.resp == NULL) {
250 return NT_STATUS_NO_MEMORY;
253 r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
254 r->out.resp->nb_referrals = junction->referral_count;
256 r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
258 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
261 r->out.resp->referral_entries = talloc_zero_array(r,
262 struct dfs_referral_type,
263 r->out.resp->nb_referrals);
264 if (r->out.resp->referral_entries == NULL) {
265 return NT_STATUS_NO_MEMORY;
268 switch (max_referral_level) {
270 for(i=0; i < junction->referral_count; i++) {
271 struct referral *ref = &junction->referral_list[i];
272 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
273 struct dfs_referral_type *t =
274 &r->out.resp->referral_entries[i];
275 struct dfs_referral_v2 *v2 = &t->referral.v2;
278 v2->size = VERSION2_REFERRAL_SIZE;
280 v2->server_type = DFS_SERVER_ROOT;
282 v2->server_type = DFS_SERVER_NON_ROOT;
285 v2->proximity = ref->proximity;
287 v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
288 if (v2->DFS_path == NULL) {
289 return NT_STATUS_NO_MEMORY;
291 v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
292 if (v2->DFS_alt_path == NULL) {
293 return NT_STATUS_NO_MEMORY;
295 v2->netw_address = talloc_strdup(mem_ctx,
296 ref->alternate_path);
297 if (v2->netw_address == NULL) {
298 return NT_STATUS_NO_MEMORY;
304 for(i=0; i < junction->referral_count; i++) {
305 struct referral *ref = &junction->referral_list[i];
306 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
307 struct dfs_referral_type *t =
308 &r->out.resp->referral_entries[i];
309 struct dfs_referral_v3 *v3 = &t->referral.v3;
310 struct dfs_normal_referral *r1 = &v3->referrals.r1;
313 v3->size = VERSION3_REFERRAL_SIZE;
315 v3->server_type = DFS_SERVER_ROOT;
317 v3->server_type = DFS_SERVER_NON_ROOT;
321 r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
322 if (r1->DFS_path == NULL) {
323 return NT_STATUS_NO_MEMORY;
325 r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
326 if (r1->DFS_alt_path == NULL) {
327 return NT_STATUS_NO_MEMORY;
329 r1->netw_address = talloc_strdup(mem_ctx,
330 ref->alternate_path);
331 if (r1->netw_address == NULL) {
332 return NT_STATUS_NO_MEMORY;
337 DEBUG(0,("Invalid dfs referral version: %d\n",
338 max_referral_level));
339 return NT_STATUS_INVALID_LEVEL;
343 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
349 static NTSTATUS vfswrap_snap_check_path(struct vfs_handle_struct *handle,
351 const char *service_path,
354 return NT_STATUS_NOT_SUPPORTED;
357 static NTSTATUS vfswrap_snap_create(struct vfs_handle_struct *handle,
359 const char *base_volume,
365 return NT_STATUS_NOT_SUPPORTED;
368 static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle,
373 return NT_STATUS_NOT_SUPPORTED;
376 /* Directory operations */
378 static DIR *vfswrap_opendir(vfs_handle_struct *handle,
379 const struct smb_filename *smb_fname,
385 START_PROFILE(syscall_opendir);
386 result = opendir(smb_fname->base_name);
387 END_PROFILE(syscall_opendir);
391 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
398 START_PROFILE(syscall_fdopendir);
399 result = sys_fdopendir(fsp->fh->fd);
400 END_PROFILE(syscall_fdopendir);
405 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
407 SMB_STRUCT_STAT *sbuf)
409 struct dirent *result;
411 START_PROFILE(syscall_readdir);
412 result = readdir(dirp);
413 END_PROFILE(syscall_readdir);
415 /* Default Posix readdir() does not give us stat info.
416 * Set to invalid to indicate we didn't return this info. */
417 SET_STAT_INVALID(*sbuf);
418 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
419 if (result != NULL) {
420 /* See if we can efficiently return this. */
422 int flags = AT_SYMLINK_NOFOLLOW;
423 int ret = fstatat(dirfd(dirp),
428 * As this is an optimization,
429 * ignore it if we stat'ed a
430 * symlink. Make the caller
431 * do it again as we don't
432 * know if they wanted the link
433 * info, or its target info.
435 if ((ret == 0) && (!S_ISLNK(st.st_mode))) {
436 init_stat_ex_from_stat(sbuf,
438 lp_fake_directory_create_times(
439 SNUM(handle->conn)));
447 static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
448 const struct smb_filename *fname,
450 struct readdir_attr_data **attr_data)
452 return NT_STATUS_NOT_SUPPORTED;
455 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
457 START_PROFILE(syscall_seekdir);
458 seekdir(dirp, offset);
459 END_PROFILE(syscall_seekdir);
462 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
465 START_PROFILE(syscall_telldir);
466 result = telldir(dirp);
467 END_PROFILE(syscall_telldir);
471 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
473 START_PROFILE(syscall_rewinddir);
475 END_PROFILE(syscall_rewinddir);
478 static int vfswrap_mkdir(vfs_handle_struct *handle,
479 const struct smb_filename *smb_fname,
483 bool has_dacl = False;
484 const char *path = smb_fname->base_name;
487 START_PROFILE(syscall_mkdir);
489 if (lp_inherit_acls(SNUM(handle->conn))
490 && parent_dirname(talloc_tos(), path, &parent, NULL)
491 && (has_dacl = directory_has_default_acl(handle->conn, parent))) {
492 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
497 result = mkdir(path, mode);
499 if (result == 0 && !has_dacl) {
501 * We need to do this as the default behavior of POSIX ACLs
502 * is to set the mask to be the requested group permission
503 * bits, not the group permission bits to be the requested
504 * group permission bits. This is not what we want, as it will
505 * mess up any inherited ACL bits that were set. JRA.
507 int saved_errno = errno; /* We may get ENOSYS */
508 if ((SMB_VFS_CHMOD_ACL(handle->conn, smb_fname, mode) == -1) &&
514 END_PROFILE(syscall_mkdir);
518 static int vfswrap_rmdir(vfs_handle_struct *handle,
519 const struct smb_filename *smb_fname)
523 START_PROFILE(syscall_rmdir);
524 result = rmdir(smb_fname->base_name);
525 END_PROFILE(syscall_rmdir);
529 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
533 START_PROFILE(syscall_closedir);
534 result = closedir(dirp);
535 END_PROFILE(syscall_closedir);
539 static void vfswrap_init_search_op(vfs_handle_struct *handle,
542 /* Default behavior is a NOOP */
545 /* File operations */
547 static int vfswrap_open(vfs_handle_struct *handle,
548 struct smb_filename *smb_fname,
549 files_struct *fsp, int flags, mode_t mode)
553 START_PROFILE(syscall_open);
555 if (smb_fname->stream_name) {
560 result = open(smb_fname->base_name, flags, mode);
562 END_PROFILE(syscall_open);
566 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
567 struct smb_request *req,
568 uint16_t root_dir_fid,
569 struct smb_filename *smb_fname,
570 uint32_t access_mask,
571 uint32_t share_access,
572 uint32_t create_disposition,
573 uint32_t create_options,
574 uint32_t file_attributes,
575 uint32_t oplock_request,
576 struct smb2_lease *lease,
577 uint64_t allocation_size,
578 uint32_t private_flags,
579 struct security_descriptor *sd,
580 struct ea_list *ea_list,
581 files_struct **result,
583 const struct smb2_create_blobs *in_context_blobs,
584 struct smb2_create_blobs *out_context_blobs)
586 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
587 access_mask, share_access,
588 create_disposition, create_options,
589 file_attributes, oplock_request, lease,
590 allocation_size, private_flags,
592 pinfo, in_context_blobs, out_context_blobs);
595 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
599 START_PROFILE(syscall_close);
600 result = fd_close_posix(fsp);
601 END_PROFILE(syscall_close);
605 static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
609 START_PROFILE_BYTES(syscall_read, n);
610 result = sys_read(fsp->fh->fd, data, n);
611 END_PROFILE_BYTES(syscall_read);
615 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
616 size_t n, off_t offset)
620 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
621 START_PROFILE_BYTES(syscall_pread, n);
622 result = sys_pread(fsp->fh->fd, data, n, offset);
623 END_PROFILE_BYTES(syscall_pread);
625 if (result == -1 && errno == ESPIPE) {
626 /* Maintain the fiction that pipes can be seeked (sought?) on. */
627 result = SMB_VFS_READ(fsp, data, n);
631 #else /* HAVE_PREAD */
635 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
636 if (curr == -1 && errno == ESPIPE) {
637 /* Maintain the fiction that pipes can be seeked (sought?) on. */
638 result = SMB_VFS_READ(fsp, data, n);
643 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
648 result = SMB_VFS_READ(fsp, data, n);
651 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
654 #endif /* HAVE_PREAD */
659 static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
663 START_PROFILE_BYTES(syscall_write, n);
664 result = sys_write(fsp->fh->fd, data, n);
665 END_PROFILE_BYTES(syscall_write);
669 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
670 size_t n, off_t offset)
674 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
675 START_PROFILE_BYTES(syscall_pwrite, n);
676 result = sys_pwrite(fsp->fh->fd, data, n, offset);
677 END_PROFILE_BYTES(syscall_pwrite);
679 if (result == -1 && errno == ESPIPE) {
680 /* Maintain the fiction that pipes can be sought on. */
681 result = SMB_VFS_WRITE(fsp, data, n);
684 #else /* HAVE_PWRITE */
688 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
693 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
697 result = SMB_VFS_WRITE(fsp, data, n);
700 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
703 #endif /* HAVE_PWRITE */
708 static int vfswrap_init_pool(struct smbd_server_connection *conn)
712 if (conn->pool != NULL) {
716 ret = pthreadpool_tevent_init(conn, lp_aio_max_threads(),
721 struct vfswrap_pread_state {
729 struct vfs_aio_state vfs_aio_state;
730 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
733 static void vfs_pread_do(void *private_data);
734 static void vfs_pread_done(struct tevent_req *subreq);
736 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
738 struct tevent_context *ev,
739 struct files_struct *fsp,
741 size_t n, off_t offset)
743 struct tevent_req *req, *subreq;
744 struct vfswrap_pread_state *state;
747 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
752 ret = vfswrap_init_pool(handle->conn->sconn);
753 if (tevent_req_error(req, ret)) {
754 return tevent_req_post(req, ev);
758 state->fd = fsp->fh->fd;
761 state->offset = offset;
763 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
764 state->profile_bytes, n);
765 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
767 subreq = pthreadpool_tevent_job_send(
768 state, ev, handle->conn->sconn->pool,
769 vfs_pread_do, state);
770 if (tevent_req_nomem(subreq, req)) {
771 return tevent_req_post(req, ev);
773 tevent_req_set_callback(subreq, vfs_pread_done, req);
778 static void vfs_pread_do(void *private_data)
780 struct vfswrap_pread_state *state = talloc_get_type_abort(
781 private_data, struct vfswrap_pread_state);
782 struct timespec start_time;
783 struct timespec end_time;
785 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
787 PROFILE_TIMESTAMP(&start_time);
790 state->ret = pread(state->fd, state->buf, state->count,
792 } while ((state->ret == -1) && (errno == EINTR));
796 PROFILE_TIMESTAMP(&end_time);
798 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
800 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
803 static void vfs_pread_done(struct tevent_req *subreq)
805 struct tevent_req *req = tevent_req_callback_data(
806 subreq, struct tevent_req);
808 struct vfswrap_pread_state *state = tevent_req_data(
809 req, struct vfswrap_pread_state);
813 ret = pthreadpool_tevent_job_recv(subreq);
815 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
816 if (tevent_req_error(req, ret)) {
820 tevent_req_done(req);
823 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
824 struct vfs_aio_state *vfs_aio_state)
826 struct vfswrap_pread_state *state = tevent_req_data(
827 req, struct vfswrap_pread_state);
829 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
833 *vfs_aio_state = state->vfs_aio_state;
837 struct vfswrap_pwrite_state {
845 struct vfs_aio_state vfs_aio_state;
846 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
849 static void vfs_pwrite_do(void *private_data);
850 static void vfs_pwrite_done(struct tevent_req *subreq);
852 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
854 struct tevent_context *ev,
855 struct files_struct *fsp,
857 size_t n, off_t offset)
859 struct tevent_req *req, *subreq;
860 struct vfswrap_pwrite_state *state;
863 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
868 ret = vfswrap_init_pool(handle->conn->sconn);
869 if (tevent_req_error(req, ret)) {
870 return tevent_req_post(req, ev);
874 state->fd = fsp->fh->fd;
877 state->offset = offset;
879 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
880 state->profile_bytes, n);
881 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
883 subreq = pthreadpool_tevent_job_send(
884 state, ev, handle->conn->sconn->pool,
885 vfs_pwrite_do, state);
886 if (tevent_req_nomem(subreq, req)) {
887 return tevent_req_post(req, ev);
889 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
894 static void vfs_pwrite_do(void *private_data)
896 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
897 private_data, struct vfswrap_pwrite_state);
898 struct timespec start_time;
899 struct timespec end_time;
901 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
903 PROFILE_TIMESTAMP(&start_time);
906 state->ret = pwrite(state->fd, state->buf, state->count,
908 } while ((state->ret == -1) && (errno == EINTR));
912 PROFILE_TIMESTAMP(&end_time);
914 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
916 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
919 static void vfs_pwrite_done(struct tevent_req *subreq)
921 struct tevent_req *req = tevent_req_callback_data(
922 subreq, struct tevent_req);
924 struct vfswrap_pwrite_state *state = tevent_req_data(
925 req, struct vfswrap_pwrite_state);
929 ret = pthreadpool_tevent_job_recv(subreq);
931 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
932 if (tevent_req_error(req, ret)) {
936 tevent_req_done(req);
939 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
940 struct vfs_aio_state *vfs_aio_state)
942 struct vfswrap_pwrite_state *state = tevent_req_data(
943 req, struct vfswrap_pwrite_state);
945 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
949 *vfs_aio_state = state->vfs_aio_state;
953 struct vfswrap_fsync_state {
958 struct vfs_aio_state vfs_aio_state;
959 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
962 static void vfs_fsync_do(void *private_data);
963 static void vfs_fsync_done(struct tevent_req *subreq);
965 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
967 struct tevent_context *ev,
968 struct files_struct *fsp)
970 struct tevent_req *req, *subreq;
971 struct vfswrap_fsync_state *state;
974 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
979 ret = vfswrap_init_pool(handle->conn->sconn);
980 if (tevent_req_error(req, ret)) {
981 return tevent_req_post(req, ev);
985 state->fd = fsp->fh->fd;
987 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
988 state->profile_basic);
990 subreq = pthreadpool_tevent_job_send(
991 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
992 if (tevent_req_nomem(subreq, req)) {
993 return tevent_req_post(req, ev);
995 tevent_req_set_callback(subreq, vfs_fsync_done, req);
1000 static void vfs_fsync_do(void *private_data)
1002 struct vfswrap_fsync_state *state = talloc_get_type_abort(
1003 private_data, struct vfswrap_fsync_state);
1004 struct timespec start_time;
1005 struct timespec end_time;
1007 PROFILE_TIMESTAMP(&start_time);
1010 state->ret = fsync(state->fd);
1011 } while ((state->ret == -1) && (errno == EINTR));
1015 PROFILE_TIMESTAMP(&end_time);
1017 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1020 static void vfs_fsync_done(struct tevent_req *subreq)
1022 struct tevent_req *req = tevent_req_callback_data(
1023 subreq, struct tevent_req);
1025 struct vfswrap_fsync_state *state = tevent_req_data(
1026 req, struct vfswrap_fsync_state);
1030 ret = pthreadpool_tevent_job_recv(subreq);
1031 TALLOC_FREE(subreq);
1032 SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
1033 if (tevent_req_error(req, ret)) {
1037 tevent_req_done(req);
1040 static int vfswrap_fsync_recv(struct tevent_req *req,
1041 struct vfs_aio_state *vfs_aio_state)
1043 struct vfswrap_fsync_state *state = tevent_req_data(
1044 req, struct vfswrap_fsync_state);
1046 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1050 *vfs_aio_state = state->vfs_aio_state;
1054 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1058 START_PROFILE(syscall_lseek);
1060 /* Cope with 'stat' file opens. */
1061 if (fsp->fh->fd != -1)
1062 result = lseek(fsp->fh->fd, offset, whence);
1065 * We want to maintain the fiction that we can seek
1066 * on a fifo for file system purposes. This allows
1067 * people to set up UNIX fifo's that feed data to Windows
1068 * applications. JRA.
1071 if((result == -1) && (errno == ESPIPE)) {
1076 END_PROFILE(syscall_lseek);
1080 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1081 off_t offset, size_t n)
1085 START_PROFILE_BYTES(syscall_sendfile, n);
1086 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
1087 END_PROFILE_BYTES(syscall_sendfile);
1091 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1093 files_struct *tofsp,
1099 START_PROFILE_BYTES(syscall_recvfile, n);
1100 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
1101 END_PROFILE_BYTES(syscall_recvfile);
1105 static int vfswrap_rename(vfs_handle_struct *handle,
1106 const struct smb_filename *smb_fname_src,
1107 const struct smb_filename *smb_fname_dst)
1111 START_PROFILE(syscall_rename);
1113 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
1118 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
1121 END_PROFILE(syscall_rename);
1125 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
1130 START_PROFILE(syscall_fsync);
1131 result = fsync(fsp->fh->fd);
1132 END_PROFILE(syscall_fsync);
1139 static int vfswrap_stat(vfs_handle_struct *handle,
1140 struct smb_filename *smb_fname)
1144 START_PROFILE(syscall_stat);
1146 if (smb_fname->stream_name) {
1151 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1152 lp_fake_directory_create_times(SNUM(handle->conn)));
1154 END_PROFILE(syscall_stat);
1158 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1162 START_PROFILE(syscall_fstat);
1163 result = sys_fstat(fsp->fh->fd,
1164 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1165 END_PROFILE(syscall_fstat);
1169 static int vfswrap_lstat(vfs_handle_struct *handle,
1170 struct smb_filename *smb_fname)
1174 START_PROFILE(syscall_lstat);
1176 if (smb_fname->stream_name) {
1181 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1182 lp_fake_directory_create_times(SNUM(handle->conn)));
1184 END_PROFILE(syscall_lstat);
1188 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1190 enum vfs_translate_direction direction,
1191 TALLOC_CTX *mem_ctx,
1194 return NT_STATUS_NONE_MAPPED;
1198 * Implement the default fsctl operation.
1200 static bool vfswrap_logged_ioctl_message = false;
1202 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1203 struct files_struct *fsp,
1206 uint16_t req_flags, /* Needed for UNICODE ... */
1207 const uint8_t *_in_data,
1209 uint8_t **_out_data,
1210 uint32_t max_out_len,
1213 const char *in_data = (const char *)_in_data;
1214 char **out_data = (char **)_out_data;
1218 case FSCTL_SET_SPARSE:
1220 bool set_sparse = true;
1222 if (in_len >= 1 && in_data[0] == 0) {
1226 status = file_set_sparse(handle->conn, fsp, set_sparse);
1228 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1229 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1230 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1231 nt_errstr(status)));
1236 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1238 unsigned char objid[16];
1239 char *return_data = NULL;
1241 /* This should return the object-id on this file.
1242 * I think I'll make this be the inode+dev. JRA.
1245 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1246 fsp_fnum_dbg(fsp)));
1248 *out_len = MIN(max_out_len, 64);
1250 /* Hmmm, will this cause problems if less data asked for? */
1251 return_data = talloc_array(ctx, char, 64);
1252 if (return_data == NULL) {
1253 return NT_STATUS_NO_MEMORY;
1256 /* For backwards compatibility only store the dev/inode. */
1257 push_file_id_16(return_data, &fsp->file_id);
1258 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1259 push_file_id_16(return_data+32, &fsp->file_id);
1260 memset(return_data+48, 0, 16);
1261 *out_data = return_data;
1262 return NT_STATUS_OK;
1265 case FSCTL_GET_REPARSE_POINT:
1267 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1268 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1269 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1270 return NT_STATUS_NOT_A_REPARSE_POINT;
1273 case FSCTL_SET_REPARSE_POINT:
1275 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1276 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1277 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1278 return NT_STATUS_NOT_A_REPARSE_POINT;
1281 case FSCTL_GET_SHADOW_COPY_DATA:
1284 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1285 * and return their volume names. If max_data_count is 16, then it is just
1286 * asking for the number of volumes and length of the combined names.
1288 * pdata is the data allocated by our caller, but that uses
1289 * total_data_count (which is 0 in our case) rather than max_data_count.
1290 * Allocate the correct amount and return the pointer to let
1291 * it be deallocated when we return.
1293 struct shadow_copy_data *shadow_data = NULL;
1294 bool labels = False;
1295 uint32_t labels_data_count = 0;
1297 char *cur_pdata = NULL;
1299 if (max_out_len < 16) {
1300 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1302 return NT_STATUS_INVALID_PARAMETER;
1305 if (max_out_len > 16) {
1309 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1310 if (shadow_data == NULL) {
1311 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1312 return NT_STATUS_NO_MEMORY;
1316 * Call the VFS routine to actually do the work.
1318 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1321 /* broken module didn't set errno on error */
1322 status = NT_STATUS_UNSUCCESSFUL;
1324 status = map_nt_error_from_unix(errno);
1325 if (NT_STATUS_EQUAL(status,
1326 NT_STATUS_NOT_SUPPORTED)) {
1330 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1331 "connectpath %s, failed - %s.\n",
1332 fsp->conn->connectpath,
1333 nt_errstr(status)));
1334 TALLOC_FREE(shadow_data);
1338 labels_data_count = (shadow_data->num_volumes * 2 *
1339 sizeof(SHADOW_COPY_LABEL)) + 2;
1344 *out_len = 12 + labels_data_count;
1347 if (max_out_len < *out_len) {
1348 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1349 max_out_len, *out_len));
1350 TALLOC_FREE(shadow_data);
1351 return NT_STATUS_BUFFER_TOO_SMALL;
1354 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1355 if (cur_pdata == NULL) {
1356 TALLOC_FREE(shadow_data);
1357 return NT_STATUS_NO_MEMORY;
1360 *out_data = cur_pdata;
1362 /* num_volumes 4 bytes */
1363 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1366 /* num_labels 4 bytes */
1367 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1370 /* needed_data_count 4 bytes */
1371 SIVAL(cur_pdata, 8, labels_data_count);
1375 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1376 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1377 if (labels && shadow_data->labels) {
1378 for (i=0; i<shadow_data->num_volumes; i++) {
1380 status = srvstr_push(cur_pdata, req_flags,
1381 cur_pdata, shadow_data->labels[i],
1382 2 * sizeof(SHADOW_COPY_LABEL),
1383 STR_UNICODE|STR_TERMINATE, &len);
1384 if (!NT_STATUS_IS_OK(status)) {
1385 TALLOC_FREE(*out_data);
1386 TALLOC_FREE(shadow_data);
1389 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1390 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1394 TALLOC_FREE(shadow_data);
1396 return NT_STATUS_OK;
1399 case FSCTL_FIND_FILES_BY_SID:
1401 /* pretend this succeeded -
1403 * we have to send back a list with all files owned by this SID
1405 * but I have to check that --metze
1411 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1412 fsp_fnum_dbg(fsp)));
1415 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1416 return NT_STATUS_INVALID_PARAMETER;
1419 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1421 /* unknown 4 bytes: this is not the length of the sid :-( */
1422 /*unknown = IVAL(pdata,0);*/
1424 if (!sid_parse(_in_data + 4, sid_len, &sid)) {
1425 return NT_STATUS_INVALID_PARAMETER;
1427 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1429 if (!sid_to_uid(&sid, &uid)) {
1430 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1431 sid_string_dbg(&sid),
1432 (unsigned long)sid_len));
1436 /* we can take a look at the find source :-)
1438 * find ./ -uid $uid -name '*' is what we need here
1441 * and send 4bytes len and then NULL terminated unicode strings
1444 * but I don't know how to deal with the paged results
1445 * (maybe we can hang the result anywhere in the fsp struct)
1447 * but I don't know how to deal with the paged results
1448 * (maybe we can hang the result anywhere in the fsp struct)
1450 * we don't send all files at once
1451 * and at the next we should *not* start from the beginning,
1452 * so we have to cache the result
1457 /* this works for now... */
1458 return NT_STATUS_OK;
1461 case FSCTL_QUERY_ALLOCATED_RANGES:
1463 /* FIXME: This is just a dummy reply, telling that all of the
1464 * file is allocated. MKS cp needs that.
1465 * Adding the real allocated ranges via FIEMAP on Linux
1466 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1467 * this FSCTL correct for sparse files.
1469 uint64_t offset, length;
1470 char *out_data_tmp = NULL;
1473 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1475 return NT_STATUS_INVALID_PARAMETER;
1478 if (max_out_len < 16) {
1479 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1481 return NT_STATUS_INVALID_PARAMETER;
1484 offset = BVAL(in_data,0);
1485 length = BVAL(in_data,8);
1487 if (offset + length < offset) {
1488 /* No 64-bit integer wrap. */
1489 return NT_STATUS_INVALID_PARAMETER;
1492 /* Shouldn't this be SMB_VFS_STAT ... ? */
1493 status = vfs_stat_fsp(fsp);
1494 if (!NT_STATUS_IS_OK(status)) {
1499 out_data_tmp = talloc_array(ctx, char, *out_len);
1500 if (out_data_tmp == NULL) {
1501 DEBUG(10, ("unable to allocate memory for response\n"));
1502 return NT_STATUS_NO_MEMORY;
1505 if (offset > fsp->fsp_name->st.st_ex_size ||
1506 fsp->fsp_name->st.st_ex_size == 0 ||
1508 memset(out_data_tmp, 0, *out_len);
1510 uint64_t end = offset + length;
1511 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1512 SBVAL(out_data_tmp, 0, 0);
1513 SBVAL(out_data_tmp, 8, end);
1516 *out_data = out_data_tmp;
1518 return NT_STATUS_OK;
1521 case FSCTL_IS_VOLUME_DIRTY:
1523 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1524 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1526 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1527 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1529 return NT_STATUS_INVALID_PARAMETER;
1534 * Only print once ... unfortunately there could be lots of
1535 * different FSCTLs that are called.
1537 if (!vfswrap_logged_ioctl_message) {
1538 vfswrap_logged_ioctl_message = true;
1539 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1540 __func__, function));
1544 return NT_STATUS_NOT_SUPPORTED;
1547 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1548 struct smb_filename *smb_fname,
1551 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1554 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1555 struct files_struct *fsp,
1558 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1561 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1562 const struct smb_filename *smb_fname,
1565 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1568 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1569 struct files_struct *fsp,
1572 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1575 struct vfs_cc_state {
1580 static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *handle,
1581 TALLOC_CTX *mem_ctx,
1582 struct tevent_context *ev,
1583 struct files_struct *src_fsp,
1585 struct files_struct *dest_fsp,
1589 struct tevent_req *req;
1590 struct vfs_cc_state *vfs_cc_state;
1593 DEBUG(10, ("performing server side copy chunk of length %lu\n",
1594 (unsigned long)num));
1596 req = tevent_req_create(mem_ctx, &vfs_cc_state, struct vfs_cc_state);
1601 vfs_cc_state->buf = talloc_array(vfs_cc_state, uint8_t,
1602 MIN(num, 8*1024*1024));
1603 if (tevent_req_nomem(vfs_cc_state->buf, req)) {
1604 return tevent_req_post(req, ev);
1607 status = vfs_stat_fsp(src_fsp);
1608 if (tevent_req_nterror(req, status)) {
1609 return tevent_req_post(req, ev);
1612 if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
1614 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1615 * If the SourceOffset or SourceOffset + Length extends beyond
1616 * the end of file, the server SHOULD<240> treat this as a
1617 * STATUS_END_OF_FILE error.
1619 * <240> Section 3.3.5.15.6: Windows servers will return
1620 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1622 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1623 return tevent_req_post(req, ev);
1626 /* could use 2.6.33+ sendfile here to do this in kernel */
1627 while (vfs_cc_state->copied < num) {
1629 struct lock_struct lck;
1632 off_t this_num = MIN(talloc_array_length(vfs_cc_state->buf),
1633 num - vfs_cc_state->copied);
1635 if (src_fsp->op == NULL) {
1636 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1637 return tevent_req_post(req, ev);
1639 init_strict_lock_struct(src_fsp,
1640 src_fsp->op->global->open_persistent_id,
1646 if (!SMB_VFS_STRICT_LOCK(src_fsp->conn, src_fsp, &lck)) {
1647 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1648 return tevent_req_post(req, ev);
1651 ret = SMB_VFS_PREAD(src_fsp, vfs_cc_state->buf,
1654 saved_errno = errno;
1657 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1660 errno = saved_errno;
1661 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1662 return tevent_req_post(req, ev);
1664 if (ret != this_num) {
1665 /* zero tolerance for short reads */
1666 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1667 return tevent_req_post(req, ev);
1672 if (dest_fsp->op == NULL) {
1673 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1674 return tevent_req_post(req, ev);
1677 init_strict_lock_struct(dest_fsp,
1678 dest_fsp->op->global->open_persistent_id,
1684 if (!SMB_VFS_STRICT_LOCK(dest_fsp->conn, dest_fsp, &lck)) {
1685 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1686 return tevent_req_post(req, ev);
1689 ret = SMB_VFS_PWRITE(dest_fsp, vfs_cc_state->buf,
1690 this_num, dest_off);
1692 saved_errno = errno;
1695 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1698 errno = saved_errno;
1699 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1700 return tevent_req_post(req, ev);
1702 if (ret != this_num) {
1703 /* zero tolerance for short writes */
1704 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1705 return tevent_req_post(req, ev);
1709 vfs_cc_state->copied += this_num;
1712 tevent_req_done(req);
1713 return tevent_req_post(req, ev);
1716 static NTSTATUS vfswrap_copy_chunk_recv(struct vfs_handle_struct *handle,
1717 struct tevent_req *req,
1720 struct vfs_cc_state *vfs_cc_state = tevent_req_data(req,
1721 struct vfs_cc_state);
1724 if (tevent_req_is_nterror(req, &status)) {
1725 DEBUG(2, ("server side copy chunk failed: %s\n",
1726 nt_errstr(status)));
1728 tevent_req_received(req);
1732 *copied = vfs_cc_state->copied;
1733 DEBUG(10, ("server side copy chunk copied %lu\n",
1734 (unsigned long)*copied));
1735 tevent_req_received(req);
1737 return NT_STATUS_OK;
1740 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1741 TALLOC_CTX *mem_ctx,
1742 struct files_struct *fsp,
1743 struct smb_filename *smb_fname,
1744 uint16_t *_compression_fmt)
1746 return NT_STATUS_INVALID_DEVICE_REQUEST;
1749 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1750 TALLOC_CTX *mem_ctx,
1751 struct files_struct *fsp,
1752 uint16_t compression_fmt)
1754 return NT_STATUS_INVALID_DEVICE_REQUEST;
1757 /********************************************************************
1758 Given a stat buffer return the allocated size on disk, taking into
1759 account sparse files.
1760 ********************************************************************/
1761 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1762 struct files_struct *fsp,
1763 const SMB_STRUCT_STAT *sbuf)
1767 START_PROFILE(syscall_get_alloc_size);
1769 if(S_ISDIR(sbuf->st_ex_mode)) {
1774 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1775 /* The type of st_blocksize is blkcnt_t which *MUST* be
1776 signed (according to POSIX) and can be less than 64-bits.
1777 Ensure when we're converting to 64 bits wide we don't
1779 #if defined(SIZEOF_BLKCNT_T_8)
1780 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1781 #elif defined(SIZEOF_BLKCNT_T_4)
1783 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1784 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1787 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1791 * Some file systems do not allocate a block for very
1792 * small files. But for non-empty file should report a
1796 uint64_t filesize = get_file_size_stat(sbuf);
1798 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
1802 result = get_file_size_stat(sbuf);
1805 if (fsp && fsp->initial_allocation_size)
1806 result = MAX(result,fsp->initial_allocation_size);
1808 result = smb_roundup(handle->conn, result);
1811 END_PROFILE(syscall_get_alloc_size);
1815 static int vfswrap_unlink(vfs_handle_struct *handle,
1816 const struct smb_filename *smb_fname)
1820 START_PROFILE(syscall_unlink);
1822 if (smb_fname->stream_name) {
1826 result = unlink(smb_fname->base_name);
1829 END_PROFILE(syscall_unlink);
1833 static int vfswrap_chmod(vfs_handle_struct *handle,
1834 const struct smb_filename *smb_fname,
1839 START_PROFILE(syscall_chmod);
1842 * We need to do this due to the fact that the default POSIX ACL
1843 * chmod modifies the ACL *mask* for the group owner, not the
1844 * group owner bits directly. JRA.
1849 int saved_errno = errno; /* We might get ENOSYS */
1850 result = SMB_VFS_CHMOD_ACL(handle->conn,
1854 END_PROFILE(syscall_chmod);
1857 /* Error - return the old errno. */
1858 errno = saved_errno;
1861 result = chmod(smb_fname->base_name, mode);
1862 END_PROFILE(syscall_chmod);
1866 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
1870 START_PROFILE(syscall_fchmod);
1873 * We need to do this due to the fact that the default POSIX ACL
1874 * chmod modifies the ACL *mask* for the group owner, not the
1875 * group owner bits directly. JRA.
1879 int saved_errno = errno; /* We might get ENOSYS */
1880 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
1881 END_PROFILE(syscall_fchmod);
1884 /* Error - return the old errno. */
1885 errno = saved_errno;
1888 #if defined(HAVE_FCHMOD)
1889 result = fchmod(fsp->fh->fd, mode);
1895 END_PROFILE(syscall_fchmod);
1899 static int vfswrap_chown(vfs_handle_struct *handle,
1900 const struct smb_filename *smb_fname,
1906 START_PROFILE(syscall_chown);
1907 result = chown(smb_fname->base_name, uid, gid);
1908 END_PROFILE(syscall_chown);
1912 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
1917 START_PROFILE(syscall_fchown);
1918 result = fchown(fsp->fh->fd, uid, gid);
1919 END_PROFILE(syscall_fchown);
1927 static int vfswrap_lchown(vfs_handle_struct *handle,
1928 const struct smb_filename *smb_fname,
1934 START_PROFILE(syscall_lchown);
1935 result = lchown(smb_fname->base_name, uid, gid);
1936 END_PROFILE(syscall_lchown);
1940 static int vfswrap_chdir(vfs_handle_struct *handle, const char *path)
1944 START_PROFILE(syscall_chdir);
1945 result = chdir(path);
1946 END_PROFILE(syscall_chdir);
1950 static char *vfswrap_getwd(vfs_handle_struct *handle)
1954 START_PROFILE(syscall_getwd);
1955 result = sys_getwd();
1956 END_PROFILE(syscall_getwd);
1960 /*********************************************************************
1961 nsec timestamp resolution call. Convert down to whatever the underlying
1962 system will support.
1963 **********************************************************************/
1965 static int vfswrap_ntimes(vfs_handle_struct *handle,
1966 const struct smb_filename *smb_fname,
1967 struct smb_file_time *ft)
1971 START_PROFILE(syscall_ntimes);
1973 if (smb_fname->stream_name) {
1979 if (null_timespec(ft->atime)) {
1980 ft->atime= smb_fname->st.st_ex_atime;
1983 if (null_timespec(ft->mtime)) {
1984 ft->mtime = smb_fname->st.st_ex_mtime;
1987 if (!null_timespec(ft->create_time)) {
1988 set_create_timespec_ea(handle->conn,
1993 if ((timespec_compare(&ft->atime,
1994 &smb_fname->st.st_ex_atime) == 0) &&
1995 (timespec_compare(&ft->mtime,
1996 &smb_fname->st.st_ex_mtime) == 0)) {
2001 #if defined(HAVE_UTIMENSAT)
2003 struct timespec ts[2];
2006 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2008 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2010 if (!((result == -1) && (errno == ENOSYS))) {
2014 #if defined(HAVE_UTIMES)
2016 struct timeval tv[2];
2017 tv[0] = convert_timespec_to_timeval(ft->atime);
2018 tv[1] = convert_timespec_to_timeval(ft->mtime);
2019 result = utimes(smb_fname->base_name, tv);
2021 result = utimes(smb_fname->base_name, NULL);
2023 if (!((result == -1) && (errno == ENOSYS))) {
2027 #if defined(HAVE_UTIME)
2029 struct utimbuf times;
2030 times.actime = convert_timespec_to_time_t(ft->atime);
2031 times.modtime = convert_timespec_to_time_t(ft->mtime);
2032 result = utime(smb_fname->base_name, ×);
2034 result = utime(smb_fname->base_name, NULL);
2036 if (!((result == -1) && (errno == ENOSYS))) {
2044 END_PROFILE(syscall_ntimes);
2048 /*********************************************************************
2049 A version of ftruncate that will write the space on disk if strict
2051 **********************************************************************/
2053 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2055 off_t space_to_write;
2056 uint64_t space_avail;
2057 uint64_t bsize,dfree,dsize;
2060 SMB_STRUCT_STAT *pst;
2062 status = vfs_stat_fsp(fsp);
2063 if (!NT_STATUS_IS_OK(status)) {
2066 pst = &fsp->fsp_name->st;
2069 if (S_ISFIFO(pst->st_ex_mode))
2073 if (pst->st_ex_size == len)
2076 /* Shrink - just ftruncate. */
2077 if (pst->st_ex_size > len)
2078 return ftruncate(fsp->fh->fd, len);
2080 space_to_write = len - pst->st_ex_size;
2082 /* for allocation try fallocate first. This can fail on some
2083 platforms e.g. when the filesystem doesn't support it and no
2084 emulation is being done by the libc (like on AIX with JFS1). In that
2085 case we do our own emulation. fallocate implementations can
2086 return ENOTSUP or EINVAL in cases like that. */
2087 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2088 if (ret == -1 && errno == ENOSPC) {
2094 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2095 "error %d. Falling back to slow manual allocation\n", errno));
2097 /* available disk space is enough or not? */
2099 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2100 /* space_avail is 1k blocks */
2101 if (space_avail == (uint64_t)-1 ||
2102 ((uint64_t)space_to_write/1024 > space_avail) ) {
2107 /* Write out the real space on disk. */
2108 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2116 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2119 SMB_STRUCT_STAT *pst;
2123 START_PROFILE(syscall_ftruncate);
2125 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2126 result = strict_allocate_ftruncate(handle, fsp, len);
2127 END_PROFILE(syscall_ftruncate);
2131 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2132 ftruncate if the system supports it. Then I discovered that
2133 you can have some filesystems that support ftruncate
2134 expansion and some that don't! On Linux fat can't do
2135 ftruncate extend but ext2 can. */
2137 result = ftruncate(fsp->fh->fd, len);
2139 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2140 extend a file with ftruncate. Provide alternate implementation
2143 /* Do an fstat to see if the file is longer than the requested
2144 size in which case the ftruncate above should have
2145 succeeded or shorter, in which case seek to len - 1 and
2146 write 1 byte of zero */
2147 status = vfs_stat_fsp(fsp);
2148 if (!NT_STATUS_IS_OK(status)) {
2152 /* We need to update the files_struct after successful ftruncate */
2157 pst = &fsp->fsp_name->st;
2160 if (S_ISFIFO(pst->st_ex_mode)) {
2166 if (pst->st_ex_size == len) {
2171 if (pst->st_ex_size > len) {
2172 /* the ftruncate should have worked */
2176 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2184 END_PROFILE(syscall_ftruncate);
2188 static int vfswrap_fallocate(vfs_handle_struct *handle,
2196 START_PROFILE(syscall_fallocate);
2198 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2200 * posix_fallocate returns 0 on success, errno on error
2201 * and doesn't set errno. Make it behave like fallocate()
2202 * which returns -1, and sets errno on failure.
2209 /* sys_fallocate handles filtering of unsupported mode flags */
2210 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2212 END_PROFILE(syscall_fallocate);
2216 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2220 START_PROFILE(syscall_fcntl_lock);
2222 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2224 "force process locks",
2226 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2229 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2230 END_PROFILE(syscall_fcntl_lock);
2234 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2235 uint32_t share_mode, uint32_t access_mask)
2237 START_PROFILE(syscall_kernel_flock);
2238 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2239 END_PROFILE(syscall_kernel_flock);
2243 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2248 START_PROFILE(syscall_fcntl_getlock);
2250 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2252 "force process locks",
2254 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2257 result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2258 END_PROFILE(syscall_fcntl_getlock);
2262 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2267 START_PROFILE(syscall_linux_setlease);
2269 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2270 result = linux_setlease(fsp->fh->fd, leasetype);
2274 END_PROFILE(syscall_linux_setlease);
2278 static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2282 START_PROFILE(syscall_symlink);
2283 result = symlink(oldpath, newpath);
2284 END_PROFILE(syscall_symlink);
2288 static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
2292 START_PROFILE(syscall_readlink);
2293 result = readlink(path, buf, bufsiz);
2294 END_PROFILE(syscall_readlink);
2298 static int vfswrap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2302 START_PROFILE(syscall_link);
2303 result = link(oldpath, newpath);
2304 END_PROFILE(syscall_link);
2308 static int vfswrap_mknod(vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev)
2312 START_PROFILE(syscall_mknod);
2313 result = sys_mknod(pathname, mode, dev);
2314 END_PROFILE(syscall_mknod);
2318 static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
2322 START_PROFILE(syscall_realpath);
2323 result = sys_realpath(path);
2324 END_PROFILE(syscall_realpath);
2328 static int vfswrap_chflags(vfs_handle_struct *handle, const char *path,
2332 return chflags(path, flags);
2339 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2340 const SMB_STRUCT_STAT *sbuf)
2344 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2348 key.devid = sbuf->st_ex_dev;
2349 key.inode = sbuf->st_ex_ino;
2350 /* key.extid is unused by default. */
2355 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2356 struct files_struct *fsp,
2357 const struct smb_filename *smb_fname,
2358 TALLOC_CTX *mem_ctx,
2359 unsigned int *pnum_streams,
2360 struct stream_struct **pstreams)
2362 SMB_STRUCT_STAT sbuf;
2363 struct stream_struct *tmp_streams = NULL;
2366 if ((fsp != NULL) && (fsp->is_directory)) {
2368 * No default streams on directories
2373 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2374 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2377 struct smb_filename smb_fname_cp;
2379 ZERO_STRUCT(smb_fname_cp);
2380 smb_fname_cp.base_name = discard_const_p(char,
2381 smb_fname->base_name);
2382 smb_fname_cp.flags = smb_fname->flags;
2384 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
2385 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2387 ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2389 sbuf = smb_fname_cp.st;
2393 return map_nt_error_from_unix(errno);
2396 if (S_ISDIR(sbuf.st_ex_mode)) {
2400 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2401 (*pnum_streams) + 1);
2402 if (tmp_streams == NULL) {
2403 return NT_STATUS_NO_MEMORY;
2405 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2406 if (tmp_streams[*pnum_streams].name == NULL) {
2407 return NT_STATUS_NO_MEMORY;
2409 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2410 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2413 *pstreams = tmp_streams;
2415 return NT_STATUS_OK;
2418 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2421 TALLOC_CTX *mem_ctx,
2425 * Don't fall back to get_real_filename so callers can differentiate
2426 * between a full directory scan and an actual case-insensitive stat.
2432 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2435 return handle->conn->connectpath;
2438 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2439 struct byte_range_lock *br_lck,
2440 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_windows_default(br_lck, plock, blocking_lock);
2449 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2450 struct messaging_context *msg_ctx,
2451 struct byte_range_lock *br_lck,
2452 const struct lock_struct *plock)
2454 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2456 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2459 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2460 struct byte_range_lock *br_lck,
2461 struct lock_struct *plock)
2463 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2465 /* Note: blr is not used in the default implementation. */
2466 return brl_lock_cancel_default(br_lck, plock);
2469 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2471 struct lock_struct *plock)
2473 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2474 plock->lock_type == WRITE_LOCK);
2476 return strict_lock_default(fsp, plock);
2479 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2481 struct lock_struct *plock)
2483 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2484 plock->lock_type == WRITE_LOCK);
2486 strict_unlock_default(fsp, plock);
2489 /* NT ACL operations. */
2491 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2493 uint32_t security_info,
2494 TALLOC_CTX *mem_ctx,
2495 struct security_descriptor **ppdesc)
2499 START_PROFILE(fget_nt_acl);
2500 result = posix_fget_nt_acl(fsp, security_info,
2502 END_PROFILE(fget_nt_acl);
2506 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2507 const struct smb_filename *smb_fname,
2508 uint32_t security_info,
2509 TALLOC_CTX *mem_ctx,
2510 struct security_descriptor **ppdesc)
2514 START_PROFILE(get_nt_acl);
2515 result = posix_get_nt_acl(handle->conn,
2520 END_PROFILE(get_nt_acl);
2524 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2528 START_PROFILE(fset_nt_acl);
2529 result = set_nt_acl(fsp, security_info_sent, psd);
2530 END_PROFILE(fset_nt_acl);
2534 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2535 struct smb_filename *file,
2536 struct security_acl *sacl,
2537 uint32_t access_requested,
2538 uint32_t access_denied)
2540 return NT_STATUS_OK; /* Nothing to do here ... */
2543 static int vfswrap_chmod_acl(vfs_handle_struct *handle,
2544 const struct smb_filename *smb_fname,
2553 START_PROFILE(chmod_acl);
2554 result = chmod_acl(handle->conn, smb_fname->base_name, mode);
2555 END_PROFILE(chmod_acl);
2560 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2568 START_PROFILE(fchmod_acl);
2569 result = fchmod_acl(fsp, mode);
2570 END_PROFILE(fchmod_acl);
2575 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2577 SMB_ACL_TYPE_T type,
2578 TALLOC_CTX *mem_ctx)
2580 return sys_acl_get_file(handle, path_p, type, mem_ctx);
2583 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2585 TALLOC_CTX *mem_ctx)
2587 return sys_acl_get_fd(handle, fsp, mem_ctx);
2590 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2592 return sys_acl_set_file(handle, name, acltype, theacl);
2595 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2597 return sys_acl_set_fd(handle, fsp, theacl);
2600 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
2602 return sys_acl_delete_def_file(handle, path);
2605 /****************************************************************
2606 Extended attribute operations.
2607 *****************************************************************/
2609 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
2611 return getxattr(path, name, value, size);
2614 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2616 return fgetxattr(fsp->fh->fd, name, value, size);
2619 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
2621 return listxattr(path, list, size);
2624 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2626 return flistxattr(fsp->fh->fd, list, size);
2629 static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
2631 return removexattr(path, name);
2634 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2636 return fremovexattr(fsp->fh->fd, name);
2639 static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
2641 return setxattr(path, name, value, size, flags);
2644 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2646 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2649 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2654 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2655 const struct smb_filename *fname,
2656 SMB_STRUCT_STAT *sbuf)
2660 bool offline = false;
2662 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2666 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2667 #if defined(ENOTSUP)
2673 status = get_full_smb_filename(talloc_tos(), fname, &path);
2674 if (!NT_STATUS_IS_OK(status)) {
2675 errno = map_errno_from_nt_status(status);
2679 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2686 static int vfswrap_set_offline(struct vfs_handle_struct *handle,
2687 const struct smb_filename *fname)
2689 /* We don't know how to set offline bit by default, needs to be overriden in the vfs modules */
2690 #if defined(ENOTSUP)
2696 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2697 struct files_struct *fsp,
2698 TALLOC_CTX *mem_ctx,
2701 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2704 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2705 struct files_struct *fsp,
2706 const DATA_BLOB old_cookie,
2707 TALLOC_CTX *mem_ctx,
2708 DATA_BLOB *new_cookie)
2710 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2714 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2715 struct smb_request *smb1req,
2716 struct smbXsrv_open *op,
2717 const DATA_BLOB old_cookie,
2718 TALLOC_CTX *mem_ctx,
2719 struct files_struct **fsp,
2720 DATA_BLOB *new_cookie)
2722 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2723 old_cookie, mem_ctx,
2727 static struct vfs_fn_pointers vfs_default_fns = {
2728 /* Disk operations */
2730 .connect_fn = vfswrap_connect,
2731 .disconnect_fn = vfswrap_disconnect,
2732 .disk_free_fn = vfswrap_disk_free,
2733 .get_quota_fn = vfswrap_get_quota,
2734 .set_quota_fn = vfswrap_set_quota,
2735 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2736 .statvfs_fn = vfswrap_statvfs,
2737 .fs_capabilities_fn = vfswrap_fs_capabilities,
2738 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2739 .snap_check_path_fn = vfswrap_snap_check_path,
2740 .snap_create_fn = vfswrap_snap_create,
2741 .snap_delete_fn = vfswrap_snap_delete,
2743 /* Directory operations */
2745 .opendir_fn = vfswrap_opendir,
2746 .fdopendir_fn = vfswrap_fdopendir,
2747 .readdir_fn = vfswrap_readdir,
2748 .readdir_attr_fn = vfswrap_readdir_attr,
2749 .seekdir_fn = vfswrap_seekdir,
2750 .telldir_fn = vfswrap_telldir,
2751 .rewind_dir_fn = vfswrap_rewinddir,
2752 .mkdir_fn = vfswrap_mkdir,
2753 .rmdir_fn = vfswrap_rmdir,
2754 .closedir_fn = vfswrap_closedir,
2755 .init_search_op_fn = vfswrap_init_search_op,
2757 /* File operations */
2759 .open_fn = vfswrap_open,
2760 .create_file_fn = vfswrap_create_file,
2761 .close_fn = vfswrap_close,
2762 .read_fn = vfswrap_read,
2763 .pread_fn = vfswrap_pread,
2764 .pread_send_fn = vfswrap_pread_send,
2765 .pread_recv_fn = vfswrap_pread_recv,
2766 .write_fn = vfswrap_write,
2767 .pwrite_fn = vfswrap_pwrite,
2768 .pwrite_send_fn = vfswrap_pwrite_send,
2769 .pwrite_recv_fn = vfswrap_pwrite_recv,
2770 .lseek_fn = vfswrap_lseek,
2771 .sendfile_fn = vfswrap_sendfile,
2772 .recvfile_fn = vfswrap_recvfile,
2773 .rename_fn = vfswrap_rename,
2774 .fsync_fn = vfswrap_fsync,
2775 .fsync_send_fn = vfswrap_fsync_send,
2776 .fsync_recv_fn = vfswrap_fsync_recv,
2777 .stat_fn = vfswrap_stat,
2778 .fstat_fn = vfswrap_fstat,
2779 .lstat_fn = vfswrap_lstat,
2780 .get_alloc_size_fn = vfswrap_get_alloc_size,
2781 .unlink_fn = vfswrap_unlink,
2782 .chmod_fn = vfswrap_chmod,
2783 .fchmod_fn = vfswrap_fchmod,
2784 .chown_fn = vfswrap_chown,
2785 .fchown_fn = vfswrap_fchown,
2786 .lchown_fn = vfswrap_lchown,
2787 .chdir_fn = vfswrap_chdir,
2788 .getwd_fn = vfswrap_getwd,
2789 .ntimes_fn = vfswrap_ntimes,
2790 .ftruncate_fn = vfswrap_ftruncate,
2791 .fallocate_fn = vfswrap_fallocate,
2792 .lock_fn = vfswrap_lock,
2793 .kernel_flock_fn = vfswrap_kernel_flock,
2794 .linux_setlease_fn = vfswrap_linux_setlease,
2795 .getlock_fn = vfswrap_getlock,
2796 .symlink_fn = vfswrap_symlink,
2797 .readlink_fn = vfswrap_readlink,
2798 .link_fn = vfswrap_link,
2799 .mknod_fn = vfswrap_mknod,
2800 .realpath_fn = vfswrap_realpath,
2801 .chflags_fn = vfswrap_chflags,
2802 .file_id_create_fn = vfswrap_file_id_create,
2803 .streaminfo_fn = vfswrap_streaminfo,
2804 .get_real_filename_fn = vfswrap_get_real_filename,
2805 .connectpath_fn = vfswrap_connectpath,
2806 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2807 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2808 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2809 .strict_lock_fn = vfswrap_strict_lock,
2810 .strict_unlock_fn = vfswrap_strict_unlock,
2811 .translate_name_fn = vfswrap_translate_name,
2812 .fsctl_fn = vfswrap_fsctl,
2813 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
2814 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
2815 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
2816 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
2817 .copy_chunk_send_fn = vfswrap_copy_chunk_send,
2818 .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
2819 .get_compression_fn = vfswrap_get_compression,
2820 .set_compression_fn = vfswrap_set_compression,
2822 /* NT ACL operations. */
2824 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2825 .get_nt_acl_fn = vfswrap_get_nt_acl,
2826 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2827 .audit_file_fn = vfswrap_audit_file,
2829 /* POSIX ACL operations. */
2831 .chmod_acl_fn = vfswrap_chmod_acl,
2832 .fchmod_acl_fn = vfswrap_fchmod_acl,
2834 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2835 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2836 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2837 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2838 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2839 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2840 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2842 /* EA operations. */
2843 .getxattr_fn = vfswrap_getxattr,
2844 .fgetxattr_fn = vfswrap_fgetxattr,
2845 .listxattr_fn = vfswrap_listxattr,
2846 .flistxattr_fn = vfswrap_flistxattr,
2847 .removexattr_fn = vfswrap_removexattr,
2848 .fremovexattr_fn = vfswrap_fremovexattr,
2849 .setxattr_fn = vfswrap_setxattr,
2850 .fsetxattr_fn = vfswrap_fsetxattr,
2852 /* aio operations */
2853 .aio_force_fn = vfswrap_aio_force,
2855 /* offline operations */
2856 .is_offline_fn = vfswrap_is_offline,
2857 .set_offline_fn = vfswrap_set_offline,
2859 /* durable handle operations */
2860 .durable_cookie_fn = vfswrap_durable_cookie,
2861 .durable_disconnect_fn = vfswrap_durable_disconnect,
2862 .durable_reconnect_fn = vfswrap_durable_reconnect,
2865 NTSTATUS vfs_default_init(void);
2866 NTSTATUS vfs_default_init(void)
2868 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
2869 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);